autocomplete_controller.h revision 116680a4aac90f2aa7413d9095a592090648e557
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CONTROLLER_H_ 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CONTROLLER_H_ 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h" 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/compiler_specific.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/gtest_prod_util.h" 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/ref_counted.h" 1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/strings/string16.h" 13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/timer/timer.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_provider.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_provider_listener.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_result.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/autocomplete/autocomplete_input.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class AutocompleteControllerDelegate; 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class HistoryURLProvider; 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class KeywordProvider; 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class Profile; 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class SearchProvider; 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class TemplateURLService; 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ZeroSuggestProvider; 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The AutocompleteController is the center of the autocomplete system. A 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// class creates an instance of the controller, which in turn creates a set of 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// AutocompleteProviders to serve it. The owning class can ask the controller 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// to Start() a query; the controller in turn passes this call down to the 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// providers, each of which keeps track of its own matches and whether it has 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// finished processing the query. When a provider gets more matches or finishes 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// processing, it notifies the controller, which merges the combined matches 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// together and makes the result available to interested observers. 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The owner may also cancel the current query by calling Stop(), which the 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// controller will in turn communicate to all the providers. No callbacks will 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// happen after a request has been stopped. 40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// IMPORTANT: There is NO THREAD SAFETY built into this portion of the 42868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// autocomplete system. All calls to and from the AutocompleteController should 43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// happen on the same thread. AutocompleteProviders are responsible for doing 44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// their own thread management when they need to return matches asynchronously. 45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The coordinator for autocomplete queries, responsible for combining the 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// matches from a series of providers into one AutocompleteResult. 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class AutocompleteController : public AutocompleteProviderListener { 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public: 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) typedef std::vector<scoped_refptr<AutocompleteProvider> > Providers; 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // |provider_types| is a bitmap containing AutocompleteProvider::Type values 5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // that will (potentially, depending on platform, flags, etc.) be 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // instantiated. |template_url_service| is used to create URLs from the 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // autocomplete results. 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AutocompleteController(Profile* profile, 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) TemplateURLService* template_url_service, 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AutocompleteControllerDelegate* delegate, 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int provider_types); 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ~AutocompleteController(); 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Starts an autocomplete query, which continues until all providers are 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // done or the query is Stop()ed. It is safe to Start() a new query without 6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Stop()ing the previous one. 6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // See AutocompleteInput::AutocompleteInput(...) for more details regarding 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // |input| params. 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The controller calls AutocompleteControllerDelegate::OnResultChanged() from 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // inside this call at least once. If matches are available later on that 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // result in changing the result set the delegate is notified again. When the 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // controller is done the notification AUTOCOMPLETE_CONTROLLER_RESULT_READY is 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // sent. 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void Start(const AutocompleteInput& input); 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Cancels the current query, ensuring there will be no future notifications 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // fired. If new matches have come in since the most recent notification was 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // fired, they will be discarded. 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // If |clear_result| is true, the controller will also erase the result set. 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void Stop(bool clear_result); 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Begin asynchronous fetch of zero-suggest suggestions. The |input| should 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // contain current omnibox input, the URL of the page we are on, and 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // that page's classification. 86a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) void StartZeroSuggest(const AutocompleteInput& input); 87a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Asks the relevant provider to delete |match|, and ensures observers are 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // notified of resulting changes immediately. This should only be called when 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // no query is running. 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void DeleteMatch(const AutocompleteMatch& match); 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Removes any entries that were copied from the last result. This is used by 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // the popup to ensure it's not showing an out-of-date query. 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void ExpireCopiedEntries(); 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // AutocompleteProviderListener: 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual void OnProviderUpdate(bool updated_matches) OVERRIDE; 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Called when an omnibox event log entry is generated. 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // 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 UpdateMatchDestinationURL(base::TimeDelta query_formulation_time, 118 AutocompleteMatch* match) const; 119 120 HistoryURLProvider* history_url_provider() const { 121 return history_url_provider_; 122 } 123 KeywordProvider* keyword_provider() const { return keyword_provider_; } 124 SearchProvider* search_provider() const { return search_provider_; } 125 126 // Deprecated. Do not use that method! It's provided temporarily as clank 127 // migrates. If you need to access the aucomplete input you should keep a 128 // local copy of it. 129 // TODO(beaudoin): Remove this method once clank no longer rely on it. 130 // crbug.com/367832 131 const AutocompleteInput& input() const { return input_; } 132 133 const AutocompleteResult& result() const { return result_; } 134 bool done() const { return done_; } 135 const Providers& providers() const { return providers_; } 136 137 const base::TimeTicks& last_time_default_match_changed() const { 138 return last_time_default_match_changed_; 139 } 140 141 private: 142 friend class AutocompleteProviderTest; 143 FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, 144 RedundantKeywordsIgnoredInResult); 145 FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, UpdateAssistedQueryStats); 146 FRIEND_TEST_ALL_PREFIXES(AutocompleteProviderTest, GetDestinationURL); 147 FRIEND_TEST_ALL_PREFIXES(OmniboxViewTest, DoesNotUpdateAutocompleteOnBlur); 148 FRIEND_TEST_ALL_PREFIXES(OmniboxViewViewsTest, CloseOmniboxPopupOnTextDrag); 149 150 // Updates |result_| to reflect the current provider state and fires 151 // notifications. If |regenerate_result| then we clear the result 152 // so when we incorporate the current provider state we end up 153 // implicitly removing all expired matches. (Normally we allow 154 // matches from the previous result set carry over. These stale 155 // results may outrank legitimate matches from the current result 156 // set. Sometimes we just want the current matches; the easier way 157 // to do this is to throw everything out and reconstruct the result 158 // set from the providers' current data.) 159 // If |force_notify_default_match_changed|, we tell NotifyChanged 160 // the default match has changed even if it hasn't. This is 161 // necessary in some cases; for instance, if the user typed a new 162 // character, the edit model needs to repaint (highlighting changed) 163 // even if the default match didn't change. 164 void UpdateResult(bool regenerate_result, 165 bool force_notify_default_match_changed); 166 167 // Updates |result| to populate each match's |associated_keyword| if that 168 // match can show a keyword hint. |result| should be sorted by 169 // relevance before this is called. 170 void UpdateAssociatedKeywords(AutocompleteResult* result); 171 172 // For each group of contiguous matches from the same TemplateURL, show the 173 // provider name as a description on the first match in the group. 174 void UpdateKeywordDescriptions(AutocompleteResult* result); 175 176 // For each AutocompleteMatch returned by SearchProvider, updates the 177 // destination_url iff the provider's TemplateURL supports assisted query 178 // stats. 179 void UpdateAssistedQueryStats(AutocompleteResult* result); 180 181 // Calls AutocompleteControllerDelegate::OnResultChanged() and if done sends 182 // AUTOCOMPLETE_CONTROLLER_RESULT_READY. 183 void NotifyChanged(bool notify_default_match); 184 185 // Updates |done_| to be accurate with respect to current providers' statuses. 186 void CheckIfDone(); 187 188 // Starts |expire_timer_|. 189 void StartExpireTimer(); 190 191 // Starts |stop_timer_|. 192 void StartStopTimer(); 193 194 AutocompleteControllerDelegate* delegate_; 195 196 // A list of all providers. 197 Providers providers_; 198 199 HistoryURLProvider* history_url_provider_; 200 201 KeywordProvider* keyword_provider_; 202 203 SearchProvider* search_provider_; 204 205 ZeroSuggestProvider* zero_suggest_provider_; 206 207 // Input passed to Start. 208 AutocompleteInput input_; 209 210 // Data from the autocomplete query. 211 AutocompleteResult result_; 212 213 // The most recent time the default match (inline match) changed. This may 214 // be earlier than the most recent keystroke if the recent keystrokes didn't 215 // change the suggested match in the omnibox. (For instance, if 216 // a user typed "mail.goog" and the match https://mail.google.com/ was 217 // the destination match ever since the user typed "ma" then this is 218 // the time that URL first appeared as the default match.) This may 219 // also be more recent than the last keystroke if there was an 220 // asynchronous provider that returned and changed the default 221 // match. See UpdateResult() for details on when we consider a 222 // match to have changed. 223 base::TimeTicks last_time_default_match_changed_; 224 225 // Timer used to remove any matches copied from the last result. When run 226 // invokes |ExpireCopiedEntries|. 227 base::OneShotTimer<AutocompleteController> expire_timer_; 228 229 // Timer used to tell the providers to Stop() searching for matches. 230 base::OneShotTimer<AutocompleteController> stop_timer_; 231 232 // Amount of time (in ms) between when the user stops typing and 233 // when we send Stop() to every provider. This is intended to avoid 234 // the disruptive effect of belated omnibox updates, updates that 235 // come after the user has had to time to read the whole dropdown 236 // and doesn't expect it to change. 237 const base::TimeDelta stop_timer_duration_; 238 239 // True if a query is not currently running. 240 bool done_; 241 242 // Are we in Start()? This is used to avoid updating |result_| and sending 243 // notifications until Start() has been invoked on all providers. 244 bool in_start_; 245 246 TemplateURLService* template_url_service_; 247 248 DISALLOW_COPY_AND_ASSIGN(AutocompleteController); 249}; 250 251#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_CONTROLLER_H_ 252