template_url.h 39 KB

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