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