Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / components / search_engines / template_url.h
1 // Copyright 2014 The Chromium Authors
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 <cstddef>
9 #include <memory>
10 #include <string>
11 #include <utility>
12 #include <vector>
13
14 #include "base/gtest_prod_util.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/time/time.h"
17 #include "components/search_engines/search_engine_type.h"
18 #include "components/search_engines/template_url_data.h"
19 #include "components/search_engines/template_url_id.h"
20 #include "third_party/metrics_proto/chrome_searchbox_stats.pb.h"
21 #include "third_party/metrics_proto/omnibox_event.pb.h"
22 #include "third_party/metrics_proto/omnibox_focus_type.pb.h"
23 #include "third_party/metrics_proto/omnibox_input_type.pb.h"
24 #include "ui/gfx/geometry/size.h"
25 #include "url/gurl.h"
26 #include "url/third_party/mozilla/url_parse.h"
27
28 class SearchTermsData;
29 class TemplateURL;
30
31
32 // TemplateURLRef -------------------------------------------------------------
33
34 // A TemplateURLRef represents a single URL within the larger TemplateURL class
35 // (which represents an entire "search engine", see below).  If
36 // SupportsReplacement() is true, this URL has placeholders in it, for which
37 // callers can substitute values to get a "real" URL using ReplaceSearchTerms().
38 //
39 // TemplateURLRefs always have a non-NULL |owner_| TemplateURL, which they
40 // access in order to get at important data like the underlying URL string or
41 // the associated Profile.
42 class TemplateURLRef {
43  public:
44   // Magic numbers to pass to ReplaceSearchTerms() for the |accepted_suggestion|
45   // parameter.  Most callers aren't using Suggest capabilities and should just
46   // pass NO_SUGGESTIONS_AVAILABLE.
47   // NOTE: Because positive values are meaningful, make sure these are negative!
48   enum AcceptedSuggestion {
49     NO_SUGGESTION_CHOSEN = -1,
50     NO_SUGGESTIONS_AVAILABLE = -2,
51   };
52
53   // Which kind of URL within our owner we are.  This allows us to get at the
54   // correct string field. Use |INDEXED| to indicate that the numerical
55   // |index_in_owner_| should be used instead.
56   enum Type {
57     SEARCH,
58     SUGGEST,
59     IMAGE,
60     NEW_TAB,
61     CONTEXTUAL_SEARCH,
62     INDEXED
63   };
64
65   // Type to store <content_type, post_data> pair for POST URLs.
66   // The |content_type|(first part of the pair) is the content-type of
67   // the |post_data|(second part of the pair) which is encoded in
68   // "multipart/form-data" format, it also contains the MIME boundary used in
69   // the |post_data|. See http://tools.ietf.org/html/rfc2046 for the details.
70   typedef std::pair<std::string, std::string> PostContent;
71
72   // Enumeration of the known search or suggest request sources. These values
73   // are not persisted or used in histograms; thus can be freely changed.
74   enum RequestSource {
75     SEARCHBOX,          // Omnibox or the NTP realbox. The default.
76     CROS_APP_LIST,      // Chrome OS app list search box.
77     NON_SEARCHBOX_NTP,  // Suggestions for the NTP surface.
78   };
79
80   // This struct encapsulates arguments passed to
81   // TemplateURLRef::ReplaceSearchTerms methods.  By default, only search_terms
82   // is required and is passed in the constructor.
83   struct SearchTermsArgs {
84     SearchTermsArgs();
85     explicit SearchTermsArgs(const std::u16string& search_terms);
86     SearchTermsArgs(const SearchTermsArgs& other);
87     ~SearchTermsArgs();
88
89     struct ContextualSearchParams {
90       ContextualSearchParams();
91       // Modern constructor, used when the content is sent in the HTTP header
92       // instead of as CGI parameters.
93       // The |version| tell the server which version of the client is making
94       // this request.
95       // The |contextual_cards_version| tells the server which version of
96       // contextual cards integration is being used by the client.
97       // The |home_country| is an ISO country code for the country that the user
98       // considers their permanent home (which may be different from the country
99       // they are currently visiting).  Pass an empty string if none available.
100       // The |previous_event_id| is an identifier previously returned by the
101       // server to identify that user interaction.
102       // The |previous_event_results| are the results of the user-interaction of
103       // that previous request.
104       // The "previous_xyz" parameters are documented in go/cs-sanitized.
105       // The |is_exact_search| allows the search request to be narrowed down to
106       // an "exact" search only, meaning just search for X rather than X +
107       // whatever else is in the context.  The returned search term should not
108       // be expanded, and the server will honor this along with creating a
109       // narrow Search Term.
110       // The |source_lang| specifies a source language hint to apply for
111       // translation or to indicate that translation might be appropriate.
112       // This comes from CLD evaluating the selection and/or page content.
113       // The |target_lang| specifies the best language to translate into for
114       // the user, which also indicates when translation is appropriate or
115       // helpful.  This comes from the Chrome Language Model.
116       // The |fluent_languages| string specifies the languages the user
117       // is fluent in reading.  This acts as an alternate set of languages
118       // to consider translating into.  The languages are ordered by
119       // fluency, and encoded as a comma-separated list of BCP 47 languages.
120       // The |related_searches_stamp| string contains an information that
121       // indicates experiment status and server processing results so that
122       // can be logged in GWS Sawmill logs for offline analysis for the
123       // Related Searches MVP experiment.
124       ContextualSearchParams(int version,
125                              int contextual_cards_version,
126                              std::string home_country,
127                              int64_t previous_event_id,
128                              int previous_event_results,
129                              bool is_exact_search,
130                              std::string source_lang,
131                              std::string target_lang,
132                              std::string fluent_languages,
133                              std::string related_searches_stamp);
134       ContextualSearchParams(const ContextualSearchParams& other);
135       ~ContextualSearchParams();
136
137       // Estimates dynamic memory usage.
138       // See base/trace_event/memory_usage_estimator.h for more info.
139       size_t EstimateMemoryUsage() const;
140
141       // The version of contextual search.
142       int version = -1;
143
144       // The version of Contextual Cards data to request.
145       // A value of 0 indicates no data needed.
146       int contextual_cards_version = 0;
147
148       // The locale of the user's home country in an ISO country code format,
149       // or an empty string if not available.  This indicates where the user
150       // resides, not where they currently are.
151       std::string home_country;
152
153       // An EventID from a previous interaction (sent by server, recorded by
154       // client).
155       int64_t previous_event_id = 0l;
156
157       // An encoded set of booleans that represent the interaction results from
158       // the previous event.
159       int previous_event_results = 0;
160
161       // A flag that restricts the search to exactly match the selection rather
162       // than expanding the Search Term to include other words in the context.
163       bool is_exact_search = false;
164
165       // Source language string to translate from.
166       std::string source_lang;
167
168       // Target language string to be translated into.
169       std::string target_lang;
170
171       // Alternate target languages that the user is fluent in, encoded in a
172       // single string.
173       std::string fluent_languages;
174
175       // Experiment arm and processing information for the Related Searches
176       // experiment. The value is an arbitrary string that starts with a
177       // schema version number.
178       std::string related_searches_stamp;
179     };
180
181     // Estimates dynamic memory usage.
182     // See base/trace_event/memory_usage_estimator.h for more info.
183     size_t EstimateMemoryUsage() const;
184
185     // The search terms (query).
186     std::u16string search_terms;
187
188     // The original (input) query.
189     std::u16string original_query;
190
191     // The type the original input query was identified as.
192     metrics::OmniboxInputType input_type = metrics::OmniboxInputType::EMPTY;
193
194     // Specifies how the user last interacted with the searchbox UI element.
195     metrics::OmniboxFocusType focus_type =
196         metrics::OmniboxFocusType::INTERACTION_DEFAULT;
197
198     // The optional assisted query stats, aka AQS, used for logging purposes.
199     // This string contains impressions of all autocomplete matches shown
200     // at the query submission time.  For privacy reasons, we require the
201     // search provider to support HTTPS protocol in order to receive the AQS
202     // param.
203     // For more details, see go/chrome-suggest-logging.
204     std::string assisted_query_stats;
205
206     // The optional searchbox stats, reported as gs_lcrp for logging purposes.
207     // This proto message contains information such as impressions of all
208     // autocomplete matches shown at the query submission time.
209     // For privacy reasons, we require the search provider to support HTTPS
210     // protocol in order to receive the gs_lcrp param.
211     // For more details, see go/chrome-suggest-logging-improvement.
212     metrics::ChromeSearchboxStats searchbox_stats;
213
214     // TODO: Remove along with "aq" CGI param.
215     int accepted_suggestion = NO_SUGGESTIONS_AVAILABLE;
216
217     // The 0-based position of the cursor within the query string at the time
218     // the request was issued.  Set to std::u16string::npos if not used.
219     size_t cursor_position = std::u16string::npos;
220
221     // The URL of the current webpage to be used for experimental zero-prefix
222     // suggestions.
223     std::string current_page_url;
224
225     // Which omnibox the user used to type the prefix.
226     metrics::OmniboxEventProto::PageClassification page_classification =
227         metrics::OmniboxEventProto::INVALID_SPEC;
228
229     // Optional session token.
230     std::string session_token;
231
232     // Prefetch query and type.
233     std::string prefetch_query;
234     std::string prefetch_query_type;
235
236     // Additional query params to append to the request.
237     std::string additional_query_params;
238
239     // If set, ReplaceSearchTerms() will automatically append any extra query
240     // params specified via the --extra-search-query-params command-line
241     // argument.  Generally, this should be set when dealing with the search
242     // TemplateURLRefs of the default search engine and the caller cares
243     // about the query portion of the URL.  Since neither TemplateURLRef nor
244     // indeed TemplateURL know whether a TemplateURL is the default search
245     // engine, callers instead must set this manually.
246     bool append_extra_query_params_from_command_line = false;
247
248     // The raw content of an image thumbnail that will be used as a query for
249     // search-by-image frontend.
250     std::string image_thumbnail_content;
251
252     // When searching for an image, the URL of the original image. Callers
253     // should leave this empty for images specified via data: URLs.
254     GURL image_url;
255
256     // When searching for an image, the original size of the image.
257     gfx::Size image_original_size;
258
259     // Source of the search or suggest request.
260     RequestSource request_source = SEARCHBOX;
261
262     // Whether the query is being fetched as a prefetch request before the user
263     // actually searches for the search terms.
264     bool is_prefetch = false;
265
266     ContextualSearchParams contextual_search_params;
267
268     // The cache duration to be sent as a query string parameter in the zero
269     // suggest requests, if non-zero.
270     uint32_t zero_suggest_cache_duration_sec = 0;
271
272     // Whether the request should bypass the HTTP cache, i.e., a "shift-reload".
273     // If true, the net::LOAD_BYPASS_CACHE load flag will be set on the request.
274     bool bypass_cache = false;
275   };
276
277   TemplateURLRef(const TemplateURL* owner, Type type);
278   TemplateURLRef(const TemplateURL* owner, size_t index_in_owner);
279   ~TemplateURLRef();
280
281   TemplateURLRef(const TemplateURLRef& source);
282   TemplateURLRef& operator=(const TemplateURLRef& source);
283
284   // Returns the raw URL. None of the parameters will have been replaced.
285   std::string GetURL() const;
286
287   // Returns the raw string of the post params. Please see comments in
288   // prepopulated_engines_schema.json for the format.
289   std::string GetPostParamsString() const;
290
291   // Returns true if this URL supports search term replacement.
292   bool SupportsReplacement(const SearchTermsData& search_terms_data) const;
293
294   // Returns a string that is the result of replacing the search terms in
295   // the url with the specified arguments.  We use our owner's input encoding.
296   //
297   // If this TemplateURLRef does not support replacement (SupportsReplacement
298   // returns false), an empty string is returned.
299   // If this TemplateURLRef uses POST, and |post_content| is not NULL, the
300   // |post_params_| will be replaced, encoded in "multipart/form-data" format
301   // and stored into |post_content|.
302   std::string ReplaceSearchTerms(const SearchTermsArgs& search_terms_args,
303                                  const SearchTermsData& search_terms_data,
304                                  PostContent* post_content) const;
305
306   // TODO(jnd): remove the following ReplaceSearchTerms definition which does
307   // not have |post_content| parameter once all reference callers pass
308   // |post_content| parameter.
309   std::string ReplaceSearchTerms(
310       const SearchTermsArgs& search_terms_args,
311       const SearchTermsData& search_terms_data) const {
312     return ReplaceSearchTerms(search_terms_args, search_terms_data, NULL);
313   }
314
315   // Returns true if the TemplateURLRef is valid. An invalid TemplateURLRef is
316   // one that contains unknown terms, or invalid characters.
317   bool IsValid(const SearchTermsData& search_terms_data) const;
318
319   // Returns a string representation of this TemplateURLRef suitable for
320   // display. The display format is the same as the format used by Firefox.
321   std::u16string DisplayURL(const SearchTermsData& search_terms_data) const;
322
323   // Converts a string as returned by DisplayURL back into a string as
324   // understood by TemplateURLRef.
325   static std::string DisplayURLToURLRef(const std::u16string& display_url);
326
327   // If this TemplateURLRef is valid and contains one search term, this returns
328   // the host/path of the URL, otherwise this returns an empty string.
329   const std::string& GetHost(const SearchTermsData& search_terms_data) const;
330   std::string GetPath(const SearchTermsData& search_terms_data) const;
331
332   // If this TemplateURLRef is valid and contains one search term
333   // in its query or ref, this returns the key of the search term,
334   // otherwise this returns an empty string.
335   const std::string& GetSearchTermKey(
336       const SearchTermsData& search_terms_data) const;
337
338   // If this TemplateURLRef is valid and contains one search term,
339   // this returns the location of the search term,
340   // otherwise this returns url::Parsed::QUERY.
341   url::Parsed::ComponentType GetSearchTermKeyLocation(
342       const SearchTermsData& search_terms_data) const;
343
344   // If this TemplateURLRef is valid and contains one search term,
345   // this returns the fixed prefix before the search term,
346   // otherwise this returns an empty string.
347   const std::string& GetSearchTermValuePrefix(
348       const SearchTermsData& search_terms_data) const;
349
350   // If this TemplateURLRef is valid and contains one search term,
351   // this returns the fixed suffix after the search term,
352   // otherwise this returns an empty string.
353   const std::string& GetSearchTermValueSuffix(
354       const SearchTermsData& search_terms_data) const;
355
356   // Converts the specified term in our owner's encoding to a std::u16string.
357   std::u16string SearchTermToString16(const base::StringPiece& term) const;
358
359   // Returns true if this TemplateURLRef has a replacement term of
360   // {google:baseURL} or {google:baseSuggestURL}.
361   bool HasGoogleBaseURLs(const SearchTermsData& search_terms_data) const;
362
363   // Use the pattern referred to by this TemplateURLRef to match the provided
364   // |url| and extract |search_terms| from it. Returns true if the pattern
365   // matches, even if |search_terms| is empty. In this case
366   // |search_term_component|, if not NULL, indicates whether the search terms
367   // were found in the query or the ref parameters; and |search_terms_position|,
368   // if not NULL, contains the position of the search terms in the query or the
369   // ref parameters. Returns false and an empty |search_terms| if the pattern
370   // does not match.
371   bool ExtractSearchTermsFromURL(
372       const GURL& url,
373       std::u16string* search_terms,
374       const SearchTermsData& search_terms_data,
375       url::Parsed::ComponentType* search_term_component,
376       url::Component* search_terms_position) const;
377
378   // Whether the URL uses POST (as opposed to GET).
379   bool UsesPOSTMethod(const SearchTermsData& search_terms_data) const;
380
381   // Estimates dynamic memory usage.
382   // See base/trace_event/memory_usage_estimator.h for more info.
383   size_t EstimateMemoryUsage() const;
384
385  private:
386   friend class TemplateURL;
387   friend class TemplateURLTest;
388   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, SetPrepopulatedAndParse);
389   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterKnown);
390   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterUnknown);
391   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLEmpty);
392   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoTemplateEnd);
393   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoKnownParameters);
394   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLTwoParameters);
395   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNestedParameter);
396   FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, URLRefTestImageURLWithPOST);
397
398   // Enumeration of the known types.
399   enum ReplacementType {
400     ENCODING,
401     GOOGLE_ASSISTED_QUERY_STATS,
402     GOOGLE_BASE_SEARCH_BY_IMAGE_URL,
403     GOOGLE_BASE_SUGGEST_URL,
404     GOOGLE_BASE_URL,
405     GOOGLE_CLIENT_CACHE_TIME_TO_LIVE,
406     GOOGLE_CONTEXTUAL_SEARCH_CONTEXT_DATA,
407     GOOGLE_CONTEXTUAL_SEARCH_VERSION,
408     GOOGLE_CURRENT_PAGE_URL,
409     GOOGLE_CURSOR_POSITION,
410     GOOGLE_IMAGE_ORIGINAL_HEIGHT,
411     GOOGLE_IMAGE_ORIGINAL_WIDTH,
412     GOOGLE_IMAGE_SEARCH_SOURCE,
413     GOOGLE_IMAGE_THUMBNAIL_BASE64,
414     GOOGLE_IMAGE_THUMBNAIL,
415     GOOGLE_IMAGE_URL,
416     GOOGLE_INPUT_TYPE,
417     GOOGLE_IOS_SEARCH_LANGUAGE,
418     GOOGLE_NTP_IS_THEMED,
419     GOOGLE_OMNIBOX_FOCUS_TYPE,
420     GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION,
421     GOOGLE_PAGE_CLASSIFICATION,
422     GOOGLE_PREFETCH_QUERY,
423     GOOGLE_PREFETCH_SOURCE,
424     GOOGLE_RLZ,
425     GOOGLE_SEARCH_CLIENT,
426     GOOGLE_SEARCH_FIELDTRIAL_GROUP,
427     GOOGLE_SEARCH_VERSION,
428     GOOGLE_SEARCHBOX_STATS,
429     GOOGLE_SESSION_TOKEN,
430     GOOGLE_SUGGEST_CLIENT,
431     GOOGLE_SUGGEST_REQUEST_ID,
432     GOOGLE_UNESCAPED_SEARCH_TERMS,
433     LANGUAGE,
434     MAIL_RU_REFERRAL_ID,
435     SEARCH_TERMS,
436     YANDEX_REFERRAL_ID,
437   };
438
439   // Used to identify an element of the raw url that can be replaced.
440   struct Replacement {
441     Replacement(ReplacementType type, size_t index)
442         : type(type), index(index), is_post_param(false) {}
443     ReplacementType type;
444     size_t index;
445     // Indicates the location in where the replacement is replaced. If
446     // |is_post_param| is false, |index| indicates the byte position in
447     // |parsed_url_|. Otherwise, |index| is the index of |post_params_|.
448     bool is_post_param;
449   };
450
451   // Stores a single parameter for a POST.
452   struct PostParam {
453     std::string name;
454     std::string value;
455     std::string content_type;
456
457     // Estimates dynamic memory usage.
458     // See base/trace_event/memory_usage_estimator.h for more info.
459     size_t EstimateMemoryUsage() const;
460   };
461
462   // The list of elements to replace.
463   typedef std::vector<struct Replacement> Replacements;
464   typedef std::vector<PostParam> PostParams;
465
466   // TemplateURLRef internally caches values to make replacement quick. This
467   // method invalidates any cached values.
468   void InvalidateCachedValues() const;
469
470   // Parses the parameter in url at the specified offset. start/end specify the
471   // range of the parameter in the url, including the braces. If the parameter
472   // is valid, url is updated to reflect the appropriate parameter. If
473   // the parameter is one of the known parameters an element is added to
474   // replacements indicating the type and range of the element. The original
475   // parameter is erased from the url.
476   //
477   // If the parameter is not a known parameter, false is returned. If this is a
478   // prepopulated URL, the parameter is erased, otherwise it is left alone.
479   bool ParseParameter(size_t start,
480                       size_t end,
481                       std::string* url,
482                       Replacements* replacements) const;
483
484   // Parses the specified url, replacing parameters as necessary. If
485   // successful, valid is set to true, and the parsed url is returned. For all
486   // known parameters that are encountered an entry is added to replacements.
487   // If there is an error parsing the url, valid is set to false, and an empty
488   // string is returned.  If the URL has the POST parameters, they will be
489   // parsed into |post_params| which will be further replaced with real search
490   // terms data and encoded in "multipart/form-data" format to generate the
491   // POST data.
492   std::string ParseURL(const std::string& url,
493                        Replacements* replacements,
494                        PostParams* post_params,
495                        bool* valid) const;
496
497   // If the url has not yet been parsed, ParseURL is invoked.
498   // NOTE: While this is const, it modifies parsed_, valid_, parsed_url_ and
499   // search_offset_.
500   void ParseIfNecessary(const SearchTermsData& search_terms_data) const;
501
502   // Parses a wildcard out of |path|, putting the parsed path in |path_prefix_|
503   // and |path_suffix_| and setting |path_wildcard_present_| to true.
504   // In the absence of a wildcard, the full path will be contained in
505   // |path_prefix_| and |path_wildcard_present_| will be false.
506   void ParsePath(const std::string& path) const;
507
508   // Returns whether the path portion of this template URL is equal to the path
509   // in |url|, checking that URL is prefixed/suffixed by
510   // |path_prefix_|/|path_suffix_| if |path_wildcard_present_| is true, or equal
511   // to |path_prefix_| otherwise.
512   bool PathIsEqual(const GURL& url) const;
513
514   // Extracts the query key and host from the url.
515   void ParseHostAndSearchTermKey(
516       const SearchTermsData& search_terms_data) const;
517
518   // Encode post parameters in "multipart/form-data" format and store it
519   // inside |post_content|. Returns false if errors are encountered during
520   // encoding. This method is called each time ReplaceSearchTerms gets called.
521   bool EncodeFormData(const PostParams& post_params,
522                       PostContent* post_content) const;
523
524   // Handles a replacement by using real term data. If the replacement
525   // belongs to a PostParam, the PostParam will be replaced by the term data.
526   // Otherwise, the term data will be inserted at the place that the
527   // replacement points to.
528   void HandleReplacement(const std::string& name,
529                          const std::string& value,
530                          const Replacement& replacement,
531                          std::string* url) const;
532
533   // Replaces all replacements in |parsed_url_| with their actual values and
534   // returns the result.  This is the main functionality of
535   // ReplaceSearchTerms().
536   std::string HandleReplacements(
537       const SearchTermsArgs& search_terms_args,
538       const SearchTermsData& search_terms_data,
539       PostContent* post_content) const;
540
541   // The TemplateURL that contains us.  This should outlive us.
542   raw_ptr<const TemplateURL> owner_;
543
544   // What kind of URL we are.
545   Type type_;
546
547   // If |type_| is |INDEXED|, this |index_in_owner_| is used instead to refer to
548   // a url within our owner.
549   size_t index_in_owner_ = 0;
550
551   // Whether the URL has been parsed.
552   mutable bool parsed_ = false;
553
554   // Whether the url was successfully parsed.
555   mutable bool valid_ = false;
556
557   // The parsed URL. All terms have been stripped out of this with
558   // replacements_ giving the index of the terms to replace.
559   mutable std::string parsed_url_;
560
561   // Do we support search term replacement?
562   mutable bool supports_replacements_ = false;
563
564   // The replaceable parts of url (parsed_url_). These are ordered by index
565   // into the string, and may be empty.
566   mutable Replacements replacements_;
567
568   // Whether the path contains a wildcard.
569   mutable bool path_wildcard_present_ = false;
570
571   // Host, port, path, key and location of the search term. These are only set
572   // if the url contains one search term.
573   mutable std::string host_;
574   mutable std::string port_;
575   mutable std::string path_prefix_;
576   mutable std::string path_suffix_;
577   mutable std::string search_term_key_;
578   mutable url::Parsed::ComponentType search_term_key_location_ =
579       url::Parsed::QUERY;
580   mutable std::string search_term_value_prefix_;
581   mutable std::string search_term_value_suffix_;
582
583   mutable PostParams post_params_;
584
585   // Whether the contained URL is a pre-populated URL.
586   bool prepopulated_ = false;
587 };
588
589
590 // TemplateURL ----------------------------------------------------------------
591
592 // A TemplateURL represents a single "search engine", defined primarily as a
593 // subset of the Open Search Description Document
594 // (http://www.opensearch.org/Specifications/OpenSearch) plus some extensions.
595 // One TemplateURL contains several TemplateURLRefs, which correspond to various
596 // different capabilities (e.g. doing searches or getting suggestions), as well
597 // as a TemplateURLData containing other details like the name, keyword, etc.
598 //
599 // TemplateURLs are intended to be read-only for most users.
600 // The TemplateURLService, which handles storing and manipulating TemplateURLs,
601 // is made a friend so that it can be the exception to this pattern.
602 class TemplateURL {
603  public:
604   using TemplateURLVector = std::vector<TemplateURL*>;
605   using OwnedTemplateURLVector = std::vector<std::unique_ptr<TemplateURL>>;
606
607   // These values are not persisted and can be freely changed.
608   // Their integer values are used for choosing the best engine during keyword
609   // conflicts, so their relative ordering should not be changed without careful
610   // thought about what happens during version skew.
611   enum Type {
612     // Installed only on this device. Should not be synced. This is not common.
613     LOCAL = 0,
614     // Regular search engine. This is the most common, and the ONLY type synced.
615     NORMAL = 1,
616     // Installed by extension through Override Settings API. Not synced.
617     NORMAL_CONTROLLED_BY_EXTENSION = 2,
618     // The keyword associated with an extension that uses the Omnibox API.
619     // Not synced.
620     OMNIBOX_API_EXTENSION = 3,
621   };
622
623   // An AssociatedExtensionInfo represents information about the extension that
624   // added the search engine.
625   struct AssociatedExtensionInfo {
626     AssociatedExtensionInfo(const std::string& extension_id,
627                             base::Time install_time,
628                             bool wants_to_be_default_engine);
629     ~AssociatedExtensionInfo();
630
631     // Estimates dynamic memory usage.
632     // See base/trace_event/memory_usage_estimator.h for more info.
633     size_t EstimateMemoryUsage() const;
634
635     std::string extension_id;
636
637     // Used to resolve conflicts when there are multiple extensions specifying
638     // the default search engine. The most recently-installed wins.
639     base::Time install_time;
640
641     // Whether the search engine is supposed to be default.
642     bool wants_to_be_default_engine;
643   };
644
645   explicit TemplateURL(const TemplateURLData& data, Type type = NORMAL);
646
647   // Constructor for extension controlled engine. |type| must be
648   // NORMAL_CONTROLLED_BY_EXTENSION or OMNIBOX_API_EXTENSION.
649   TemplateURL(const TemplateURLData& data,
650               Type type,
651               std::string extension_id,
652               base::Time install_time,
653               bool wants_to_be_default_engine);
654
655   TemplateURL(const TemplateURL&) = delete;
656   TemplateURL& operator=(const TemplateURL&) = delete;
657
658   ~TemplateURL();
659
660   // For two engines with the same keyword, |this| and |other|,
661   // returns true if |this| is strictly better than |other|.
662   //
663   // While normal engines must all have distinct keywords, policy-created,
664   // extension-controlled and omnibox API engines may have the same keywords as
665   // each other or as normal engines.  In these cases, policy-create engines
666   // override omnibox API engines, which override extension-controlled engines,
667   // which override normal engines.
668   //
669   // If there is still a conflict after this, compare by safe-for-autoreplace,
670   // then last modified date, then use the sync guid as a tiebreaker.
671   //
672   // TODO(tommycli): I'd like to use this to resolve Sync conflicts in the
673   // future, but we need a total ordering of TemplateURLs. That's not the case
674   // today, because the sync GUIDs are not actually globally unique, so there
675   // can be a genuine tie, which is not good, because then two different clients
676   // could choose to resolve the conflict in two different ways.
677   bool IsBetterThanEngineWithConflictingKeyword(const TemplateURL* other) const;
678
679   // Generates a suitable keyword for the specified url, which must be valid.
680   // This is guaranteed not to return an empty string, since TemplateURLs should
681   // never have an empty keyword.
682   static std::u16string GenerateKeyword(const GURL& url);
683
684   // Generates a favicon URL from the specified url.
685   static GURL GenerateFaviconURL(const GURL& url);
686
687   // Returns true if |t_url| and |data| are equal in all meaningful respects.
688   // Static to allow either or both params to be NULL.
689   static bool MatchesData(const TemplateURL* t_url,
690                           const TemplateURLData* data,
691                           const SearchTermsData& search_terms_data);
692
693   const TemplateURLData& data() const { return data_; }
694
695   const std::u16string& short_name() const { return data_.short_name(); }
696   // An accessor for the short_name, but adjusted so it can be appropriately
697   // displayed even if it is LTR and the UI is RTL.
698   std::u16string AdjustedShortNameForLocaleDirection() const;
699
700   const std::u16string& keyword() const { return data_.keyword(); }
701
702   const std::string& url() const { return data_.url(); }
703   const std::string& suggestions_url() const { return data_.suggestions_url; }
704   const std::string& image_url() const { return data_.image_url; }
705   const std::string& new_tab_url() const { return data_.new_tab_url; }
706   const std::string& contextual_search_url() const {
707     return data_.contextual_search_url;
708   }
709   const std::string& search_url_post_params() const {
710     return data_.search_url_post_params;
711   }
712   const std::string& suggestions_url_post_params() const {
713     return data_.suggestions_url_post_params;
714   }
715   const std::string& image_url_post_params() const {
716     return data_.image_url_post_params;
717   }
718   const std::string& side_search_param() const {
719     return data_.side_search_param;
720   }
721   const std::string& side_image_search_param() const {
722     return data_.side_image_search_param;
723   }
724   const std::u16string& image_search_branding_label() const {
725     return !data_.image_search_branding_label.empty()
726                ? data_.image_search_branding_label
727                : short_name();
728   }
729   const std::vector<std::string>& alternate_urls() const {
730     return data_.alternate_urls;
731   }
732   const GURL& favicon_url() const { return data_.favicon_url; }
733
734   const GURL& logo_url() const { return data_.logo_url; }
735
736   const GURL& doodle_url() const { return data_.doodle_url; }
737
738   const GURL& originating_url() const { return data_.originating_url; }
739
740   bool safe_for_autoreplace() const { return data_.safe_for_autoreplace; }
741
742   const std::vector<std::string>& input_encodings() const {
743     return data_.input_encodings;
744   }
745
746   TemplateURLID id() const { return data_.id; }
747
748   base::Time date_created() const { return data_.date_created; }
749   base::Time last_modified() const { return data_.last_modified; }
750   base::Time last_visited() const { return data_.last_visited; }
751
752   bool created_by_policy() const { return data_.created_by_policy; }
753   bool created_from_play_api() const { return data_.created_from_play_api; }
754
755   int usage_count() const { return data_.usage_count; }
756
757   int prepopulate_id() const { return data_.prepopulate_id; }
758
759   const std::string& sync_guid() const { return data_.sync_guid; }
760
761   TemplateURLData::ActiveStatus is_active() const { return data_.is_active; }
762
763   int starter_pack_id() const { return data_.starter_pack_id; }
764
765   const std::vector<TemplateURLRef>& url_refs() const { return url_refs_; }
766   const TemplateURLRef& url_ref() const {
767     // Sanity check for https://crbug.com/781703.
768     CHECK(!url_refs_.empty());
769     return url_refs_.back();
770   }
771   const TemplateURLRef& suggestions_url_ref() const {
772     return suggestions_url_ref_;
773   }
774   const TemplateURLRef& image_url_ref() const { return image_url_ref_; }
775   const TemplateURLRef& new_tab_url_ref() const { return new_tab_url_ref_; }
776   const TemplateURLRef& contextual_search_url_ref() const {
777     return contextual_search_url_ref_;
778   }
779
780   Type type() const { return type_; }
781
782   const AssociatedExtensionInfo* GetExtensionInfoForTesting() const {
783     return extension_info_.get();
784   }
785
786   // Returns true if |url| supports replacement.
787   bool SupportsReplacement(const SearchTermsData& search_terms_data) const;
788
789   // Returns true if any URLRefs use Googe base URLs.
790   bool HasGoogleBaseURLs(const SearchTermsData& search_terms_data) const;
791
792   // Returns true if this TemplateURL uses Google base URLs and has a keyword
793   // of "google.TLD".  We use this to decide whether we can automatically
794   // update the keyword to reflect the current Google base URL TLD.
795   bool IsGoogleSearchURLWithReplaceableKeyword(
796       const SearchTermsData& search_terms_data) const;
797
798   // Returns true if the keywords match or if
799   // IsGoogleSearchURLWithReplaceableKeyword() is true for both |this| and
800   // |other|.
801   bool HasSameKeywordAs(const TemplateURLData& other,
802                         const SearchTermsData& search_terms_data) const;
803
804   // Returns the id of the extension that added this search engine. Only call
805   // this for TemplateURLs of type NORMAL_CONTROLLED_BY_EXTENSION or
806   // OMNIBOX_API_EXTENSION.
807   std::string GetExtensionId() const;
808
809   // Returns the type of this search engine, or SEARCH_ENGINE_OTHER if no
810   // engines match.
811   SearchEngineType GetEngineType(
812       const SearchTermsData& search_terms_data) const;
813
814   // Returns the type of this search engine, i.e. whether the engine is a
815   // prepopulated engine, starter pack engine, or not built-in.
816   BuiltinEngineType GetBuiltinEngineType() const;
817
818   // Use the alternate URLs and the search URL to match the provided |url|
819   // and extract |search_terms| from it. Returns false and an empty
820   // |search_terms| if no search terms can be matched. The URLs are matched in
821   // the order listed in |url_refs_| (see comment there).
822   bool ExtractSearchTermsFromURL(const GURL& url,
823                                  const SearchTermsData& search_terms_data,
824                                  std::u16string* search_terms) const;
825
826   // Returns true if non-empty search terms could be extracted from |url| using
827   // ExtractSearchTermsFromURL(). In other words, this returns whether |url|
828   // could be the result of performing a search with |this|.
829   bool IsSearchURL(const GURL& url,
830                    const SearchTermsData& search_terms_data) const;
831
832   // Given a |url| corresponding to this TemplateURL, identifies the search
833   // terms and replaces them with the ones in |search_terms_args|, leaving the
834   // other parameters untouched. If the replacement fails, returns false and
835   // leaves |result| untouched. This is used by mobile ports to perform query
836   // refinement.
837   bool ReplaceSearchTermsInURL(
838       const GURL& url,
839       const TemplateURLRef::SearchTermsArgs& search_terms_args,
840       const SearchTermsData& search_terms_data,
841       GURL* result) const;
842
843   // Encodes the search terms from |search_terms_args| so that we know the
844   // |input_encoding|. Returns the |encoded_terms| and the
845   // |encoded_original_query|. |encoded_terms| may be escaped as path or query
846   // depending on |is_in_query|; |encoded_original_query| is always escaped as
847   // query.
848   void EncodeSearchTerms(
849       const TemplateURLRef::SearchTermsArgs& search_terms_args,
850       bool is_in_query,
851       std::string* input_encoding,
852       std::u16string* encoded_terms,
853       std::u16string* encoded_original_query) const;
854
855   // Returns the search url for this template URL and the optional search terms.
856   // Uses something obscure as the default value for the search terms argument
857   // so that in the rare case the term replaces the URL it's unlikely another
858   // keyword would have the same url.
859   // Returns an empty GURL if this template URL has no url().
860   GURL GenerateSearchURL(
861       const SearchTermsData& search_terms_data,
862       const std::u16string& search_terms = u"blah.blah.blah.blah.blah") const;
863
864   // Returns the suggest endpoint URL for this template URL.
865   // Returns an empty GURL if this template URL has no suggestions_url().
866   GURL GenerateSuggestionURL(const SearchTermsData& search_terms_data) const;
867
868   // Returns true if this search engine supports the side search feature.
869   bool IsSideSearchSupported() const;
870
871   // Returns true if this search engine supports the side image search feature.
872   bool IsSideImageSearchSupported() const;
873
874   // Takes a search URL belonging to this search engine and generates the URL
875   // appropriate for the side search side panel.
876   GURL GenerateSideSearchURL(const GURL& search_url,
877                              const std::string& version,
878                              const SearchTermsData& search_terms_data) const;
879
880   // Takes a search URL belonging to this image search engine and generates the
881   // URL appropriate for the image search in the side panel.
882   GURL GenerateSideImageSearchURL(const GURL& image_search_url,
883                                   const std::string& version) const;
884
885   // Takes a search URL that belongs to this image search in the side panel and
886   // removes the side image search param from the URL.
887   GURL RemoveSideImageSearchParamFromURL(const GURL& image_search_url) const;
888
889   // TemplateURL internally caches values derived from a passed SearchTermsData
890   // to make its functions quick. This method invalidates any cached values and
891   // it should be called after SearchTermsData has been changed.
892   void InvalidateCachedValues() const;
893
894   // Estimates dynamic memory usage.
895   // See base/trace_event/memory_usage_estimator.h for more info.
896   size_t EstimateMemoryUsage() const;
897
898   // Returns whether |url| query contains a side search param.
899   bool ContainsSideSearchParam(const GURL& url) const;
900
901   // Returns whether |url| query contains a side image search param.
902   bool ContainsSideImageSearchParam(const GURL& url) const;
903
904  private:
905   friend class TemplateURLService;
906
907   void CopyFrom(const TemplateURL& other);
908
909   void SetURL(const std::string& url);
910   void SetPrepopulateId(int id);
911
912   // Resets the keyword if IsGoogleSearchURLWithReplaceableKeyword() or |force|.
913   // The |force| parameter is useful when the existing keyword is known to be
914   // a placeholder.  The resulting keyword is generated using
915   // GenerateSearchURL() and GenerateKeyword().
916   void ResetKeywordIfNecessary(const SearchTermsData& search_terms_data,
917                                bool force);
918
919   // Resizes the |url_refs_| vector, which always holds the search URL as the
920   // last item.
921   void ResizeURLRefVector();
922
923   // Uses the alternate URLs and the search URL to match the provided |url|
924   // and extract |search_terms| from it as well as the |search_terms_component|
925   // (either REF or QUERY) and |search_terms_component| at which the
926   // |search_terms| are found in |url|. See also ExtractSearchTermsFromURL().
927   bool FindSearchTermsInURL(const GURL& url,
928                             const SearchTermsData& search_terms_data,
929                             std::u16string* search_terms,
930                             url::Parsed::ComponentType* search_terms_component,
931                             url::Component* search_terms_position) const;
932
933   TemplateURLData data_;
934
935   // Contains TemplateURLRefs corresponding to the alternate URLs and the search
936   // URL, in priority order: the URL at index 0 is treated as the highest
937   // priority and the primary search URL is treated as the lowest priority.  For
938   // example, if a TemplateURL has alternate URL "http://foo/#q={searchTerms}"
939   // and search URL "http://foo/?q={searchTerms}", and the URL to be decoded is
940   // "http://foo/?q=a#q=b", the alternate URL will match first and the decoded
941   // search term will be "b".  Note that since every TemplateURLRef has a
942   // primary search URL, this vector is never empty.
943   std::vector<TemplateURLRef> url_refs_;
944
945   TemplateURLRef suggestions_url_ref_;
946   TemplateURLRef image_url_ref_;
947   TemplateURLRef new_tab_url_ref_;
948   TemplateURLRef contextual_search_url_ref_;
949   std::unique_ptr<AssociatedExtensionInfo> extension_info_;
950
951   const Type type_;
952
953   // Caches the computed engine type across successive calls to GetEngineType().
954   mutable SearchEngineType engine_type_;
955
956   // TODO(sky): Add date last parsed OSD file.
957 };
958
959 #endif  // COMPONENTS_SEARCH_ENGINES_TEMPLATE_URL_H_