summaryrefslogtreecommitdiffstats
path: root/chrome/browser/search_engines/template_url.h
blob: c00dad191ea83444fd202fb26b0bea5e0452368e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_H_
#define CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_H_
#pragma once

#include <string>
#include <vector>

#include "base/gtest_prod_util.h"
#include "base/time.h"
#include "googleurl/src/gurl.h"

class TemplateURL;

// TemplateURL represents the relevant portions of the Open Search Description
// Document (http://www.opensearch.org/Specifications/OpenSearch).
// The main use case for TemplateURL is to use the TemplateURLRef returned by
// suggestions_url or url for keyword/suggestion expansion:
// . suggestions_url describes a URL that is ideal for as you type suggestions.
//   The returned results are in the mime type application/x-suggestions+json.
// . url describes a URL that may be used as a shortcut. Returned results are
//   are text/html.
// Before using either one, make sure it's non-NULL, and if you intend to use
// it to replace search terms, make sure SupportsReplacement returns true.
// To use either URL invoke the ReplaceSearchTerms method on the corresponding
// TemplateURLRef.
//
// For files parsed from the Web, be sure and invoke IsValid. IsValid returns
// true if the URL could be parsed.
//
// Both TemplateURL and TemplateURLRef have value semantics. This allows the
// UI to create a copy while the user modifies the values.
class TemplateURLRef {
 public:
  // Magic numbers to pass to ReplaceSearchTerms() for the |accepted_suggestion|
  // parameter.  Most callers aren't using Suggest capabilities and should just
  // pass NO_SUGGESTIONS_AVAILABLE.
  // NOTE: Because positive values are meaningful, make sure these are negative!
  enum AcceptedSuggestion {
    NO_SUGGESTION_CHOSEN = -1,
    NO_SUGGESTIONS_AVAILABLE = -2,
  };

  TemplateURLRef();

  TemplateURLRef(const std::string& url, int index_offset, int page_offset)
      : url_(url),
        index_offset_(index_offset),
        page_offset_(page_offset),
        parsed_(false),
        valid_(false),
        supports_replacements_(false) {
  }

  // Returns true if this URL supports replacement.
  bool SupportsReplacement() const;

  // Returns a string that is the result of replacing the search terms in
  // the url with the specified value.
  //
  // If this TemplateURLRef does not support replacement (SupportsReplacement
  // returns false), an empty string is returned.
  //
  // The TemplateURL is used to determine the input encoding for the term.
  std::string ReplaceSearchTerms(
      const TemplateURL& host,
      const std::wstring& terms,
      int accepted_suggestion,
      const std::wstring& original_query_for_suggestion) const;

  // Returns the raw URL. None of the parameters will have been replaced.
  const std::string& url() const { return url_; }

  // Returns the index number of the first search result.
  int index_offset() const { return index_offset_; }

  // Returns the page number of the first search results.
  int page_offset() const { return page_offset_; }

  // Returns true if the TemplateURLRef is valid. An invalid TemplateURLRef is
  // one that contains unknown terms, or invalid characters.
  bool IsValid() const;

  // Returns a string representation of this TemplateURLRef suitable for
  // display. The display format is the same as the format used by Firefox.
  std::wstring DisplayURL() const;

  // Converts a string as returned by DisplayURL back into a string as
  // understood by TemplateURLRef.
  static std::string DisplayURLToURLRef(const std::wstring& display_url);

  // If this TemplateURLRef is valid and contains one search term, this returns
  // the host/path of the URL, otherwise this returns an empty string.
  const std::string& GetHost() const;
  const std::string& GetPath() const;

  // If this TemplateURLRef is valid and contains one search term, this returns
  // the key of the search term, otherwise this returns an empty string.
  const std::string& GetSearchTermKey() const;

  // Converts the specified term in the encoding of the host TemplateURL to a
  // wide string.
  std::wstring SearchTermToWide(const TemplateURL& host,
                                const std::string& term) const;

  // Returns true if this TemplateURLRef has a replacement term of
  // {google:baseURL} or {google:baseSuggestURL}.
  bool HasGoogleBaseURLs() const;

 private:
  friend class TemplateURL;
  friend class TemplateURLModelTest;
  friend class TemplateURLTest;
  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterKnown);
  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterUnknown);
  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLEmpty);
  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoTemplateEnd);
  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoKnownParameters);
  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLTwoParameters);
  FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNestedParameter);

  // Enumeration of the known types.
  enum ReplacementType {
    ENCODING,
    GOOGLE_ACCEPTED_SUGGESTION,
    GOOGLE_BASE_URL,
    GOOGLE_BASE_SUGGEST_URL,
    GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION,
    GOOGLE_RLZ,
    GOOGLE_UNESCAPED_SEARCH_TERMS,
    LANGUAGE,
    SEARCH_TERMS,
  };

  // Used to identify an element of the raw url that can be replaced.
  struct Replacement {
    Replacement(ReplacementType type, size_t index)
        : type(type), index(index) {}
    ReplacementType type;
    size_t index;
  };

  // The list of elements to replace.
  typedef std::vector<struct Replacement> Replacements;

  // TemplateURLRef internally caches values to make replacement quick. This
  // method invalidates any cached values.
  void InvalidateCachedValues() const;

  // Resets the url.
  void Set(const std::string& url, int index_offset, int page_offset);

  // Parses the parameter in url at the specified offset. start/end specify the
  // range of the parameter in the url, including the braces. If the parameter
  // is valid, url is updated to reflect the appropriate parameter. If
  // the parameter is one of the known parameters an element is added to
  // replacements indicating the type and range of the element. The original
  // parameter is erased from the url.
  //
  // If the parameter is not a known parameter, it's not erased and false is
  // returned.
  bool ParseParameter(size_t start,
                      size_t end,
                      std::string* url,
                      Replacements* replacements) const;

  // Parses the specified url, replacing parameters as necessary. If
  // successful, valid is set to true, and the parsed url is returned. For all
  // known parameters that are encountered an entry is added to replacements.
  // If there is an error parsing the url, valid is set to false, and an empty
  // string is returned.
  std::string ParseURL(const std::string& url,
                       Replacements* replacements,
                       bool* valid) const;

  // If the url has not yet been parsed, ParseURL is invoked.
  // NOTE: While this is const, it modifies parsed_, valid_, parsed_url_ and
  // search_offset_.
  void ParseIfNecessary() const;

  // Extracts the query key and host from the url.
  void ParseHostAndSearchTermKey() const;

  // Returns the value for the GOOGLE_BASE_URL term.
  static std::string GoogleBaseURLValue();

  // Returns the value for the GOOGLE_BASE_SUGGEST_URL term.
  static std::string GoogleBaseSuggestURLValue();

  // The raw URL. Where as this contains all the terms (such as {searchTerms}),
  // parsed_url_ has them all stripped out.
  std::string url_;

  // indexOffset defined for the Url element.
  int index_offset_;

  // searchOffset defined for the Url element.
  int page_offset_;

  // Whether the URL has been parsed.
  mutable bool parsed_;

  // Whether the url was successfully parsed.
  mutable bool valid_;

  // The parsed URL. All terms have been stripped out of this with
  // replacements_ giving the index of the terms to replace.
  mutable std::string parsed_url_;

  // Do we support replacement?
  mutable bool supports_replacements_;

  // The replaceable parts of url (parsed_url_). These are ordered by index
  // into the string, and may be empty.
  mutable Replacements replacements_;

  // Host, path and key of the search term. These are only set if the url
  // contains one search term.
  mutable std::string host_;
  mutable std::string path_;
  mutable std::string search_term_key_;

  // For testing. If non-null this is the replacement value for GOOGLE_BASE_URL
  // terms.
  static std::string* google_base_url_;
};

// Describes the relevant portions of a single OSD document.
class TemplateURL {
 public:
  typedef int64 IDType;

  // Describes a single image reference. Each TemplateURL may have
  // any number (including 0) of ImageRefs.
  //
  // If a TemplateURL has no images, the favicon for the generated URL
  // should be used.
  struct ImageRef {
    ImageRef(const std::wstring& type, int width, int height)
        : type(type), width(width), height(height) {
    }

    ImageRef(const std::wstring& type, int width, int height, const GURL& url)
      : type(type), width(width), height(height), url(url) {
    }

    // Mime type for the image.
    // ICO image will have the format: image/x-icon or image/vnd.microsoft.icon
    std::wstring type;

    // Size of the image
    int width;
    int height;

    // URL of the image.
    GURL url;
  };

  // Generates a favicon URL from the specified url.
  static GURL GenerateFaviconURL(const GURL& url);

  // Returns true if |true| is non-null and has a search URL that supports
  // replacement.
  static bool SupportsReplacement(const TemplateURL* turl);

  TemplateURL()
      : autogenerate_keyword_(false),
        keyword_generated_(false),
        show_in_default_list_(false),
        safe_for_autoreplace_(false),
        id_(0),
        date_created_(base::Time::Now()),
        usage_count_(0),
        prepopulate_id_(0) {}
  ~TemplateURL() {}

  // A short description of the template. This is the name we show to the user
  // in various places that use keywords. For example, the location bar shows
  // this when the user selects the keyword.
  void set_short_name(const std::wstring& short_name) {
    short_name_ = short_name;
  }
  const std::wstring& short_name() const { return short_name_; }

  // An accessor for the short_name, but adjusted so it can be appropriately
  // displayed even if it is LTR and the UI is RTL.
  std::wstring AdjustedShortNameForLocaleDirection() const;

  // A description of the template; this may be empty.
  void set_description(const std::wstring& description) {
    description_ = description;
  }
  const std::wstring& description() const { return description_; }

  // URL providing JSON results. This is typically used to provide suggestions
  // as your type. If NULL, this url does not support suggestions.
  // Be sure and check the resulting TemplateURLRef for SupportsReplacement
  // before using.
  void SetSuggestionsURL(const std::string& suggestions_url,
                         int index_offset,
                         int page_offset);
  const TemplateURLRef* suggestions_url() const {
    if (suggestions_url_.url().empty())
      return NULL;
    return &suggestions_url_;
  }

  // Parameterized URL for providing the results. This may be NULL.
  // Be sure and check the resulting TemplateURLRef for SupportsReplacement
  // before using.
  void SetURL(const std::string& url, int index_offset, int page_offset);
  // Returns the TemplateURLRef that may be used for search results. This
  // returns NULL if a url element was not specified.
  const TemplateURLRef* url() const {
    if (url_.url().empty())
      return NULL;
    return &url_;
  }

  // URL to the OSD file this came from. May be empty.
  void set_originating_url(const GURL& url) {
    originating_url_ = url;
  }
  const GURL& originating_url() const { return originating_url_; }

  // The shortcut for this template url. May be empty.
  void set_keyword(const std::wstring& keyword);
  const std::wstring& keyword() const;

  // Whether to autogenerate a keyword from the url() in GetKeyword().  Most
  // consumers should not need this.
  // NOTE: Calling set_keyword() turns this back off.  Manual and automatic
  // keywords are mutually exclusive.
  void set_autogenerate_keyword(bool autogenerate_keyword) {
    autogenerate_keyword_ = autogenerate_keyword;
    if (autogenerate_keyword_) {
      keyword_.clear();
      keyword_generated_ = false;
    }
  }
  bool autogenerate_keyword() const {
    return autogenerate_keyword_;
  }

  // Whether this keyword is shown in the default list of search providers. This
  // is just a property and does not indicate whether this TemplateURL has
  // a TemplateURLRef that supports replacement. Use ShowInDefaultList to
  // test both.
  // The default value is false.
  void set_show_in_default_list(bool show_in_default_list) {
    show_in_default_list_ = show_in_default_list;
  }
  bool show_in_default_list() const { return show_in_default_list_; }

  // Returns true if show_in_default_list() is true and this TemplateURL has a
  // TemplateURLRef that supports replacement.
  bool ShowInDefaultList() const;

  // Whether it's safe for auto-modification code (the autogenerator and the
  // code that imports data from other browsers) to replace the TemplateURL.
  // This should be set to false for any keyword the user edits, or any keyword
  // that the user clearly manually edited in the past, like a bookmark keyword
  // from another browser.
  void set_safe_for_autoreplace(bool safe_for_autoreplace) {
    safe_for_autoreplace_ = safe_for_autoreplace;
  }
  bool safe_for_autoreplace() const { return safe_for_autoreplace_; }

  // Images for this URL. May be empty.
  void add_image_ref(const ImageRef& ref) { image_refs_.push_back(ref); }
  const std::vector<ImageRef>& image_refs() const { return image_refs_; }

  // Convenience methods for getting/setting an ImageRef that points to a
  // favicon. A TemplateURL need not have an ImageRef for a favicon. In such
  // a situation GetFavIconURL returns an invalid url.
  //
  // If url is empty and there is an image ref for a favicon, it is removed.
  void SetFavIconURL(const GURL& url);
  GURL GetFavIconURL() const;

  // Set of languages supported. This may be empty.
  void add_language(const std::wstring& language) {
    languages_.push_back(language);
  }
  const std::vector<std::wstring>& languages() const { return languages_; }

  // Date this keyword was created.
  //
  // NOTE: this may be 0, which indicates the keyword was created before we
  // started tracking creation time.
  void set_date_created(base::Time time) { date_created_ = time; }
  base::Time date_created() const { return date_created_; }

  // Number of times this keyword has been explicitly used to load a URL.  We
  // don't increment this for uses as the "default search engine" since that's
  // not really "explicit" usage and incrementing would result in pinning the
  // user's default search engine(s) to the top of the list of searches on the
  // New Tab page, de-emphasizing the omnibox as "where you go to search".
  void set_usage_count(int count) { usage_count_ = count; }
  int usage_count() const { return usage_count_; }

  // The list of supported encodings for the search terms. This may be empty,
  // which indicates the terms should be encoded with UTF-8.
  void set_input_encodings(const std::vector<std::string>& encodings) {
    input_encodings_ = encodings;
  }
  void add_input_encoding(const std::string& encoding) {
    input_encodings_.push_back(encoding);
  }
  const std::vector<std::string>& input_encodings() const {
    return input_encodings_;
  }

  // Returns the unique identifier of this TemplateURL. The unique ID is set
  // by the TemplateURLModel when the TemplateURL is added to it.
  IDType id() const { return id_; }

  // If this TemplateURL comes from prepopulated data the prepopulate_id is > 0.
  void set_prepopulate_id(int id) { prepopulate_id_ = id; }
  int prepopulate_id() const { return prepopulate_id_; }

  std::string GetExtensionId() const;
  bool IsExtensionKeyword() const;

 private:
  friend class WebDatabaseTest;
  friend class WebDatabase;
  friend class TemplateURLModel;

  // Invalidates cached values on this object and its child TemplateURLRefs.
  void InvalidateCachedValues() const;

  // Unique identifier, used when archived to the database.
  void set_id(IDType id) { id_ = id;}

  std::wstring short_name_;
  std::wstring description_;
  TemplateURLRef suggestions_url_;
  TemplateURLRef url_;
  GURL originating_url_;
  mutable std::wstring keyword_;
  bool autogenerate_keyword_;  // If this is set, |keyword_| holds the cached
                               // generated keyword if available.
  mutable bool keyword_generated_;  // True if the keyword was generated. This
                                    // is used to avoid multiple attempts if
                                    // generating a keyword failed.
  bool show_in_default_list_;
  bool safe_for_autoreplace_;
  std::vector<ImageRef> image_refs_;
  std::vector<std::wstring> languages_;
  // List of supported input encodings.
  std::vector<std::string> input_encodings_;
  IDType id_;
  base::Time date_created_;
  int usage_count_;
  int prepopulate_id_;

  // TODO(sky): Add date last parsed OSD file.
};

#endif  // CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_H_