autocomplete_controller.h revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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
20class AutocompleteControllerDelegate;
21class HistoryURLProvider;
22class KeywordProvider;
23class Profile;
24class SearchProvider;
25class TemplateURLService;
26class 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.
48class 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
127  HistoryURLProvider* history_url_provider() const {
128    return history_url_provider_;
129  }
130  KeywordProvider* keyword_provider() const { return keyword_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
138  const AutocompleteInput& input() const { return input_; }
139
140  const AutocompleteResult& result() const { return result_; }
141  bool done() const { return done_; }
142  const Providers& providers() const { return providers_; }
143
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