Home | History | Annotate | Download | only in autocomplete
      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 
     20 class AutocompleteControllerDelegate;
     21 class HistoryURLProvider;
     22 class KeywordProvider;
     23 class Profile;
     24 class SearchProvider;
     25 class TemplateURLService;
     26 class 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.
     48 class 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