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