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 file contains the keyword autocomplete provider. The keyword provider
      6 // is responsible for remembering/suggesting user "search keyword queries"
      7 // (e.g.  "imdb Godzilla") and then fixing them up into valid URLs.  An
      8 // instance of it gets created and managed by the autocomplete controller.
      9 // KeywordProvider uses a TemplateURLService to find the set of keywords.
     10 
     11 #ifndef COMPONENTS_OMNIBOX_KEYWORD_PROVIDER_H_
     12 #define COMPONENTS_OMNIBOX_KEYWORD_PROVIDER_H_
     13 
     14 #include <string>
     15 
     16 #include "base/basictypes.h"
     17 #include "base/compiler_specific.h"
     18 #include "base/memory/scoped_ptr.h"
     19 #include "components/metrics/proto/omnibox_input_type.pb.h"
     20 #include "components/omnibox/autocomplete_input.h"
     21 #include "components/omnibox/autocomplete_provider.h"
     22 #include "components/omnibox/keyword_extensions_delegate.h"
     23 
     24 class AutocompleteProviderListener;
     25 class KeywordExtensionsDelegate;
     26 class TemplateURL;
     27 class TemplateURLService;
     28 
     29 // Autocomplete provider for keyword input.
     30 //
     31 // After construction, the autocomplete controller repeatedly calls Start()
     32 // with some user input, each time expecting to receive a small set of the best
     33 // matches (either synchronously or asynchronously).
     34 //
     35 // To construct these matches, the provider treats user input as a series of
     36 // whitespace-delimited tokens and tries to match the first token as the prefix
     37 // of a known "keyword".  A keyword is some string that maps to a search query
     38 // URL; the rest of the user's input is taken as the input to the query.  For
     39 // example, the keyword "bug" might map to the URL "http://b/issue?id=%s", so
     40 // input like "bug 123" would become "http://b/issue?id=123".
     41 //
     42 // Because we do prefix matching, user input could match more than one keyword
     43 // at once.  (Example: the input "f jazz" matches all keywords starting with
     44 // "f".)  We return the best matches, up to three.
     45 //
     46 // The resulting matches are shown with content specified by the keyword
     47 // (usually "Search [name] for %s"), description "(Keyword: [keyword])", and
     48 // action "[keyword] %s".  If the user has typed a (possibly partial) keyword
     49 // but no search terms, the suggested result is shown greyed out, with
     50 // "<enter term(s)>" as the substituted input, and does nothing when selected.
     51 class KeywordProvider : public AutocompleteProvider {
     52  public:
     53   KeywordProvider(AutocompleteProviderListener* listener,
     54                   TemplateURLService* model);
     55 
     56   void set_extensions_delegate(
     57       scoped_ptr<KeywordExtensionsDelegate> extensions_delegate) {
     58     extensions_delegate_ = extensions_delegate.Pass();
     59   }
     60 
     61   // Extracts the next whitespace-delimited token from input and returns it.
     62   // Sets |remaining_input| to everything after the first token (skipping over
     63   // the first intervening whitespace).
     64   // If |trim_leading_whitespace| is true then leading whitespace in
     65   // |*remaining_input| will be trimmed.
     66   static base::string16 SplitKeywordFromInput(const base::string16& input,
     67                                               bool trim_leading_whitespace,
     68                                               base::string16* remaining_input);
     69 
     70   // Returns the replacement string from the user input. The replacement
     71   // string is the portion of the input that does not contain the keyword.
     72   // For example, the replacement string for "b blah" is blah.
     73   // If |trim_leading_whitespace| is true then leading whitespace in
     74   // replacement string will be trimmed.
     75   static base::string16 SplitReplacementStringFromInput(
     76       const base::string16& input,
     77       bool trim_leading_whitespace);
     78 
     79   // Returns the matching substituting keyword for |input|, or NULL if there
     80   // is no keyword for the specified input.  If the matching keyword was found,
     81   // updates |input|'s text and cursor position.
     82   static const TemplateURL* GetSubstitutingTemplateURLForInput(
     83       TemplateURLService* model,
     84       AutocompleteInput* input);
     85 
     86   // If |text| corresponds (in the sense of
     87   // TemplateURLModel::CleanUserInputKeyword()) to an enabled, substituting
     88   // keyword, returns that keyword; returns the empty string otherwise.
     89   base::string16 GetKeywordForText(const base::string16& text) const;
     90 
     91   // Creates a fully marked-up AutocompleteMatch for a specific keyword.
     92   AutocompleteMatch CreateVerbatimMatch(const base::string16& text,
     93                                         const base::string16& keyword,
     94                                         const AutocompleteInput& input);
     95 
     96   // AutocompleteProvider:
     97   virtual void Start(const AutocompleteInput& input,
     98                      bool minimal_changes) OVERRIDE;
     99   virtual void Stop(bool clear_cached_results) OVERRIDE;
    100 
    101  private:
    102   friend class KeywordExtensionsDelegateImpl;
    103 
    104   virtual ~KeywordProvider();
    105 
    106   // Extracts the keyword from |input| into |keyword|. Any remaining characters
    107   // after the keyword are placed in |remaining_input|. Returns true if |input|
    108   // is valid and has a keyword. This makes use of SplitKeywordFromInput to
    109   // extract the keyword and remaining string, and uses
    110   // TemplateURLService::CleanUserInputKeyword to remove unnecessary characters.
    111   // In general use this instead of SplitKeywordFromInput.
    112   // Leading whitespace in |*remaining_input| will be trimmed.
    113   static bool ExtractKeywordFromInput(const AutocompleteInput& input,
    114                                       base::string16* keyword,
    115                                       base::string16* remaining_input);
    116 
    117   // Determines the relevance for some input, given its type, whether the user
    118   // typed the complete keyword, and whether the user is in "prefer keyword
    119   // matches" mode, and whether the keyword supports replacement.
    120   // If |allow_exact_keyword_match| is false, the relevance for complete
    121   // keywords that support replacements is degraded.
    122   static int CalculateRelevance(metrics::OmniboxInputType::Type type,
    123                                 bool complete,
    124                                 bool support_replacement,
    125                                 bool prefer_keyword,
    126                                 bool allow_exact_keyword_match);
    127 
    128   // Creates a fully marked-up AutocompleteMatch from the user's input.
    129   // If |relevance| is negative, calculate a relevance based on heuristics.
    130   AutocompleteMatch CreateAutocompleteMatch(
    131       const TemplateURL* template_url,
    132       const AutocompleteInput& input,
    133       size_t prefix_length,
    134       const base::string16& remaining_input,
    135       bool allowed_to_be_default_match,
    136       int relevance);
    137 
    138   // Fills in the "destination_url" and "contents" fields of |match| with the
    139   // provided user input and keyword data.
    140   void FillInURLAndContents(const base::string16& remaining_input,
    141                             const TemplateURL* element,
    142                             AutocompleteMatch* match) const;
    143 
    144   TemplateURLService* GetTemplateURLService() const;
    145 
    146   AutocompleteProviderListener* listener_;
    147 
    148   // Model for the keywords.
    149   TemplateURLService* model_;
    150 
    151   // Delegate to handle the extensions-only logic for KeywordProvider.
    152   // NULL when extensions are not enabled. May be NULL for tests.
    153   scoped_ptr<KeywordExtensionsDelegate> extensions_delegate_;
    154 
    155   DISALLOW_COPY_AND_ASSIGN(KeywordProvider);
    156 };
    157 
    158 #endif  // COMPONENTS_OMNIBOX_KEYWORD_PROVIDER_H_
    159