172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/search_engines/template_url.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/icu_string_conversions.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/rtl.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h"
1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/metrics/user_metrics.h"
13513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "chrome/browser/search_engines/search_engine_type.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/search_engines/search_terms_data.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/search_engines/template_url_model.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h"
1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/installer/util/google_update_settings.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/escape.h"
1972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/favicon_size.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// TODO(pastarmovj): Remove google_update_settings and user_metrics when the
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// CollectRLZMetrics function is not needed anymore.
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The TemplateURLRef has any number of terms that need to be replaced. Each of
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// the terms is enclosed in braces. If the character preceeding the final
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// brace is a ?, it indicates the term is optional and can be replaced with
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// an empty string.
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kStartParameter = '{';
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kEndParameter = '}';
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kOptional = '?';
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Known parameters found in the URL.
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kSearchTermsParameter[] = "searchTerms";
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kSearchTermsParameterFull[] = "{searchTerms}";
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kCountParameter[] = "count";
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kStartIndexParameter[] = "startIndex";
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kStartPageParameter[] = "startPage";
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kLanguageParameter[] = "language";
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kInputEncodingParameter[] = "inputEncoding";
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kOutputEncodingParameter[] = "outputEncoding";
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kGoogleAcceptedSuggestionParameter[] =
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "google:acceptedSuggestion";
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Host/Domain Google searches are relative to.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kGoogleBaseURLParameter[] = "google:baseURL";
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kGoogleBaseURLParameterFull[] = "{google:baseURL}";
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Like google:baseURL, but for the Search Suggest capability.
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kGoogleBaseSuggestURLParameter[] =
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "google:baseSuggestURL";
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kGoogleBaseSuggestURLParameterFull[] =
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "{google:baseSuggestURL}";
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kGoogleOriginalQueryForSuggestionParameter[] =
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "google:originalQueryForSuggestion";
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kGoogleRLZParameter[] = "google:RLZ";
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Same as kSearchTermsParameter, with no escaping.
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kGoogleUnescapedSearchTermsParameter[] =
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "google:unescapedSearchTerms";
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kGoogleUnescapedSearchTermsParameterFull[] =
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    "{google:unescapedSearchTerms}";
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Display value for kSearchTermsParameter.
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kDisplaySearchTerms[] = "%s";
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Display value for kGoogleUnescapedSearchTermsParameter.
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kDisplayUnescapedSearchTerms[] = "%S";
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Used if the count parameter is not optional. Indicates we want 10 search
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// results.
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kDefaultCount[] = "10";
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Used if the parameter kOutputEncodingParameter is required.
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kOutputEncodingType[] = "UTF-8";
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochTemplateURLRef::TemplateURLRef() {
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Set(std::string(), 0, 0);
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTemplateURLRef::TemplateURLRef(const std::string& url,
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               int index_offset,
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               int page_offset)
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : url_(url),
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      index_offset_(index_offset),
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      page_offset_(page_offset),
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      parsed_(false),
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      valid_(false),
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      supports_replacements_(false) {
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TemplateURLRef::Set(const std::string& url,
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         int index_offset,
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         int page_offset) {
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url_ = url;
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  index_offset_ = index_offset;
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  page_offset_ = page_offset;
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InvalidateCachedValues();
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
983345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTemplateURLRef::~TemplateURLRef() {
993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TemplateURLRef::ParseParameter(size_t start,
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    size_t end,
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    std::string* url,
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    Replacements* replacements) const {
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(start != std::string::npos &&
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         end != std::string::npos && end > start);
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  size_t length = end - start - 1;
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool optional = false;
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if ((*url)[end - 1] == kOptional) {
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    optional = true;
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    length--;
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string parameter(url->substr(start + 1, length));
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string full_parameter(url->substr(start, end - start + 1));
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Remove the parameter from the string.
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url->erase(start, end - start + 1);
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (parameter == kSearchTermsParameter) {
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    replacements->push_back(Replacement(SEARCH_TERMS, start));
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kCountParameter) {
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!optional)
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url->insert(start, kDefaultCount);
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kStartIndexParameter) {
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!optional) {
1243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      url->insert(start, base::IntToString(index_offset_));
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kStartPageParameter) {
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!optional) {
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      url->insert(start, base::IntToString(page_offset_));
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kLanguageParameter) {
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    replacements->push_back(Replacement(LANGUAGE, start));
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kInputEncodingParameter) {
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    replacements->push_back(Replacement(ENCODING, start));
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kOutputEncodingParameter) {
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!optional)
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      url->insert(start, kOutputEncodingType);
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kGoogleAcceptedSuggestionParameter) {
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    replacements->push_back(Replacement(GOOGLE_ACCEPTED_SUGGESTION, start));
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kGoogleBaseURLParameter) {
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    replacements->push_back(Replacement(GOOGLE_BASE_URL, start));
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kGoogleBaseSuggestURLParameter) {
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    replacements->push_back(Replacement(GOOGLE_BASE_SUGGEST_URL, start));
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kGoogleOriginalQueryForSuggestionParameter) {
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    replacements->push_back(Replacement(GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION,
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        start));
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kGoogleRLZParameter) {
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    replacements->push_back(Replacement(GOOGLE_RLZ, start));
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else if (parameter == kGoogleUnescapedSearchTermsParameter) {
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    replacements->push_back(Replacement(GOOGLE_UNESCAPED_SEARCH_TERMS, start));
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // It can be some garbage but can also be a javascript block. Put it back.
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    url->insert(start, full_parameter);
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string TemplateURLRef::ParseURL(const std::string& url,
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     Replacements* replacements,
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                     bool* valid) const {
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *valid = false;
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string parsed_url = url;
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t last = 0; last != std::string::npos; ) {
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    last = parsed_url.find(kStartParameter, last);
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (last != std::string::npos) {
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      size_t template_end = parsed_url.find(kEndParameter, last);
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (template_end != std::string::npos) {
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Since we allow Javascript in the URL, {} pairs could be nested. Match
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // only leaf pairs with supported parameters.
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        size_t next_template_start = parsed_url.find(kStartParameter, last + 1);
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (next_template_start == std::string::npos ||
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            next_template_start > template_end) {
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // If successful, ParseParameter erases from the string as such no
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // need to update |last|. If failed, move |last| to the end of pair.
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (!ParseParameter(last, template_end, &parsed_url, replacements)) {
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            // |template_end| + 1 may be beyond the end of the string.
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            last = template_end;
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        } else {
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          last = next_template_start;
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // Open brace without a closing brace, return.
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return std::string();
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  *valid = true;
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return parsed_url;
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TemplateURLRef::ParseIfNecessary() const {
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  UIThreadSearchTermsData search_terms_data;
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ParseIfNecessaryUsingTermsData(search_terms_data);
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid TemplateURLRef::ParseIfNecessaryUsingTermsData(
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const SearchTermsData& search_terms_data) const {
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!parsed_) {
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    parsed_ = true;
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    parsed_url_ = ParseURL(url_, &replacements_, &valid_);
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    supports_replacements_ = false;
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (valid_) {
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bool has_only_one_search_term = false;
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (Replacements::const_iterator i = replacements_.begin();
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           i != replacements_.end(); ++i) {
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if ((i->type == SEARCH_TERMS) ||
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            (i->type == GOOGLE_UNESCAPED_SEARCH_TERMS)) {
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          if (has_only_one_search_term) {
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            has_only_one_search_term = false;
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            break;
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          }
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          has_only_one_search_term = true;
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          supports_replacements_ = true;
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Only parse the host/key if there is one search term. Technically there
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // could be more than one term, but it's uncommon; so we punt.
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (has_only_one_search_term)
2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        ParseHostAndSearchTermKey(search_terms_data);
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid TemplateURLRef::ParseHostAndSearchTermKey(
2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const SearchTermsData& search_terms_data) const {
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url_string = url_;
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ReplaceSubstringsAfterOffset(&url_string, 0,
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               kGoogleBaseURLParameterFull,
2303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               search_terms_data.GoogleBaseURLValue());
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ReplaceSubstringsAfterOffset(&url_string, 0,
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               kGoogleBaseSuggestURLParameterFull,
2333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                               search_terms_data.GoogleBaseSuggestURLValue());
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url(url_string);
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!url.is_valid())
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string query_string = url.query();
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (query_string.empty())
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url_parse::Component query, key, value;
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  query.len = static_cast<int>(query_string.size());
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (url_parse::ExtractQueryKeyValue(query_string.c_str(), &query, &key,
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         &value)) {
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (key.is_nonempty() && value.is_nonempty()) {
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      std::string value_string = query_string.substr(value.begin, value.len);
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (value_string.find(kSearchTermsParameterFull, 0) !=
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::string::npos ||
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          value_string.find(kGoogleUnescapedSearchTermsParameterFull, 0) !=
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          std::string::npos) {
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        search_term_key_ = query_string.substr(key.begin, key.len);
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        host_ = url.host();
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        path_ = url.path();
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static
2633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid TemplateURLRef::SetGoogleBaseURL(std::string* google_base_url) {
2643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  UIThreadSearchTermsData::SetGoogleBaseURL(google_base_url);
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string TemplateURLRef::ReplaceSearchTerms(
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const TemplateURL& host,
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& terms,
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int accepted_suggestion,
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& original_query_for_suggestion) const {
2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  UIThreadSearchTermsData search_terms_data;
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return ReplaceSearchTermsUsingTermsData(host,
2743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                          terms,
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                          accepted_suggestion,
2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                          original_query_for_suggestion,
2773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                          search_terms_data);
2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstd::string TemplateURLRef::ReplaceSearchTermsUsingTermsData(
2813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const TemplateURL& host,
28272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& terms,
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    int accepted_suggestion,
28472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& original_query_for_suggestion,
2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const SearchTermsData& search_terms_data) const {
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ParseIfNecessaryUsingTermsData(search_terms_data);
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!valid_)
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return std::string();
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (replacements_.empty())
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return parsed_url_;
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Determine if the search terms are in the query or before. We're escaping
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // space as '+' in the former case and as '%20' in the latter case.
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool is_in_query = true;
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (Replacements::iterator i = replacements_.begin();
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != replacements_.end(); ++i) {
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (i->type == SEARCH_TERMS) {
29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      string16::size_type query_start = parsed_url_.find('?');
30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      is_in_query = query_start != string16::npos &&
30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          (static_cast<string16::size_type>(i->index) > query_start);
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 encoded_terms;
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 encoded_original_query;
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string input_encoding;
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // If the search terms are in query - escape them respecting the encoding.
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (is_in_query) {
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Encode the search terms so that we know the encoding.
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const std::vector<std::string>& encodings = host.input_encodings();
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (size_t i = 0; i < encodings.size(); ++i) {
31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (EscapeQueryParamValue(terms,
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                encodings[i].c_str(), true,
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                &encoded_terms)) {
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (!original_query_for_suggestion.empty()) {
31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          EscapeQueryParamValue(original_query_for_suggestion,
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                encodings[i].c_str(),
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                true,
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                &encoded_original_query);
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        input_encoding = encodings[i];
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (input_encoding.empty()) {
32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      encoded_terms = EscapeQueryParamValueUTF8(terms, true);
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!original_query_for_suggestion.empty()) {
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        encoded_original_query =
33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen            EscapeQueryParamValueUTF8(original_query_for_suggestion, true);
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      input_encoding = "UTF-8";
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    encoded_terms = UTF8ToUTF16(EscapePath(UTF16ToUTF8(terms)));
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    input_encoding = "UTF-8";
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url = parsed_url_;
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // replacements_ is ordered in ascending order, as such we need to iterate
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // from the back.
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (Replacements::reverse_iterator i = replacements_.rbegin();
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != replacements_.rend(); ++i) {
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (i->type) {
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case ENCODING:
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        url.insert(i->index, input_encoding);
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case GOOGLE_ACCEPTED_SUGGESTION:
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (accepted_suggestion == NO_SUGGESTION_CHOSEN)
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          url.insert(i->index, "aq=f&");
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        else if (accepted_suggestion != NO_SUGGESTIONS_AVAILABLE)
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          url.insert(i->index, StringPrintf("aq=%d&", accepted_suggestion));
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case GOOGLE_BASE_URL:
3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        url.insert(i->index, search_terms_data.GoogleBaseURLValue());
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case GOOGLE_BASE_SUGGEST_URL:
3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        url.insert(i->index, search_terms_data.GoogleBaseSuggestURLValue());
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION:
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (accepted_suggestion >= 0)
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          url.insert(i->index, "oq=" + UTF16ToUTF8(encoded_original_query) +
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               "&");
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case GOOGLE_RLZ: {
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // On platforms that don't have RLZ, we still want this branch
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // to happen so that we replace the RLZ template with the
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // empty string.  (If we don't handle this case, we hit a
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // NOTREACHED below.)
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
37872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        string16 rlz_string = search_terms_data.GetRlzParameterValue();
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if (!rlz_string.empty()) {
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          rlz_string = L"rlz=" + rlz_string + L"&";
38172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          url.insert(i->index, UTF16ToUTF8(rlz_string));
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case GOOGLE_UNESCAPED_SEARCH_TERMS: {
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        std::string unescaped_terms;
38972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        base::UTF16ToCodepage(terms, input_encoding.c_str(),
39072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                              base::OnStringConversionError::SKIP,
39172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                              &unescaped_terms);
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        url.insert(i->index, std::string(unescaped_terms.begin(),
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                         unescaped_terms.end()));
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case LANGUAGE:
3983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        url.insert(i->index, search_terms_data.GetApplicationLocale());
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case SEARCH_TERMS:
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        url.insert(i->index, UTF16ToUTF8(encoded_terms));
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      default:
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED();
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return url;
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TemplateURLRef::SupportsReplacement() const {
4153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  UIThreadSearchTermsData search_terms_data;
4163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return SupportsReplacementUsingTermsData(search_terms_data);
4173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TemplateURLRef::SupportsReplacementUsingTermsData(
4203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const SearchTermsData& search_terms_data) const {
4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ParseIfNecessaryUsingTermsData(search_terms_data);
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return valid_ && supports_replacements_;
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TemplateURLRef::IsValid() const {
4263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  UIThreadSearchTermsData search_terms_data;
4273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return IsValidUsingTermsData(search_terms_data);
4283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TemplateURLRef::IsValidUsingTermsData(
4313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const SearchTermsData& search_terms_data) const {
4323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ParseIfNecessaryUsingTermsData(search_terms_data);
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return valid_;
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 TemplateURLRef::DisplayURL() const {
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ParseIfNecessary();
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!valid_ || replacements_.empty())
43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return UTF8ToUTF16(url_);
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 result = UTF8ToUTF16(url_);
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ReplaceSubstringsAfterOffset(&result, 0,
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               ASCIIToUTF16(kSearchTermsParameterFull),
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               ASCIIToUTF16(kDisplaySearchTerms));
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ReplaceSubstringsAfterOffset(
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &result, 0,
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ASCIIToUTF16(kGoogleUnescapedSearchTermsParameterFull),
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ASCIIToUTF16(kDisplayUnescapedSearchTerms));
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return result;
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string TemplateURLRef::DisplayURLToURLRef(
45672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& display_url) {
45772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  string16 result = display_url;
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ReplaceSubstringsAfterOffset(&result, 0, ASCIIToUTF16(kDisplaySearchTerms),
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               ASCIIToUTF16(kSearchTermsParameterFull));
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ReplaceSubstringsAfterOffset(
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &result, 0,
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ASCIIToUTF16(kDisplayUnescapedSearchTerms),
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ASCIIToUTF16(kGoogleUnescapedSearchTermsParameterFull));
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return UTF16ToUTF8(result);
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst std::string& TemplateURLRef::GetHost() const {
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ParseIfNecessary();
469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return host_;
470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst std::string& TemplateURLRef::GetPath() const {
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ParseIfNecessary();
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return path_;
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst std::string& TemplateURLRef::GetSearchTermKey() const {
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ParseIfNecessary();
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return search_term_key_;
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
48272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 TemplateURLRef::SearchTermToString16(const TemplateURL& host,
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                              const std::string& term) const {
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::vector<std::string>& encodings = host.input_encodings();
48572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  string16 result;
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string unescaped =
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      UnescapeURLComponent(term, UnescapeRule::REPLACE_PLUS_WITH_SPACE |
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 UnescapeRule::URL_SPECIAL_CHARS);
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < encodings.size(); ++i) {
49172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (base::CodepageToUTF16(unescaped, encodings[i].c_str(),
49272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                              base::OnStringConversionError::FAIL, &result))
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return result;
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Always fall back on UTF-8 if it works.
49772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (base::CodepageToUTF16(unescaped, base::kCodepageUTF8,
49872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                            base::OnStringConversionError::FAIL, &result))
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return result;
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When nothing worked, just use the escaped text. We have no idea what the
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // encoding is. We need to substitute spaces for pluses ourselves since we're
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // not sending it through an unescaper.
50472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  result = UTF8ToUTF16(term);
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::replace(result.begin(), result.end(), '+', ' ');
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return result;
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TemplateURLRef::HasGoogleBaseURLs() const {
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ParseIfNecessary();
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < replacements_.size(); ++i) {
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if ((replacements_[i].type == GOOGLE_BASE_URL) ||
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        (replacements_[i].type == GOOGLE_BASE_SUGGEST_URL))
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return true;
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return false;
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
519731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static
520731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool TemplateURLRef::SameUrlRefs(const TemplateURLRef* ref1,
521731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const TemplateURLRef* ref2) {
522731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return ref1 == ref2 || (ref1 && ref2 && ref1->url() == ref2->url());
523731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
524731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
52572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid TemplateURLRef::CollectRLZMetrics() const {
52672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
52772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ParseIfNecessary();
52872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (size_t i = 0; i < replacements_.size(); ++i) {
52972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // We are interesed in searches that were supposed to send the RLZ token.
53072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (replacements_[i].type == GOOGLE_RLZ) {
53172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      string16 brand;
53272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // We only have RLZ tocken on a branded browser version.
53372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (GoogleUpdateSettings::GetBrand(&brand) && !brand.empty() &&
53472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen           !GoogleUpdateSettings::IsOrganic(brand)) {
53572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        // Now we know we should have had RLZ token check if there was one.
53672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        if (url().find("rlz=") != std::string::npos)
53772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          UserMetrics::RecordAction(UserMetricsAction("SearchWithRLZ"));
53872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        else
53972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          UserMetrics::RecordAction(UserMetricsAction("SearchWithoutRLZ"));
54072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
54172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return;
54272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
54372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
54472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
54572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
54672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TemplateURLRef::InvalidateCachedValues() const {
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  supports_replacements_ = valid_ = parsed_ = false;
549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  host_.clear();
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  path_.clear();
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  search_term_key_.clear();
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  replacements_.clear();
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TemplateURL ----------------------------------------------------------------
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGURL TemplateURL::GenerateFaviconURL(const GURL& url) {
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(url.is_valid());
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL::Replacements rep;
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char favicon_path[] = "/favicon.ico";
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int favicon_path_len = arraysize(favicon_path) - 1;
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.SetPath(favicon_path, url_parse::Component(0, favicon_path_len));
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearUsername();
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearPassword();
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearQuery();
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rep.ClearRef();
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return url.ReplaceComponents(rep);
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TemplateURL::SupportsReplacement(const TemplateURL* turl) {
5753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  UIThreadSearchTermsData search_terms_data;
5763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return SupportsReplacementUsingTermsData(turl, search_terms_data);
5773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
5783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static
5803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool TemplateURL::SupportsReplacementUsingTermsData(
5813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const TemplateURL* turl,
5823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const SearchTermsData& search_terms_data) {
5833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return turl && turl->url() &&
5843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      turl->url()->SupportsReplacementUsingTermsData(search_terms_data);
5853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
5863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
5873345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTemplateURL::TemplateURL()
5883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : autogenerate_keyword_(false),
5893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      keyword_generated_(false),
5903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      show_in_default_list_(false),
5913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      safe_for_autoreplace_(false),
5923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      id_(0),
5933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      date_created_(base::Time::Now()),
5943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      created_by_policy_(false),
5953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      usage_count_(0),
596513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      search_engine_type_(SEARCH_ENGINE_OTHER),
597513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      logo_id_(kNoSearchEngineLogo),
5983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      prepopulate_id_(0) {
5993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6013345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickTemplateURL::~TemplateURL() {
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
60472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 TemplateURL::AdjustedShortNameForLocaleDirection() const {
60572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  string16 bidi_safe_short_name = short_name_;
606201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  base::i18n::AdjustStringForLocaleDirection(&bidi_safe_short_name);
607201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return bidi_safe_short_name;
608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TemplateURL::SetSuggestionsURL(const std::string& suggestions_url,
611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    int index_offset,
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    int page_offset) {
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  suggestions_url_.Set(suggestions_url, index_offset, page_offset);
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TemplateURL::SetURL(const std::string& url,
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         int index_offset,
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                         int page_offset) {
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url_.Set(url, index_offset, page_offset);
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
622731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid TemplateURL::SetInstantURL(const std::string& url,
623731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                int index_offset,
624731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                                int page_offset) {
625731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  instant_url_.Set(url, index_offset, page_offset);
626731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
627731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
62872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid TemplateURL::set_keyword(const string16& keyword) {
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Case sensitive keyword matching is confusing. As such, we force all
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // keywords to be lower case.
63172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  keyword_ = l10n_util::ToLower(keyword);
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  autogenerate_keyword_ = false;
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
63572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 TemplateURL::keyword() const {
6363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EnsureKeyword();
6373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return keyword_;
6383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
6393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
6403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid TemplateURL::EnsureKeyword() const {
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (autogenerate_keyword_ && !keyword_generated_) {
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Generate a keyword and cache it.
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    keyword_ = TemplateURLModel::GenerateKeyword(
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        TemplateURLModel::GenerateSearchURL(this).GetWithEmptyPath(), true);
645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    keyword_generated_ = true;
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TemplateURL::ShowInDefaultList() const {
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return show_in_default_list() && url() && url()->SupportsReplacement();
651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
653ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid TemplateURL::SetFaviconURL(const GURL& url) {
654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::vector<ImageRef>::iterator i = image_refs_.begin();
655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != image_refs_.end(); ++i) {
65672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (i->type == "image/x-icon" &&
657ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        i->width == kFaviconSize && i->height == kFaviconSize) {
658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (!url.is_valid())
659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        image_refs_.erase(i);
660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      else
661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        i->url = url;
662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
664c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Don't have one yet, add it.
666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (url.is_valid()) {
667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    add_image_ref(
668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        TemplateURL::ImageRef("image/x-icon", kFaviconSize,
669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                              kFaviconSize, url));
670c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
671c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
672c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
673ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenGURL TemplateURL::GetFaviconURL() const {
674c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::vector<ImageRef>::const_iterator i = image_refs_.begin();
675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != image_refs_.end(); ++i) {
67672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if ((i->type == "image/x-icon" || i->type == "image/vnd.microsoft.icon")
677ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        && i->width == kFaviconSize && i->height == kFaviconSize) {
678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return i->url;
679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GURL();
682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid TemplateURL::InvalidateCachedValues() const {
685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url_.InvalidateCachedValues();
686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  suggestions_url_.InvalidateCachedValues();
687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (autogenerate_keyword_) {
688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    keyword_.clear();
689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    keyword_generated_ = false;
690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string TemplateURL::GetExtensionId() const {
694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(IsExtensionKeyword());
695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GURL(url_.url()).host();
696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool TemplateURL::IsExtensionKeyword() const {
699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GURL(url_.url()).SchemeIs(chrome::kExtensionScheme);
700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
701