Home | History | Annotate | Download | only in search_engines
      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 #ifndef COMPONENTS_SEARCH_ENGINES_TEMPLATE_URL_H_
      6 #define COMPONENTS_SEARCH_ENGINES_TEMPLATE_URL_H_
      7 
      8 #include <string>
      9 #include <utility>
     10 #include <vector>
     11 
     12 #include "base/gtest_prod_util.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/time/time.h"
     15 #include "components/metrics/proto/omnibox_event.pb.h"
     16 #include "components/metrics/proto/omnibox_input_type.pb.h"
     17 #include "components/search_engines/template_url_data.h"
     18 #include "components/search_engines/template_url_id.h"
     19 #include "ui/gfx/geometry/size.h"
     20 #include "url/gurl.h"
     21 #include "url/url_parse.h"
     22 
     23 class SearchTermsData;
     24 class TemplateURL;
     25 
     26 
     27 // TemplateURLRef -------------------------------------------------------------
     28 
     29 // A TemplateURLRef represents a single URL within the larger TemplateURL class
     30 // (which represents an entire "search engine", see below).  If
     31 // SupportsReplacement() is true, this URL has placeholders in it, for which
     32 // callers can substitute values to get a "real" URL using ReplaceSearchTerms().
     33 //
     34 // TemplateURLRefs always have a non-NULL |owner_| TemplateURL, which they
     35 // access in order to get at important data like the underlying URL string or
     36 // the associated Profile.
     37 class TemplateURLRef {
     38  public:
     39   // Magic numbers to pass to ReplaceSearchTerms() for the |accepted_suggestion|
     40   // parameter.  Most callers aren't using Suggest capabilities and should just
     41   // pass NO_SUGGESTIONS_AVAILABLE.
     42   // NOTE: Because positive values are meaningful, make sure these are negative!
     43   enum AcceptedSuggestion {
     44     NO_SUGGESTION_CHOSEN = -1,
     45     NO_SUGGESTIONS_AVAILABLE = -2,
     46   };
     47 
     48   // Which kind of URL within our owner we are.  This allows us to get at the
     49   // correct string field. Use |INDEXED| to indicate that the numerical
     50   // |index_in_owner_| should be used instead.
     51   enum Type {
     52     SEARCH,
     53     SUGGEST,
     54     INSTANT,
     55     IMAGE,
     56     NEW_TAB,
     57     CONTEXTUAL_SEARCH,
     58     INDEXED
     59   };
     60 
     61   // Type to store <content_type, post_data> pair for POST URLs.
     62   // The |content_type|(first part of the pair) is the content-type of
     63   // the |post_data|(second part of the pair) which is encoded in
     64   // "multipart/form-data" format, it also contains the MIME boundary used in
     65   // the |post_data|. See http://tools.ietf.org/html/rfc2046 for the details.
     66   typedef std::pair<std::string, std::string> PostContent;
     67 
     68   // This struct encapsulates arguments passed to
     69   // TemplateURLRef::ReplaceSearchTerms methods.  By default, only search_terms
     70   // is required and is passed in the constructor.
     71   struct SearchTermsArgs {
     72     explicit SearchTermsArgs(const base::string16& search_terms);
     73     ~SearchTermsArgs();
     74 
     75     struct ContextualSearchParams {
     76       ContextualSearchParams();
     77       // Used when the content is sent in the HTTP header instead of as CGI
     78       // parameters.
     79       // TODO(jeremycho): Remove base_page_url and selection parameters once
     80       // they are logged from the HTTP header.
     81       ContextualSearchParams(const int version,
     82                              const std::string& selection,
     83                              const std::string& base_page_url,
     84                              const bool resolve);
     85       // TODO(jeremycho): Delete constructor once Clank no longer depends on it.
     86       ContextualSearchParams(const int version,
     87                              const size_t start,
     88                              const size_t end,
     89                              const std::string& selection,
     90                              const std::string& content,
     91                              const std::string& base_page_url,
     92                              const std::string& encoding,
     93                              const bool resolve);
     94       ~ContextualSearchParams();
     95 
     96       // The version of contextual search.
     97       int version;
     98 
     99       // Offset into the page content of the start of the user selection.
    100       size_t start;
    101 
    102       // Offset into the page content of the end of the user selection.
    103       size_t end;
    104 
    105       // The user selection.
    106       std::string selection;
    107 
    108       // The text including and surrounding the user selection.
    109       std::string content;
    110 
    111       // The URL of the page containing the user selection.
    112       std::string base_page_url;
    113 
    114       // The encoding of content.
    115       std::string encoding;
    116 
    117       // If true, the server will generate a search term based on the user
    118       // selection and context.  Otherwise the user selection will be used as-is
    119       // as the search term.
    120       bool resolve;
    121     };
    122 
    123     // The search terms (query).
    124     base::string16 search_terms;
    125 
    126     // The original (input) query.
    127     base::string16 original_query;
    128 
    129     // The type the original input query was identified as.
    130     metrics::OmniboxInputType::Type input_type;
    131 
    132     // The optional assisted query stats, aka AQS, used for logging purposes.
    133     // This string contains impressions of all autocomplete matches shown
    134     // at the query submission time.  For privacy reasons, we require the
    135     // search provider to support HTTPS protocol in order to receive the AQS
    136     // param.
    137     // For more details, see http://goto.google.com/binary-clients-logging .
    138     std::string assisted_query_stats;
    139 
    140     // TODO: Remove along with "aq" CGI param.
    141     int accepted_suggestion;
    142 
    143     // The 0-based position of the cursor within the query string at the time
    144     // the request was issued.  Set to base::string16::npos if not used.
    145     size_t cursor_position;
    146 
    147     // True to enable the start-edge margin of the omnibox, used in extended
    148     // Instant to align the preview contents with the omnibox.
    149     bool enable_omnibox_start_margin;
    150 
    151     // The URL of the current webpage to be used for experimental zero-prefix
    152     // suggestions.
    153     std::string current_page_url;
    154 
    155     // Which omnibox the user used to type the prefix.
    156     metrics::OmniboxEventProto::PageClassification page_classification;
    157 
    158     // True for searches issued with the bookmark bar pref set to shown.
    159     bool bookmark_bar_pinned;
    160 
    161     // Optional session token.
    162     std::string session_token;
    163 
    164     // Prefetch query and type.
    165     std::string prefetch_query;
    166     std::string prefetch_query_type;
    167 
    168     // Additional query params provided by the suggest server.
    169     std::string suggest_query_params;
    170 
    171     // If set, ReplaceSearchTerms() will automatically append any extra query
    172     // params specified via the --extra-search-query-params command-line
    173     // argument.  Generally, this should be set when dealing with the search or
    174     // instant TemplateURLRefs of the default search engine and the caller cares
    175     // about the query portion of the URL.  Since neither TemplateURLRef nor
    176     // indeed TemplateURL know whether a TemplateURL is the default search
    177     // engine, callers instead must set this manually.
    178     bool append_extra_query_params;
    179 
    180     // The raw content of an image thumbnail that will be used as a query for
    181     // search-by-image frontend.
    182     std::string image_thumbnail_content;
    183 
    184     // When searching for an image, the URL of the original image. Callers
    185     // should leave this empty for images specified via data: URLs.
    186     GURL image_url;
    187 
    188     // When searching for an image, the original size of the image.
    189     gfx::Size image_original_size;
    190 
    191     // If set, ReplaceSearchTerms() will append a param to the TemplateURLRef to
    192     // update the search results page incrementally even if that is otherwise
    193     // disabled by google.com preferences. See comments on
    194     // chrome::ForceInstantResultsParam().
    195     bool force_instant_results;
    196 
    197     // True if the search was made using the app list search box. Otherwise, the
    198     // search was made using the omnibox.
    199     bool from_app_list;
    200 
    201     ContextualSearchParams contextual_search_params;
    202   };
    203 
    204   TemplateURLRef(TemplateURL* owner, Type type);
    205   TemplateURLRef(TemplateURL* owner, size_t index_in_owner);
    206   ~TemplateURLRef();
    207 
    208   // Returns the raw URL. None of the parameters will have been replaced.
    209   std::string GetURL() const;
    210 
    211   // Returns the raw string of the post params. Please see comments in
    212   // prepopulated_engines_schema.json for the format.
    213   std::string GetPostParamsString() const;
    214 
    215   // Returns true if this URL supports search term replacement.
    216   bool SupportsReplacement(const SearchTermsData& search_terms_data) const;
    217 
    218   // Returns a string that is the result of replacing the search terms in
    219   // the url with the specified arguments.  We use our owner's input encoding.
    220   //
    221   // If this TemplateURLRef does not support replacement (SupportsReplacement
    222   // returns false), an empty string is returned.
    223   // If this TemplateURLRef uses POST, and |post_content| is not NULL, the
    224   // |post_params_| will be replaced, encoded in "multipart/form-data" format
    225   // and stored into |post_content|.
    226   std::string ReplaceSearchTerms(const SearchTermsArgs& search_terms_args,
    227                                  const SearchTermsData& search_terms_data,
    228                                  PostContent* post_content) const;
    229 
    230   // TODO(jnd): remove the following ReplaceSearchTerms definition which does
    231   // not have |post_content| parameter once all reference callers pass
    232   // |post_content| parameter.
    233   std::string ReplaceSearchTerms(
    234       const SearchTermsArgs& search_terms_args,
    235       const SearchTermsData& search_terms_data) const {
    236     return ReplaceSearchTerms(search_terms_args, search_terms_data, NULL);
    237   }
    238 
    239   // Returns true if the TemplateURLRef is valid. An invalid TemplateURLRef is
    240   // one that contains unknown terms, or invalid characters.
    241   bool IsValid(const SearchTermsData& search_terms_data) const;
    242 
    243   // Returns a string representation of this TemplateURLRef suitable for
    244   // display. The display format is the same as the format used by Firefox.
    245   base::string16 DisplayURL(const SearchTermsData& search_terms_data) const;
    246 
    247   // Converts a string as returned by DisplayURL back into a string as
    248   // understood by TemplateURLRef.
    249   static std::string DisplayURLToURLRef(const base::string16& display_url);
    250 
    251   // If this TemplateURLRef is valid and contains one search term, this returns
    252   // the host/path of the URL, otherwise this returns an empty string.
    253   const std::string& GetHost(const SearchTermsData& search_terms_data) const;
    254   const std::string& GetPath(const SearchTermsData& search_terms_data) const;
    255 
    256   // If this TemplateURLRef is valid and contains one search term, this returns
    257   // the key of the search term, otherwise this returns an empty string.
    258   const std::string& GetSearchTermKey(
    259       const SearchTermsData& search_terms_data) const;
    260 
    261   // Converts the specified term in our owner's encoding to a base::string16.
    262   base::string16 SearchTermToString16(const std::string& term) const;
    263 
    264   // Returns true if this TemplateURLRef has a replacement term of
    265   // {google:baseURL} or {google:baseSuggestURL}.
    266   bool HasGoogleBaseURLs(const SearchTermsData& search_terms_data) const;
    267 
    268   // Use the pattern referred to by this TemplateURLRef to match the provided
    269   // |url| and extract |search_terms| from it. Returns true if the pattern
    270   // matches, even if |search_terms| is empty. In this case
    271   // |search_term_component|, if not NULL, indicates whether the search terms
    272   // were found in the query or the ref parameters; and |search_terms_position|,
    273   // if not NULL, contains the position of the search terms in the query or the
    274   // ref parameters. Returns false and an empty |search_terms| if the pattern
    275   // does not match.
    276   bool ExtractSearchTermsFromURL(
    277       const GURL& url,
    278       base::string16* search_terms,
    279       const SearchTermsData& search_terms_data,
    280       url::Parsed::ComponentType* search_term_component,
    281       url::Component* search_terms_position) const;
    282 
    283   // Whether the URL uses POST (as opposed to GET).
    284   bool UsesPOSTMethod(const SearchTermsData& search_terms_data) const;
    285 
    286  private:
    287   friend class TemplateURL;
    288   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, SetPrepopulatedAndParse);
    289   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterKnown);
    290   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterUnknown);
    291   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLEmpty);
    292   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoTemplateEnd);
    293   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoKnownParameters);
    294   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLTwoParameters);
    295   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNestedParameter);
    296   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, URLRefTestImageURLWithPOST);
    297   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ReflectsBookmarkBarPinned);
    298 
    299   // Enumeration of the known types.
    300   enum ReplacementType {
    301     ENCODING,
    302     GOOGLE_ASSISTED_QUERY_STATS,
    303     GOOGLE_BASE_URL,
    304     GOOGLE_BASE_SUGGEST_URL,
    305     GOOGLE_BOOKMARK_BAR_PINNED,
    306     GOOGLE_CURRENT_PAGE_URL,
    307     GOOGLE_CURSOR_POSITION,
    308     GOOGLE_FORCE_INSTANT_RESULTS,
    309     GOOGLE_IMAGE_ORIGINAL_HEIGHT,
    310     GOOGLE_IMAGE_ORIGINAL_WIDTH,
    311     GOOGLE_IMAGE_SEARCH_SOURCE,
    312     GOOGLE_IMAGE_THUMBNAIL,
    313     GOOGLE_IMAGE_URL,
    314     GOOGLE_INPUT_TYPE,
    315     GOOGLE_INSTANT_EXTENDED_ENABLED,
    316     GOOGLE_NTP_IS_THEMED,
    317     GOOGLE_OMNIBOX_START_MARGIN,
    318     GOOGLE_CONTEXTUAL_SEARCH_VERSION,
    319     GOOGLE_CONTEXTUAL_SEARCH_CONTEXT_DATA,
    320     GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION,
    321     GOOGLE_PAGE_CLASSIFICATION,
    322     GOOGLE_PREFETCH_QUERY,
    323     GOOGLE_RLZ,
    324     GOOGLE_SEARCH_CLIENT,
    325     GOOGLE_SEARCH_FIELDTRIAL_GROUP,
    326     GOOGLE_SEARCH_VERSION,
    327     GOOGLE_SESSION_TOKEN,
    328     GOOGLE_SUGGEST_CLIENT,
    329     GOOGLE_SUGGEST_REQUEST_ID,
    330     GOOGLE_UNESCAPED_SEARCH_TERMS,
    331     LANGUAGE,
    332     SEARCH_TERMS,
    333   };
    334 
    335   // Used to identify an element of the raw url that can be replaced.
    336   struct Replacement {
    337     Replacement(ReplacementType type, size_t index)
    338         : type(type), index(index), is_post_param(false) {}
    339     ReplacementType type;
    340     size_t index;
    341     // Indicates the location in where the replacement is replaced. If
    342     // |is_post_param| is false, |index| indicates the byte position in
    343     // |parsed_url_|. Otherwise, |index| is the index of |post_params_|.
    344     bool is_post_param;
    345   };
    346 
    347   // The list of elements to replace.
    348   typedef std::vector<struct Replacement> Replacements;
    349   // Type to store <key, value> pairs for POST URLs.
    350   typedef std::pair<std::string, std::string> PostParam;
    351   typedef std::vector<PostParam> PostParams;
    352 
    353   // TemplateURLRef internally caches values to make replacement quick. This
    354   // method invalidates any cached values.
    355   void InvalidateCachedValues() const;
    356 
    357   // Parses the parameter in url at the specified offset. start/end specify the
    358   // range of the parameter in the url, including the braces. If the parameter
    359   // is valid, url is updated to reflect the appropriate parameter. If
    360   // the parameter is one of the known parameters an element is added to
    361   // replacements indicating the type and range of the element. The original
    362   // parameter is erased from the url.
    363   //
    364   // If the parameter is not a known parameter, false is returned. If this is a
    365   // prepopulated URL, the parameter is erased, otherwise it is left alone.
    366   bool ParseParameter(size_t start,
    367                       size_t end,
    368                       std::string* url,
    369                       Replacements* replacements) const;
    370 
    371   // Parses the specified url, replacing parameters as necessary. If
    372   // successful, valid is set to true, and the parsed url is returned. For all
    373   // known parameters that are encountered an entry is added to replacements.
    374   // If there is an error parsing the url, valid is set to false, and an empty
    375   // string is returned.  If the URL has the POST parameters, they will be
    376   // parsed into |post_params| which will be further replaced with real search
    377   // terms data and encoded in "multipart/form-data" format to generate the
    378   // POST data.
    379   std::string ParseURL(const std::string& url,
    380                        Replacements* replacements,
    381                        PostParams* post_params,
    382                        bool* valid) const;
    383 
    384   // If the url has not yet been parsed, ParseURL is invoked.
    385   // NOTE: While this is const, it modifies parsed_, valid_, parsed_url_ and
    386   // search_offset_.
    387   void ParseIfNecessary(const SearchTermsData& search_terms_data) const;
    388 
    389   // Extracts the query key and host from the url.
    390   void ParseHostAndSearchTermKey(
    391       const SearchTermsData& search_terms_data) const;
    392 
    393   // Encode post parameters in "multipart/form-data" format and store it
    394   // inside |post_content|. Returns false if errors are encountered during
    395   // encoding. This method is called each time ReplaceSearchTerms gets called.
    396   bool EncodeFormData(const PostParams& post_params,
    397                       PostContent* post_content) const;
    398 
    399   // Handles a replacement by using real term data. If the replacement
    400   // belongs to a PostParam, the PostParam will be replaced by the term data.
    401   // Otherwise, the term data will be inserted at the place that the
    402   // replacement points to.
    403   void HandleReplacement(const std::string& name,
    404                          const std::string& value,
    405                          const Replacement& replacement,
    406                          std::string* url) const;
    407 
    408   // Replaces all replacements in |parsed_url_| with their actual values and
    409   // returns the result.  This is the main functionality of
    410   // ReplaceSearchTerms().
    411   std::string HandleReplacements(
    412       const SearchTermsArgs& search_terms_args,
    413       const SearchTermsData& search_terms_data,
    414       PostContent* post_content) const;
    415 
    416   // The TemplateURL that contains us.  This should outlive us.
    417   TemplateURL* const owner_;
    418 
    419   // What kind of URL we are.
    420   const Type type_;
    421 
    422   // If |type_| is |INDEXED|, this |index_in_owner_| is used instead to refer to
    423   // a url within our owner.
    424   const size_t index_in_owner_;
    425 
    426   // Whether the URL has been parsed.
    427   mutable bool parsed_;
    428 
    429   // Whether the url was successfully parsed.
    430   mutable bool valid_;
    431 
    432   // The parsed URL. All terms have been stripped out of this with
    433   // replacements_ giving the index of the terms to replace.
    434   mutable std::string parsed_url_;
    435 
    436   // Do we support search term replacement?
    437   mutable bool supports_replacements_;
    438 
    439   // The replaceable parts of url (parsed_url_). These are ordered by index
    440   // into the string, and may be empty.
    441   mutable Replacements replacements_;
    442 
    443   // Host, path, key and location of the search term. These are only set if the
    444   // url contains one search term.
    445   mutable std::string host_;
    446   mutable std::string path_;
    447   mutable std::string search_term_key_;
    448   mutable url::Parsed::ComponentType search_term_key_location_;
    449 
    450   mutable PostParams post_params_;
    451 
    452   // Whether the contained URL is a pre-populated URL.
    453   bool prepopulated_;
    454 
    455   DISALLOW_COPY_AND_ASSIGN(TemplateURLRef);
    456 };
    457 
    458 
    459 // TemplateURL ----------------------------------------------------------------
    460 
    461 // A TemplateURL represents a single "search engine", defined primarily as a
    462 // subset of the Open Search Description Document
    463 // (http://www.opensearch.org/Specifications/OpenSearch) plus some extensions.
    464 // One TemplateURL contains several TemplateURLRefs, which correspond to various
    465 // different capabilities (e.g. doing searches or getting suggestions), as well
    466 // as a TemplateURLData containing other details like the name, keyword, etc.
    467 //
    468 // TemplateURLs are intended to be read-only for most users.
    469 // The TemplateURLService, which handles storing and manipulating TemplateURLs,
    470 // is made a friend so that it can be the exception to this pattern.
    471 class TemplateURL {
    472  public:
    473   enum Type {
    474     // Regular search engine.
    475     NORMAL,
    476     // Installed by extension through Override Settings API.
    477     NORMAL_CONTROLLED_BY_EXTENSION,
    478     // The keyword associated with an extension that uses the Omnibox API.
    479     OMNIBOX_API_EXTENSION,
    480   };
    481 
    482   // An AssociatedExtensionInfo represents information about the extension that
    483   // added the search engine.
    484   struct AssociatedExtensionInfo {
    485     AssociatedExtensionInfo(Type type, const std::string& extension_id);
    486     ~AssociatedExtensionInfo();
    487 
    488     Type type;
    489 
    490     std::string extension_id;
    491 
    492     // Whether the search engine is supposed to be default.
    493     bool wants_to_be_default_engine;
    494 
    495     // Used to resolve conflicts when there are multiple extensions specifying
    496     // the default search engine. The most recently-installed wins.
    497     base::Time install_time;
    498   };
    499 
    500   explicit TemplateURL(const TemplateURLData& data);
    501   ~TemplateURL();
    502 
    503   // Generates a suitable keyword for the specified url, which must be valid.
    504   // This is guaranteed not to return an empty string, since TemplateURLs should
    505   // never have an empty keyword.
    506   static base::string16 GenerateKeyword(const GURL& url);
    507 
    508   // Generates a favicon URL from the specified url.
    509   static GURL GenerateFaviconURL(const GURL& url);
    510 
    511   // Returns true if |t_url| and |data| are equal in all meaningful respects.
    512   // Static to allow either or both params to be NULL.
    513   static bool MatchesData(const TemplateURL* t_url,
    514                           const TemplateURLData* data,
    515                           const SearchTermsData& search_terms_data);
    516 
    517   const TemplateURLData& data() const { return data_; }
    518 
    519   const base::string16& short_name() const { return data_.short_name; }
    520   // An accessor for the short_name, but adjusted so it can be appropriately
    521   // displayed even if it is LTR and the UI is RTL.
    522   base::string16 AdjustedShortNameForLocaleDirection() const;
    523 
    524   const base::string16& keyword() const { return data_.keyword(); }
    525 
    526   const std::string& url() const { return data_.url(); }
    527   const std::string& suggestions_url() const { return data_.suggestions_url; }
    528   const std::string& instant_url() const { return data_.instant_url; }
    529   const std::string& image_url() const { return data_.image_url; }
    530   const std::string& new_tab_url() const { return data_.new_tab_url; }
    531   const std::string& contextual_search_url() const {
    532     return data_.contextual_search_url;
    533   }
    534   const std::string& search_url_post_params() const {
    535     return data_.search_url_post_params;
    536   }
    537   const std::string& suggestions_url_post_params() const {
    538     return data_.suggestions_url_post_params;
    539   }
    540   const std::string& instant_url_post_params() const {
    541     return data_.instant_url_post_params;
    542   }
    543   const std::string& image_url_post_params() const {
    544     return data_.image_url_post_params;
    545   }
    546   const std::vector<std::string>& alternate_urls() const {
    547     return data_.alternate_urls;
    548   }
    549   const GURL& favicon_url() const { return data_.favicon_url; }
    550 
    551   const GURL& originating_url() const { return data_.originating_url; }
    552 
    553   bool show_in_default_list() const { return data_.show_in_default_list; }
    554   // Returns true if show_in_default_list() is true and this TemplateURL has a
    555   // TemplateURLRef that supports replacement.
    556   bool ShowInDefaultList(const SearchTermsData& search_terms_data) const;
    557 
    558   bool safe_for_autoreplace() const { return data_.safe_for_autoreplace; }
    559 
    560   const std::vector<std::string>& input_encodings() const {
    561     return data_.input_encodings;
    562   }
    563 
    564   TemplateURLID id() const { return data_.id; }
    565 
    566   base::Time date_created() const { return data_.date_created; }
    567   base::Time last_modified() const { return data_.last_modified; }
    568 
    569   bool created_by_policy() const { return data_.created_by_policy; }
    570 
    571   int usage_count() const { return data_.usage_count; }
    572 
    573   int prepopulate_id() const { return data_.prepopulate_id; }
    574 
    575   const std::string& sync_guid() const { return data_.sync_guid; }
    576 
    577   // TODO(beaudoin): Rename this when renaming HasSearchTermsReplacementKey().
    578   const std::string& search_terms_replacement_key() const {
    579     return data_.search_terms_replacement_key;
    580   }
    581 
    582   const TemplateURLRef& url_ref() const { return url_ref_; }
    583   const TemplateURLRef& suggestions_url_ref() const {
    584     return suggestions_url_ref_;
    585   }
    586   const TemplateURLRef& instant_url_ref() const { return instant_url_ref_; }
    587   const TemplateURLRef& image_url_ref() const { return image_url_ref_; }
    588   const TemplateURLRef& new_tab_url_ref() const { return new_tab_url_ref_; }
    589   const TemplateURLRef& contextual_search_url_ref() const {
    590     return contextual_search_url_ref_;
    591   }
    592 
    593   // This setter shouldn't be used except by TemplateURLService and
    594   // TemplateURLServiceClient implementations.
    595   void set_extension_info(scoped_ptr<AssociatedExtensionInfo> extension_info) {
    596     extension_info_ = extension_info.Pass();
    597   }
    598 
    599   // Returns true if |url| supports replacement.
    600   bool SupportsReplacement(const SearchTermsData& search_terms_data) const;
    601 
    602   // Returns true if any URLRefs use Googe base URLs.
    603   bool HasGoogleBaseURLs(const SearchTermsData& search_terms_data) const;
    604 
    605   // Returns true if this TemplateURL uses Google base URLs and has a keyword
    606   // of "google.TLD".  We use this to decide whether we can automatically
    607   // update the keyword to reflect the current Google base URL TLD.
    608   bool IsGoogleSearchURLWithReplaceableKeyword(
    609       const SearchTermsData& search_terms_data) const;
    610 
    611   // Returns true if the keywords match or if
    612   // IsGoogleSearchURLWithReplaceableKeyword() is true for both |this| and
    613   // |other|.
    614   bool HasSameKeywordAs(const TemplateURLData& other,
    615                         const SearchTermsData& search_terms_data) const;
    616 
    617   Type GetType() const;
    618 
    619   // Returns the id of the extension that added this search engine. Only call
    620   // this for TemplateURLs of type NORMAL_CONTROLLED_BY_EXTENSION or
    621   // OMNIBOX_API_EXTENSION.
    622   std::string GetExtensionId() const;
    623 
    624   // Returns the total number of URLs comprised in this template, including
    625   // search and alternate URLs.
    626   size_t URLCount() const;
    627 
    628   // Gets the search URL at the given index. The alternate URLs, if any, are
    629   // numbered starting at 0, and the primary search URL follows. This is used
    630   // to decode the search term given a search URL (see
    631   // ExtractSearchTermsFromURL()).
    632   const std::string& GetURL(size_t index) const;
    633 
    634   // Use the alternate URLs and the search URL to match the provided |url|
    635   // and extract |search_terms| from it. Returns false and an empty
    636   // |search_terms| if no search terms can be matched. The order in which the
    637   // alternate URLs are listed dictates their priority, the URL at index 0 is
    638   // treated as the highest priority and the primary search URL is treated as
    639   // the lowest priority (see GetURL()).  For example, if a TemplateURL has
    640   // alternate URL "http://foo/#q={searchTerms}" and search URL
    641   // "http://foo/?q={searchTerms}", and the URL to be decoded is
    642   // "http://foo/?q=a#q=b", the alternate URL will match first and the decoded
    643   // search term will be "b".
    644   bool ExtractSearchTermsFromURL(const GURL& url,
    645                                  const SearchTermsData& search_terms_data,
    646                                  base::string16* search_terms);
    647 
    648   // Returns true if non-empty search terms could be extracted from |url| using
    649   // ExtractSearchTermsFromURL(). In other words, this returns whether |url|
    650   // could be the result of performing a search with |this|.
    651   bool IsSearchURL(const GURL& url, const SearchTermsData& search_terms_data);
    652 
    653   // Returns true if the specified |url| contains the search terms replacement
    654   // key in either the query or the ref. This method does not verify anything
    655   // else about the URL. In particular, it does not check that the domain
    656   // matches that of this TemplateURL.
    657   // TODO(beaudoin): Rename this to reflect that it really checks for an
    658   // InstantExtended capable URL.
    659   bool HasSearchTermsReplacementKey(const GURL& url) const;
    660 
    661   // Given a |url| corresponding to this TemplateURL, identifies the search
    662   // terms and replaces them with the ones in |search_terms_args|, leaving the
    663   // other parameters untouched. If the replacement fails, returns false and
    664   // leaves |result| untouched. This is used by mobile ports to perform query
    665   // refinement.
    666   bool ReplaceSearchTermsInURL(
    667       const GURL& url,
    668       const TemplateURLRef::SearchTermsArgs& search_terms_args,
    669       const SearchTermsData& search_terms_data,
    670       GURL* result);
    671 
    672   // Encodes the search terms from |search_terms_args| so that we know the
    673   // |input_encoding|. Returns the |encoded_terms| and the
    674   // |encoded_original_query|. |encoded_terms| may be escaped as path or query
    675   // depending on |is_in_query|; |encoded_original_query| is always escaped as
    676   // query.
    677   void EncodeSearchTerms(
    678       const TemplateURLRef::SearchTermsArgs& search_terms_args,
    679       bool is_in_query,
    680       std::string* input_encoding,
    681       base::string16* encoded_terms,
    682       base::string16* encoded_original_query) const;
    683 
    684   // Returns the search url for this template URL.
    685   // Returns an empty GURL if this template URL has no url().
    686   GURL GenerateSearchURL(const SearchTermsData& search_terms_data) const;
    687 
    688  private:
    689   friend class TemplateURLService;
    690   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ReflectsBookmarkBarPinned);
    691 
    692   void CopyFrom(const TemplateURL& other);
    693 
    694   void SetURL(const std::string& url);
    695   void SetPrepopulateId(int id);
    696 
    697   // Resets the keyword if IsGoogleSearchURLWithReplaceableKeyword() or |force|.
    698   // The |force| parameter is useful when the existing keyword is known to be
    699   // a placeholder.  The resulting keyword is generated using
    700   // GenerateSearchURL() and GenerateKeyword().
    701   void ResetKeywordIfNecessary(const SearchTermsData& search_terms_data,
    702                                bool force);
    703 
    704   // Uses the alternate URLs and the search URL to match the provided |url|
    705   // and extract |search_terms| from it as well as the |search_terms_component|
    706   // (either REF or QUERY) and |search_terms_component| at which the
    707   // |search_terms| are found in |url|. See also ExtractSearchTermsFromURL().
    708   bool FindSearchTermsInURL(const GURL& url,
    709                             const SearchTermsData& search_terms_data,
    710                             base::string16* search_terms,
    711                             url::Parsed::ComponentType* search_terms_component,
    712                             url::Component* search_terms_position);
    713 
    714   TemplateURLData data_;
    715   TemplateURLRef url_ref_;
    716   TemplateURLRef suggestions_url_ref_;
    717   TemplateURLRef instant_url_ref_;
    718   TemplateURLRef image_url_ref_;
    719   TemplateURLRef new_tab_url_ref_;
    720   TemplateURLRef contextual_search_url_ref_;
    721   scoped_ptr<AssociatedExtensionInfo> extension_info_;
    722 
    723   // TODO(sky): Add date last parsed OSD file.
    724 
    725   DISALLOW_COPY_AND_ASSIGN(TemplateURL);
    726 };
    727 
    728 #endif  // COMPONENTS_SEARCH_ENGINES_TEMPLATE_URL_H_
    729