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