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
23class SearchTermsData;
24class 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.
37class 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.
471class 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