Home | History | Annotate | Download | only in omnibox
      1 // Copyright 2014 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 // This class contains common functionality for search-based autocomplete
      6 // providers. Search provider and zero suggest provider both use it for common
      7 // functionality.
      8 
      9 #ifndef COMPONENTS_OMNIBOX_BASE_SEARCH_PROVIDER_H_
     10 #define COMPONENTS_OMNIBOX_BASE_SEARCH_PROVIDER_H_
     11 
     12 #include <map>
     13 #include <string>
     14 #include <utility>
     15 #include <vector>
     16 
     17 #include "base/memory/scoped_vector.h"
     18 #include "base/strings/string16.h"
     19 #include "components/metrics/proto/omnibox_event.pb.h"
     20 #include "components/omnibox/autocomplete_input.h"
     21 #include "components/omnibox/autocomplete_match.h"
     22 #include "components/omnibox/autocomplete_provider.h"
     23 #include "components/omnibox/search_suggestion_parser.h"
     24 
     25 class AutocompleteProviderClient;
     26 class GURL;
     27 class SearchTermsData;
     28 class SuggestionDeletionHandler;
     29 class TemplateURL;
     30 class TemplateURLService;
     31 
     32 namespace base {
     33 class DictionaryValue;
     34 class ListValue;
     35 class Value;
     36 }
     37 
     38 // Base functionality for receiving suggestions from a search engine.
     39 // This class is abstract and should only be used as a base for other
     40 // autocomplete providers utilizing its functionality.
     41 class BaseSearchProvider : public AutocompleteProvider {
     42  public:
     43   // ID used in creating URLFetcher for default provider's suggest results.
     44   static const int kDefaultProviderURLFetcherID;
     45 
     46   // ID used in creating URLFetcher for keyword provider's suggest results.
     47   static const int kKeywordProviderURLFetcherID;
     48 
     49   // ID used in creating URLFetcher for deleting suggestion results.
     50   static const int kDeletionURLFetcherID;
     51 
     52   BaseSearchProvider(TemplateURLService* template_url_service,
     53                      scoped_ptr<AutocompleteProviderClient> client,
     54                      AutocompleteProvider::Type type);
     55 
     56   // Returns whether |match| is flagged as a query that should be prefetched.
     57   static bool ShouldPrefetch(const AutocompleteMatch& match);
     58 
     59   // Returns a simpler AutocompleteMatch suitable for persistence like in
     60   // ShortcutsDatabase.  This wrapper function uses a number of default values
     61   // that may or may not be appropriate for your needs.
     62   // NOTE: Use with care. Most likely you want the other CreateSearchSuggestion
     63   // with protected access.
     64   static AutocompleteMatch CreateSearchSuggestion(
     65       const base::string16& suggestion,
     66       AutocompleteMatchType::Type type,
     67       bool from_keyword_provider,
     68       const TemplateURL* template_url,
     69       const SearchTermsData& search_terms_data);
     70 
     71   // AutocompleteProvider:
     72   virtual void DeleteMatch(const AutocompleteMatch& match) OVERRIDE;
     73   virtual void AddProviderInfo(ProvidersInfo* provider_info) const OVERRIDE;
     74 
     75   bool field_trial_triggered_in_session() const {
     76     return field_trial_triggered_in_session_;
     77   }
     78 
     79  protected:
     80   // The following keys are used to record additional information on matches.
     81 
     82   // We annotate our AutocompleteMatches with whether their relevance scores
     83   // were server-provided using this key in the |additional_info| field.
     84   static const char kRelevanceFromServerKey[];
     85 
     86   // Indicates whether the server said a match should be prefetched.
     87   static const char kShouldPrefetchKey[];
     88 
     89   // Used to store metadata from the server response, which is needed for
     90   // prefetching.
     91   static const char kSuggestMetadataKey[];
     92 
     93   // Used to store a deletion request url for server-provided suggestions.
     94   static const char kDeletionUrlKey[];
     95 
     96   // These are the values for the above keys.
     97   static const char kTrue[];
     98   static const char kFalse[];
     99 
    100   virtual ~BaseSearchProvider();
    101 
    102   typedef std::pair<base::string16, std::string> MatchKey;
    103   typedef std::map<MatchKey, AutocompleteMatch> MatchMap;
    104   typedef ScopedVector<SuggestionDeletionHandler> SuggestionDeletionHandlers;
    105 
    106   // Returns an AutocompleteMatch with the given |autocomplete_provider|
    107   // for the search |suggestion|, which represents a search via |template_url|.
    108   // If |template_url| is NULL, returns a match with an invalid destination URL.
    109   //
    110   // |input| is the original user input. Text in the input is used to highlight
    111   // portions of the match contents to distinguish locally-typed text from
    112   // suggested text.
    113   //
    114   // |input| is also necessary for various other details, like whether we should
    115   // allow inline autocompletion and what the transition type should be.
    116   // |in_keyword_mode| helps guarantee a non-keyword suggestion does not
    117   // appear as the default match when the user is in keyword mode.
    118   // |accepted_suggestion| is used to generate Assisted Query Stats.
    119   // |append_extra_query_params| should be set if |template_url| is the default
    120   // search engine, so the destination URL will contain any
    121   // command-line-specified query params.
    122   static AutocompleteMatch CreateSearchSuggestion(
    123       AutocompleteProvider* autocomplete_provider,
    124       const AutocompleteInput& input,
    125       const bool in_keyword_mode,
    126       const SearchSuggestionParser::SuggestResult& suggestion,
    127       const TemplateURL* template_url,
    128       const SearchTermsData& search_terms_data,
    129       int accepted_suggestion,
    130       bool append_extra_query_params);
    131 
    132   // Returns whether the requirements for requesting zero suggest results
    133   // are met. The requirements are
    134   // * The user is enrolled in a zero suggest experiment.
    135   // * The user is not on the NTP.
    136   // * The suggest request is sent over HTTPS.  This avoids leaking the current
    137   //   page URL or personal data in unencrypted network traffic.
    138   // * The user has suggest enabled in their settings and is not in incognito
    139   //   mode.  (Incognito disables suggest entirely.)
    140   // * The user's suggest provider is Google.  We might want to allow other
    141   //   providers to see this data someday, but for now this has only been
    142   //   implemented for Google.
    143   static bool ZeroSuggestEnabled(
    144      const GURL& suggest_url,
    145      const TemplateURL* template_url,
    146      metrics::OmniboxEventProto::PageClassification page_classification,
    147      const SearchTermsData& search_terms_data,
    148      AutocompleteProviderClient* client);
    149 
    150   // Returns whether we can send the URL of the current page in any suggest
    151   // requests.  Doing this requires that all the following hold:
    152   // * ZeroSuggestEnabled() is true, so we meet the requirements above.
    153   // * The current URL is HTTP, or HTTPS with the same domain as the suggest
    154   //   server.  Non-HTTP[S] URLs (e.g. FTP/file URLs) may contain sensitive
    155   //   information.  HTTPS URLs may also contain sensitive information, but if
    156   //   they're on the same domain as the suggest server, then the relevant
    157   //   entity could have already seen/logged this data.
    158   // * The user is OK in principle with sending URLs of current pages to their
    159   //   provider.  Today, there is no explicit setting that controls this, but if
    160   //   the user has tab sync enabled and tab sync is unencrypted, then they're
    161   //   already sending this data to Google for sync purposes.  Thus we use this
    162   //   setting as a proxy for "it's OK to send such data".  In the future,
    163   //   especially if we want to support suggest providers other than Google, we
    164   //   may change this to be a standalone setting or part of some explicit
    165   //   general opt-in.
    166   static bool CanSendURL(
    167       const GURL& current_page_url,
    168       const GURL& suggest_url,
    169       const TemplateURL* template_url,
    170       metrics::OmniboxEventProto::PageClassification page_classification,
    171       const SearchTermsData& search_terms_data,
    172       AutocompleteProviderClient* client);
    173 
    174   // If the |deletion_url| is valid, then set |match.deletable| to true and
    175   // save the |deletion_url| into the |match|'s additional info under
    176   // the key |kDeletionUrlKey|.
    177   void SetDeletionURL(const std::string& deletion_url,
    178                       AutocompleteMatch* match);
    179 
    180   // Creates an AutocompleteMatch from |result| to search for the query in
    181   // |result|. Adds the created match to |map|; if such a match
    182   // already exists, whichever one has lower relevance is eliminated.
    183   // |metadata| and |accepted_suggestion| are used for generating an
    184   // AutocompleteMatch.
    185   // |mark_as_deletable| indicates whether the match should be marked deletable.
    186   // |in_keyword_mode| helps guarantee a non-keyword suggestion does not
    187   // appear as the default match when the user is in keyword mode.
    188   // NOTE: Any result containing a deletion URL is always marked deletable.
    189   void AddMatchToMap(const SearchSuggestionParser::SuggestResult& result,
    190                      const std::string& metadata,
    191                      int accepted_suggestion,
    192                      bool mark_as_deletable,
    193                      bool in_keyword_mode,
    194                      MatchMap* map);
    195 
    196   // Parses results from the suggest server and updates the appropriate suggest
    197   // and navigation result lists in |results|. |default_result_relevance| is
    198   // the relevance to use if it was not explicitly set by the server.
    199   // |is_keyword_result| indicates whether the response was received from the
    200   // keyword provider.
    201   // Returns whether the appropriate result list members were updated.
    202   bool ParseSuggestResults(const base::Value& root_val,
    203                            int default_result_relevance,
    204                            bool is_keyword_result,
    205                            SearchSuggestionParser::Results* results);
    206 
    207   // Returns the TemplateURL corresponding to the keyword or default
    208   // provider based on the value of |is_keyword|.
    209   virtual const TemplateURL* GetTemplateURL(bool is_keyword) const = 0;
    210 
    211   // Returns the AutocompleteInput for keyword provider or default provider
    212   // based on the value of |is_keyword|.
    213   virtual const AutocompleteInput GetInput(bool is_keyword) const = 0;
    214 
    215   // Returns whether the destination URL corresponding to the given |result|
    216   // should contain command-line-specified query params.
    217   virtual bool ShouldAppendExtraParams(
    218       const SearchSuggestionParser::SuggestResult& result) const = 0;
    219 
    220   // Records in UMA whether the deletion request resulted in success.
    221   virtual void RecordDeletionResult(bool success) = 0;
    222 
    223   TemplateURLService* template_url_service_;
    224   scoped_ptr<AutocompleteProviderClient> client_;
    225 
    226   // Whether a field trial, if any, has triggered in the most recent
    227   // autocomplete query. This field is set to true only if the suggestion
    228   // provider has completed and the response contained
    229   // '"google:fieldtrialtriggered":true'.
    230   bool field_trial_triggered_;
    231 
    232   // Same as above except that it is maintained across the current Omnibox
    233   // session.
    234   bool field_trial_triggered_in_session_;
    235 
    236  private:
    237   friend class SearchProviderTest;
    238   FRIEND_TEST_ALL_PREFIXES(SearchProviderTest, TestDeleteMatch);
    239 
    240   // Removes the deleted |match| from the list of |matches_|.
    241   void DeleteMatchFromMatches(const AutocompleteMatch& match);
    242 
    243   // This gets called when we have requested a suggestion deletion from the
    244   // server to handle the results of the deletion. It will be called after the
    245   // deletion request completes.
    246   void OnDeletionComplete(bool success,
    247                           SuggestionDeletionHandler* handler);
    248 
    249   // Each deletion handler in this vector corresponds to an outstanding request
    250   // that a server delete a personalized suggestion. Making this a ScopedVector
    251   // causes us to auto-cancel all such requests on shutdown.
    252   SuggestionDeletionHandlers deletion_handlers_;
    253 
    254   DISALLOW_COPY_AND_ASSIGN(BaseSearchProvider);
    255 };
    256 
    257 #endif  // COMPONENTS_OMNIBOX_BASE_SEARCH_PROVIDER_H_
    258