autocomplete_controller.h revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CONTROLLER_H_ 6#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CONTROLLER_H_ 7 8#include "base/basictypes.h" 9#include "base/compiler_specific.h" 10#include "base/gtest_prod_util.h" 11#include "base/strings/string16.h" 12#include "base/time/time.h" 13#include "base/timer/timer.h" 14#include "chrome/browser/autocomplete/autocomplete_input.h" 15#include "chrome/browser/autocomplete/autocomplete_provider.h" 16#include "chrome/browser/autocomplete/autocomplete_provider_listener.h" 17#include "chrome/browser/autocomplete/autocomplete_result.h" 18 19class AutocompleteControllerDelegate; 20class HistoryURLProvider; 21class KeywordProvider; 22class Profile; 23class SearchProvider; 24class ZeroSuggestProvider; 25 26// The AutocompleteController is the center of the autocomplete system. A 27// class creates an instance of the controller, which in turn creates a set of 28// AutocompleteProviders to serve it. The owning class can ask the controller 29// to Start() a query; the controller in turn passes this call down to the 30// providers, each of which keeps track of its own matches and whether it has 31// finished processing the query. When a provider gets more matches or finishes 32// processing, it notifies the controller, which merges the combined matches 33// together and makes the result available to interested observers. 34// 35// The owner may also cancel the current query by calling Stop(), which the 36// controller will in turn communicate to all the providers. No callbacks will 37// happen after a request has been stopped. 38// 39// IMPORTANT: There is NO THREAD SAFETY built into this portion of the 40// autocomplete system. All calls to and from the AutocompleteController should 41// happen on the same thread. AutocompleteProviders are responsible for doing 42// their own thread management when they need to return matches asynchronously. 43// 44// The coordinator for autocomplete queries, responsible for combining the 45// matches from a series of providers into one AutocompleteResult. 46class AutocompleteController : public AutocompleteProviderListener { 47 public: 48 // Used to indicate an index that is not selected in a call to Update(). 49 static const int kNoItemSelected; 50 51 // |provider_types| is a bitmap containing AutocompleteProvider::Type values 52 // that will (potentially, depending on platform, flags, etc.) be 53 // instantiated. 54 AutocompleteController(Profile* profile, 55 AutocompleteControllerDelegate* delegate, 56 int provider_types); 57 ~AutocompleteController(); 58 59 // Starts an autocomplete query, which continues until all providers are 60 // done or the query is Stop()ed. It is safe to Start() a new query without 61 // Stop()ing the previous one. 62 // 63 // See AutocompleteInput::AutocompleteInput(...) for more details regarding 64 // |input| params. 65 // 66 // The controller calls AutocompleteControllerDelegate::OnResultChanged() from 67 // inside this call at least once. If matches are available later on that 68 // result in changing the result set the delegate is notified again. When the 69 // controller is done the notification AUTOCOMPLETE_CONTROLLER_RESULT_READY is 70 // sent. 71 void Start(const AutocompleteInput& input); 72 73 // Cancels the current query, ensuring there will be no future notifications 74 // fired. If new matches have come in since the most recent notification was 75 // fired, they will be discarded. 76 // 77 // If |clear_result| is true, the controller will also erase the result set. 78 void Stop(bool clear_result); 79 80 // Begin asynchronously fetching zero-suggest suggestions for |url|. 81 // |user_text| is the text entered in the omnibox, which may be non-empty if 82 // the user previously focused in the omnibox during this interaction. 83 // |permanent_text| is the omnibox text for the current page. 84 // TODO(jered): Rip out |user_text| once the first match is decoupled from 85 // the current typing in the omnibox. 86 void StartZeroSuggest(const GURL& url, 87 const string16& permanent_text); 88 89 // Cancels any pending zero-suggest fetch. 90 void StopZeroSuggest(); 91 92 // Asks the relevant provider to delete |match|, and ensures observers are 93 // notified of resulting changes immediately. This should only be called when 94 // no query is running. 95 void DeleteMatch(const AutocompleteMatch& match); 96 97 // Removes any entries that were copied from the last result. This is used by 98 // the popup to ensure it's not showing an out-of-date query. 99 void ExpireCopiedEntries(); 100 101 // AutocompleteProviderListener: 102 virtual void OnProviderUpdate(bool updated_matches) OVERRIDE; 103 104 // Called when an omnibox event log entry is generated. 105 // Populates provider_info with diagnostic information about the status 106 // of various providers. In turn, calls 107 // AutocompleteProvider::AddProviderInfo() so each provider can add 108 // provider-specific information, information we want to log for a particular 109 // provider but not others. 110 void AddProvidersInfo(ProvidersInfo* provider_info) const; 111 112 // Called when a new omnibox session starts. 113 // We start a new session when the user first begins modifying the omnibox 114 // content; see |OmniboxEditModel::user_input_in_progress_|. 115 void ResetSession(); 116 117 // Constructs the final destination URL for a given match using additional 118 // parameters otherwise not available at initial construction time. This 119 // method should be called from OmniboxEditModel::OpenMatch() before the user 120 // navigates to the selected match. 121 GURL GetDestinationURL(const AutocompleteMatch& match, 122 base::TimeDelta query_formulation_time) const; 123 124 HistoryURLProvider* history_url_provider() const { 125 return history_url_provider_; 126 } 127 KeywordProvider* keyword_provider() const { return keyword_provider_; } 128 SearchProvider* search_provider() const { return search_provider_; } 129 130 const AutocompleteInput& input() const { return input_; } 131 const AutocompleteResult& result() const { return result_; } 132 bool done() const { return done_; } 133 const ACProviders* providers() const { return &providers_; } 134 135 const base::TimeTicks& last_time_default_match_changed() const { 136 return last_time_default_match_changed_; 137 } 138 139 private: 140 friend class AutocompleteProviderTest; 141 FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, 142 RedundantKeywordsIgnoredInResult); 143 FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, UpdateAssistedQueryStats); 144 FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, GetDestinationURL); 145 146 // Updates |result_| to reflect the current provider state and fires 147 // notifications. If |regenerate_result| then we clear the result 148 // so when we incorporate the current provider state we end up 149 // implicitly removing all expired matches. (Normally we allow 150 // matches from the previous result set carry over. These stale 151 // results may outrank legitimate matches from the current result 152 // set. Sometimes we just want the current matches; the easier way 153 // to do this is to throw everything out and reconstruct the result 154 // set from the providers' current data.) 155 // If |force_notify_default_match_changed|, we tell NotifyChanged 156 // the default match has changed even if it hasn't. This is 157 // necessary in some cases; for instance, if the user typed a new 158 // character, the edit model needs to repaint (highlighting changed) 159 // even if the default match didn't change. 160 void UpdateResult(bool regenerate_result, 161 bool force_notify_default_match_changed); 162 163 // Updates |result| to populate each match's |associated_keyword| if that 164 // match can show a keyword hint. |result| should be sorted by 165 // relevance before this is called. 166 void UpdateAssociatedKeywords(AutocompleteResult* result); 167 168 // For each group of contiguous matches from the same TemplateURL, show the 169 // provider name as a description on the first match in the group. 170 void UpdateKeywordDescriptions(AutocompleteResult* result); 171 172 // For each AutocompleteMatch returned by SearchProvider, updates the 173 // destination_url iff the provider's TemplateURL supports assisted query 174 // stats. 175 void UpdateAssistedQueryStats(AutocompleteResult* result); 176 177 // Calls AutocompleteControllerDelegate::OnResultChanged() and if done sends 178 // AUTOCOMPLETE_CONTROLLER_RESULT_READY. 179 void NotifyChanged(bool notify_default_match); 180 181 // Updates |done_| to be accurate with respect to current providers' statuses. 182 void CheckIfDone(); 183 184 // Starts |expire_timer_|. 185 void StartExpireTimer(); 186 187 // Starts |stop_timer_|. 188 void StartStopTimer(); 189 190 AutocompleteControllerDelegate* delegate_; 191 192 // A list of all providers. 193 ACProviders providers_; 194 195 HistoryURLProvider* history_url_provider_; 196 197 KeywordProvider* keyword_provider_; 198 199 SearchProvider* search_provider_; 200 201 ZeroSuggestProvider* zero_suggest_provider_; 202 203 // Input passed to Start. 204 AutocompleteInput input_; 205 206 // Data from the autocomplete query. 207 AutocompleteResult result_; 208 209 // The most recent time the default match (inline match) changed. This may 210 // be earlier than the most recent keystroke if the recent keystrokes didn't 211 // change the suggested match in the omnibox. (For instance, if 212 // a user typed "mail.goog" and the match https://mail.google.com/ was 213 // the destination match ever since the user typed "ma" then this is 214 // the time that URL first appeared as the default match.) This may 215 // also be more recent than the last keystroke if there was an 216 // asynchronous provider that returned and changed the default 217 // match. See UpdateResult() for details on when we consider a 218 // match to have changed. 219 base::TimeTicks last_time_default_match_changed_; 220 221 // Timer used to remove any matches copied from the last result. When run 222 // invokes |ExpireCopiedEntries|. 223 base::OneShotTimer<AutocompleteController> expire_timer_; 224 225 // Timer used to tell the providers to Stop() searching for matches. 226 base::OneShotTimer<AutocompleteController> stop_timer_; 227 228 // True if the user is in the "stop timer" field trial. If so, the 229 // controller uses the |stop_timer_|. 230 const bool in_stop_timer_field_trial_; 231 232 // True if a query is not currently running. 233 bool done_; 234 235 // Are we in Start()? This is used to avoid updating |result_| and sending 236 // notifications until Start() has been invoked on all providers. 237 bool in_start_; 238 239 // Has StartZeroSuggest() been called but not Start()? 240 bool in_zero_suggest_; 241 242 Profile* profile_; 243 244 DISALLOW_COPY_AND_ASSIGN(AutocompleteController); 245}; 246 247#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CONTROLLER_H_ 248