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