template_url.h revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2010 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 CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_H_
6#define CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_H_
7#pragma once
8
9#include <string>
10#include <vector>
11
12#include "base/gtest_prod_util.h"
13#include "base/time.h"
14#include "chrome/browser/search_engines/search_engine_type.h"
15#include "chrome/browser/search_engines/template_url_id.h"
16#include "googleurl/src/gurl.h"
17
18class PrefService;
19class SearchTermsData;
20class TemplateURL;
21class WebDataService;
22struct WDKeywordsResult;
23
24// TemplateURL represents the relevant portions of the Open Search Description
25// Document (http://www.opensearch.org/Specifications/OpenSearch).
26// The main use case for TemplateURL is to use the TemplateURLRef returned by
27// suggestions_url or url for keyword/suggestion expansion:
28// . suggestions_url describes a URL that is ideal for as you type suggestions.
29//   The returned results are in the mime type application/x-suggestions+json.
30// . url describes a URL that may be used as a shortcut. Returned results are
31//   are text/html.
32// Before using either one, make sure it's non-NULL, and if you intend to use
33// it to replace search terms, make sure SupportsReplacement returns true.
34// To use either URL invoke the ReplaceSearchTerms method on the corresponding
35// TemplateURLRef.
36//
37// For files parsed from the Web, be sure and invoke IsValid. IsValid returns
38// true if the URL could be parsed.
39//
40// Both TemplateURL and TemplateURLRef have value semantics. This allows the
41// UI to create a copy while the user modifies the values.
42class 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  TemplateURLRef();
54
55  TemplateURLRef(const std::string& url, int index_offset, int page_offset);
56
57  ~TemplateURLRef();
58
59  // Returns true if this URL supports replacement.
60  bool SupportsReplacement() const;
61
62  // Like SupportsReplacement but usable on threads other than the UI thread.
63  bool SupportsReplacementUsingTermsData(
64      const SearchTermsData& search_terms_data) const;
65
66  // Returns a string that is the result of replacing the search terms in
67  // the url with the specified value.
68  //
69  // If this TemplateURLRef does not support replacement (SupportsReplacement
70  // returns false), an empty string is returned.
71  //
72  // The TemplateURL is used to determine the input encoding for the term.
73  std::string ReplaceSearchTerms(
74      const TemplateURL& host,
75      const std::wstring& terms,
76      int accepted_suggestion,
77      const std::wstring& original_query_for_suggestion) const;
78
79  // Just like ReplaceSearchTerms except that it takes SearchTermsData to supply
80  // the data for some search terms. Most of the time ReplaceSearchTerms should
81  // be called.
82  std::string ReplaceSearchTermsUsingTermsData(
83      const TemplateURL& host,
84      const std::wstring& terms,
85      int accepted_suggestion,
86      const std::wstring& original_query_for_suggestion,
87      const SearchTermsData& search_terms_data) const;
88
89  // Returns the raw URL. None of the parameters will have been replaced.
90  const std::string& url() const { return url_; }
91
92  // Returns the index number of the first search result.
93  int index_offset() const { return index_offset_; }
94
95  // Returns the page number of the first search results.
96  int page_offset() const { return page_offset_; }
97
98  // Returns true if the TemplateURLRef is valid. An invalid TemplateURLRef is
99  // one that contains unknown terms, or invalid characters.
100  bool IsValid() const;
101
102  // Like IsValid but usable on threads other than the UI thread.
103  bool IsValidUsingTermsData(const SearchTermsData& search_terms_data) const;
104
105  // Returns a string representation of this TemplateURLRef suitable for
106  // display. The display format is the same as the format used by Firefox.
107  std::wstring DisplayURL() const;
108
109  // Converts a string as returned by DisplayURL back into a string as
110  // understood by TemplateURLRef.
111  static std::string DisplayURLToURLRef(const std::wstring& display_url);
112
113  // If this TemplateURLRef is valid and contains one search term, this returns
114  // the host/path of the URL, otherwise this returns an empty string.
115  const std::string& GetHost() const;
116  const std::string& GetPath() const;
117
118  // If this TemplateURLRef is valid and contains one search term, this returns
119  // the key of the search term, otherwise this returns an empty string.
120  const std::string& GetSearchTermKey() const;
121
122  // Converts the specified term in the encoding of the host TemplateURL to a
123  // wide string.
124  std::wstring SearchTermToWide(const TemplateURL& host,
125                                const std::string& term) const;
126
127  // Returns true if this TemplateURLRef has a replacement term of
128  // {google:baseURL} or {google:baseSuggestURL}.
129  bool HasGoogleBaseURLs() const;
130
131  // Returns true if both refs are NULL or have the same values.
132  static bool SameUrlRefs(const TemplateURLRef* ref1,
133                          const TemplateURLRef* ref2);
134
135 private:
136  friend class SearchHostToURLsMapTest;
137  friend class TemplateURL;
138  friend class TemplateURLModelTestUtil;
139  friend class TemplateURLTest;
140  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterKnown);
141  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterUnknown);
142  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLEmpty);
143  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoTemplateEnd);
144  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoKnownParameters);
145  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLTwoParameters);
146  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNestedParameter);
147
148  // Enumeration of the known types.
149  enum ReplacementType {
150    ENCODING,
151    GOOGLE_ACCEPTED_SUGGESTION,
152    GOOGLE_BASE_URL,
153    GOOGLE_BASE_SUGGEST_URL,
154    GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION,
155    GOOGLE_RLZ,
156    GOOGLE_UNESCAPED_SEARCH_TERMS,
157    LANGUAGE,
158    SEARCH_TERMS,
159  };
160
161  // Used to identify an element of the raw url that can be replaced.
162  struct Replacement {
163    Replacement(ReplacementType type, size_t index)
164        : type(type), index(index) {}
165    ReplacementType type;
166    size_t index;
167  };
168
169  // The list of elements to replace.
170  typedef std::vector<struct Replacement> Replacements;
171
172  // TemplateURLRef internally caches values to make replacement quick. This
173  // method invalidates any cached values.
174  void InvalidateCachedValues() const;
175
176  // Resets the url.
177  void Set(const std::string& url, int index_offset, int page_offset);
178
179  // Parses the parameter in url at the specified offset. start/end specify the
180  // range of the parameter in the url, including the braces. If the parameter
181  // is valid, url is updated to reflect the appropriate parameter. If
182  // the parameter is one of the known parameters an element is added to
183  // replacements indicating the type and range of the element. The original
184  // parameter is erased from the url.
185  //
186  // If the parameter is not a known parameter, it's not erased and false is
187  // returned.
188  bool ParseParameter(size_t start,
189                      size_t end,
190                      std::string* url,
191                      Replacements* replacements) const;
192
193  // Parses the specified url, replacing parameters as necessary. If
194  // successful, valid is set to true, and the parsed url is returned. For all
195  // known parameters that are encountered an entry is added to replacements.
196  // If there is an error parsing the url, valid is set to false, and an empty
197  // string is returned.
198  std::string ParseURL(const std::string& url,
199                       Replacements* replacements,
200                       bool* valid) const;
201
202  // If the url has not yet been parsed, ParseURL is invoked.
203  // NOTE: While this is const, it modifies parsed_, valid_, parsed_url_ and
204  // search_offset_.
205  void ParseIfNecessary() const;
206
207  // Like ParseIfNecessary but usable on threads other than the UI thread.
208  void ParseIfNecessaryUsingTermsData(
209      const SearchTermsData& search_terms_data) const;
210
211  // Extracts the query key and host from the url.
212  void ParseHostAndSearchTermKey(
213      const SearchTermsData& search_terms_data) const;
214
215  // Used by tests to set the value for the Google base url. This takes
216  // ownership of the given std::string.
217  static void SetGoogleBaseURL(std::string* google_base_url);
218
219  // The raw URL. Where as this contains all the terms (such as {searchTerms}),
220  // parsed_url_ has them all stripped out.
221  std::string url_;
222
223  // indexOffset defined for the Url element.
224  int index_offset_;
225
226  // searchOffset defined for the Url element.
227  int page_offset_;
228
229  // Whether the URL has been parsed.
230  mutable bool parsed_;
231
232  // Whether the url was successfully parsed.
233  mutable bool valid_;
234
235  // The parsed URL. All terms have been stripped out of this with
236  // replacements_ giving the index of the terms to replace.
237  mutable std::string parsed_url_;
238
239  // Do we support replacement?
240  mutable bool supports_replacements_;
241
242  // The replaceable parts of url (parsed_url_). These are ordered by index
243  // into the string, and may be empty.
244  mutable Replacements replacements_;
245
246  // Host, path and key of the search term. These are only set if the url
247  // contains one search term.
248  mutable std::string host_;
249  mutable std::string path_;
250  mutable std::string search_term_key_;
251};
252
253// Describes the relevant portions of a single OSD document.
254class TemplateURL {
255 public:
256  // Describes a single image reference. Each TemplateURL may have
257  // any number (including 0) of ImageRefs.
258  //
259  // If a TemplateURL has no images, the favicon for the generated URL
260  // should be used.
261  struct ImageRef {
262    ImageRef(const std::wstring& type, int width, int height)
263        : type(type), width(width), height(height) {
264    }
265
266    ImageRef(const std::wstring& type, int width, int height, const GURL& url)
267      : type(type), width(width), height(height), url(url) {
268    }
269
270    // Mime type for the image.
271    // ICO image will have the format: image/x-icon or image/vnd.microsoft.icon
272    std::wstring type;
273
274    // Size of the image
275    int width;
276    int height;
277
278    // URL of the image.
279    GURL url;
280  };
281
282  // Generates a favicon URL from the specified url.
283  static GURL GenerateFaviconURL(const GURL& url);
284
285  // Returns true if |turl| is non-null and has a search URL that supports
286  // replacement.
287  static bool SupportsReplacement(const TemplateURL* turl);
288
289  // Like SupportsReplacement but usable on threads other than the UI thread.
290  static bool SupportsReplacementUsingTermsData(
291      const TemplateURL* turl,
292      const SearchTermsData& search_terms_data);
293
294  TemplateURL();
295  ~TemplateURL();
296
297  // A short description of the template. This is the name we show to the user
298  // in various places that use keywords. For example, the location bar shows
299  // this when the user selects the keyword.
300  void set_short_name(const std::wstring& short_name) {
301    short_name_ = short_name;
302  }
303  const std::wstring& short_name() const { return short_name_; }
304
305  // An accessor for the short_name, but adjusted so it can be appropriately
306  // displayed even if it is LTR and the UI is RTL.
307  std::wstring AdjustedShortNameForLocaleDirection() const;
308
309  // A description of the template; this may be empty.
310  void set_description(const std::wstring& description) {
311    description_ = description;
312  }
313  const std::wstring& description() const { return description_; }
314
315  // URL providing JSON results. This is typically used to provide suggestions
316  // as your type. If NULL, this url does not support suggestions.
317  // Be sure and check the resulting TemplateURLRef for SupportsReplacement
318  // before using.
319  void SetSuggestionsURL(const std::string& suggestions_url,
320                         int index_offset,
321                         int page_offset);
322  const TemplateURLRef* suggestions_url() const {
323    return suggestions_url_.url().empty() ? NULL : &suggestions_url_;
324  }
325
326  // Parameterized URL for providing the results. This may be NULL.
327  // Be sure and check the resulting TemplateURLRef for SupportsReplacement
328  // before using.
329  void SetURL(const std::string& url, int index_offset, int page_offset);
330  // Returns the TemplateURLRef that may be used for search results. This
331  // returns NULL if a url element was not specified.
332  const TemplateURLRef* url() const {
333    return url_.url().empty() ? NULL : &url_;
334  }
335
336  // Parameterized URL for instant results. This may be NULL.  Be sure and check
337  // the resulting TemplateURLRef for SupportsReplacement before using. See
338  // TemplateURLRef for a description of |index_offset| and |page_offset|.
339  void SetInstantURL(const std::string& url, int index_offset, int page_offset);
340  // Returns the TemplateURLRef that may be used for search results. This
341  // returns NULL if a url element was not specified.
342  const TemplateURLRef* instant_url() const {
343    return instant_url_.url().empty() ? NULL : &instant_url_;
344  }
345
346  // URL to the OSD file this came from. May be empty.
347  void set_originating_url(const GURL& url) {
348    originating_url_ = url;
349  }
350  const GURL& originating_url() const { return originating_url_; }
351
352  // The shortcut for this template url. May be empty.
353  void set_keyword(const std::wstring& keyword);
354  const std::wstring& keyword() const;
355
356  // Whether to autogenerate a keyword from the url() in GetKeyword().  Most
357  // consumers should not need this.
358  // NOTE: Calling set_keyword() turns this back off.  Manual and automatic
359  // keywords are mutually exclusive.
360  void set_autogenerate_keyword(bool autogenerate_keyword) {
361    autogenerate_keyword_ = autogenerate_keyword;
362    if (autogenerate_keyword_) {
363      keyword_.clear();
364      keyword_generated_ = false;
365    }
366  }
367  bool autogenerate_keyword() const {
368    return autogenerate_keyword_;
369  }
370
371  // Ensures that the keyword is generated.  Most consumers should not need this
372  // because it is done automatically.  Use this method on the UI thread, so
373  // the keyword may be accessed on another thread.
374  void EnsureKeyword() const;
375
376  // Whether this keyword is shown in the default list of search providers. This
377  // is just a property and does not indicate whether this TemplateURL has
378  // a TemplateURLRef that supports replacement. Use ShowInDefaultList to
379  // test both.
380  // The default value is false.
381  void set_show_in_default_list(bool show_in_default_list) {
382    show_in_default_list_ = show_in_default_list;
383  }
384  bool show_in_default_list() const { return show_in_default_list_; }
385
386  // Returns true if show_in_default_list() is true and this TemplateURL has a
387  // TemplateURLRef that supports replacement.
388  bool ShowInDefaultList() const;
389
390  // Whether it's safe for auto-modification code (the autogenerator and the
391  // code that imports data from other browsers) to replace the TemplateURL.
392  // This should be set to false for any keyword the user edits, or any keyword
393  // that the user clearly manually edited in the past, like a bookmark keyword
394  // from another browser.
395  void set_safe_for_autoreplace(bool safe_for_autoreplace) {
396    safe_for_autoreplace_ = safe_for_autoreplace;
397  }
398  bool safe_for_autoreplace() const { return safe_for_autoreplace_; }
399
400  // Images for this URL. May be empty.
401  void add_image_ref(const ImageRef& ref) { image_refs_.push_back(ref); }
402  const std::vector<ImageRef>& image_refs() const { return image_refs_; }
403
404  // Convenience methods for getting/setting an ImageRef that points to a
405  // favicon. A TemplateURL need not have an ImageRef for a favicon. In such
406  // a situation GetFavIconURL returns an invalid url.
407  //
408  // If url is empty and there is an image ref for a favicon, it is removed.
409  void SetFavIconURL(const GURL& url);
410  GURL GetFavIconURL() const;
411
412  // Set of languages supported. This may be empty.
413  void add_language(const std::wstring& language) {
414    languages_.push_back(language);
415  }
416  const std::vector<std::wstring>& languages() const { return languages_; }
417
418  // Date this keyword was created.
419  //
420  // NOTE: this may be 0, which indicates the keyword was created before we
421  // started tracking creation time.
422  void set_date_created(base::Time time) { date_created_ = time; }
423  base::Time date_created() const { return date_created_; }
424
425  // True if this TemplateURL was automatically created by the administrator via
426  // group policy.
427  void set_created_by_policy(bool created_by_policy) {
428     created_by_policy_ = created_by_policy;
429  }
430  bool created_by_policy() const { return created_by_policy_; }
431
432  // Number of times this keyword has been explicitly used to load a URL.  We
433  // don't increment this for uses as the "default search engine" since that's
434  // not really "explicit" usage and incrementing would result in pinning the
435  // user's default search engine(s) to the top of the list of searches on the
436  // New Tab page, de-emphasizing the omnibox as "where you go to search".
437  void set_usage_count(int count) { usage_count_ = count; }
438  int usage_count() const { return usage_count_; }
439
440  // The list of supported encodings for the search terms. This may be empty,
441  // which indicates the terms should be encoded with UTF-8.
442  void set_input_encodings(const std::vector<std::string>& encodings) {
443    input_encodings_ = encodings;
444  }
445  void add_input_encoding(const std::string& encoding) {
446    input_encodings_.push_back(encoding);
447  }
448  const std::vector<std::string>& input_encodings() const {
449    return input_encodings_;
450  }
451
452  void set_search_engine_type(SearchEngineType search_engine_type) {
453    search_engine_type_ = search_engine_type;
454  }
455  SearchEngineType search_engine_type() const {
456    return search_engine_type_;
457  }
458
459  void set_logo_id(int logo_id) { logo_id_ = logo_id; }
460  int logo_id() const { return logo_id_; }
461
462  // Returns the unique identifier of this TemplateURL. The unique ID is set
463  // by the TemplateURLModel when the TemplateURL is added to it.
464  TemplateURLID id() const { return id_; }
465
466  // If this TemplateURL comes from prepopulated data the prepopulate_id is > 0.
467  void set_prepopulate_id(int id) { prepopulate_id_ = id; }
468  int prepopulate_id() const { return prepopulate_id_; }
469
470  std::string GetExtensionId() const;
471  bool IsExtensionKeyword() const;
472
473 private:
474  friend void MergeEnginesFromPrepopulateData(
475      PrefService* prefs,
476      WebDataService* service,
477      std::vector<TemplateURL*>* template_urls,
478      const TemplateURL** default_search_provider);
479  friend class SearchHostToURLsMap;
480  friend class TemplateURLModel;
481  friend class WebDatabaseTest;
482  friend class WebDatabase;
483
484  // Invalidates cached values on this object and its child TemplateURLRefs.
485  void InvalidateCachedValues() const;
486
487  // Unique identifier, used when archived to the database.
488  void set_id(TemplateURLID id) { id_ = id;}
489
490  std::wstring short_name_;
491  std::wstring description_;
492  TemplateURLRef suggestions_url_;
493  TemplateURLRef url_;
494  TemplateURLRef instant_url_;
495  GURL originating_url_;
496  mutable std::wstring keyword_;
497  bool autogenerate_keyword_;  // If this is set, |keyword_| holds the cached
498                               // generated keyword if available.
499  mutable bool keyword_generated_;  // True if the keyword was generated. This
500                                    // is used to avoid multiple attempts if
501                                    // generating a keyword failed.
502  bool show_in_default_list_;
503  bool safe_for_autoreplace_;
504  std::vector<ImageRef> image_refs_;
505  std::vector<std::wstring> languages_;
506  // List of supported input encodings.
507  std::vector<std::string> input_encodings_;
508  TemplateURLID id_;
509  base::Time date_created_;
510  bool created_by_policy_;
511  int usage_count_;
512  SearchEngineType search_engine_type_;
513  int logo_id_;
514  int prepopulate_id_;
515
516  // TODO(sky): Add date last parsed OSD file.
517};
518
519#endif  // CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_H_
520