| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2008 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 #include "chrome/browser/template_url.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "base/string_util.h" | |
| 9 #include "chrome/browser/browser_process.h" | |
| 10 #include "chrome/browser/rlz/rlz.h" | |
| 11 #include "chrome/browser/google_url_tracker.h" | |
| 12 #include "chrome/browser/template_url_model.h" | |
| 13 #include "chrome/common/gfx/favicon_size.h" | |
| 14 #include "chrome/common/l10n_util.h" | |
| 15 #include "net/base/escape.h" | |
| 16 | |
| 17 // The TemplateURLRef has any number of terms that need to be replaced. Each of | |
| 18 // the terms is enclosed in braces. If the character preceeding the final | |
| 19 // brace is a ?, it indicates the term is optional and can be replaced with | |
| 20 // an empty string. | |
| 21 static const wchar_t kStartParameter = '{'; | |
| 22 static const wchar_t kEndParameter = '}'; | |
| 23 static const wchar_t kOptional = '?'; | |
| 24 | |
| 25 // Known parameters found in the URL. | |
| 26 static const wchar_t kSearchTermsParameter[] = L"searchTerms"; | |
| 27 static const wchar_t kSearchTermsParameterFull[] = L"{searchTerms}"; | |
| 28 static const wchar_t kCountParameter[] = L"count"; | |
| 29 static const wchar_t kStartIndexParameter[] = L"startIndex"; | |
| 30 static const wchar_t kStartPageParameter[] = L"startPage"; | |
| 31 static const wchar_t kLanguageParameter[] = L"language"; | |
| 32 static const wchar_t kInputEncodingParameter[] = L"inputEncoding"; | |
| 33 static const wchar_t kOutputEncodingParameter[] = L"outputEncoding"; | |
| 34 | |
| 35 static const wchar_t kGoogleAcceptedSuggestionParameter[] = | |
| 36 L"google:acceptedSuggestion"; | |
| 37 // Host/Domain Google searches are relative to. | |
| 38 static const wchar_t kGoogleBaseURLParameter[] = L"google:baseURL"; | |
| 39 static const wchar_t kGoogleBaseURLParameterFull[] = L"{google:baseURL}"; | |
| 40 // Like google:baseURL, but for the Search Suggest capability. | |
| 41 static const wchar_t kGoogleBaseSuggestURLParameter[] = | |
| 42 L"google:baseSuggestURL"; | |
| 43 static const wchar_t kGoogleBaseSuggestURLParameterFull[] = | |
| 44 L"{google:baseSuggestURL}"; | |
| 45 static const wchar_t kGoogleOriginalQueryForSuggestionParameter[] = | |
| 46 L"google:originalQueryForSuggestion"; | |
| 47 static const wchar_t kGoogleRLZParameter[] = L"google:RLZ"; | |
| 48 // Same as kSearchTermsParameter, with no escaping. | |
| 49 static const wchar_t kGoogleUnescapedSearchTermsParameter[] = | |
| 50 L"google:unescapedSearchTerms"; | |
| 51 static const wchar_t kGoogleUnescapedSearchTermsParameterFull[] = | |
| 52 L"{google:unescapedSearchTerms}"; | |
| 53 | |
| 54 // Display value for kSearchTermsParameter. | |
| 55 static const wchar_t kDisplaySearchTerms[] = L"%s"; | |
| 56 | |
| 57 // Display value for kGoogleUnescapedSearchTermsParameter. | |
| 58 static const wchar_t kDisplayUnescapedSearchTerms[] = L"%S"; | |
| 59 | |
| 60 // Used if the count parameter is not optional. Indicates we want 10 search | |
| 61 // results. | |
| 62 static const wchar_t kDefaultCount[] = L"10"; | |
| 63 | |
| 64 // Used if the parameter kOutputEncodingParameter is required. | |
| 65 static const wchar_t kOutputEncodingType[] = L"UTF-8"; | |
| 66 | |
| 67 // static | |
| 68 std::wstring* TemplateURLRef::google_base_url_ = NULL; | |
| 69 | |
| 70 TemplateURLRef::TemplateURLRef() { | |
| 71 Set(std::wstring(), 0, 0); | |
| 72 } | |
| 73 | |
| 74 void TemplateURLRef::Set(const std::wstring& url, | |
| 75 int index_offset, | |
| 76 int page_offset) { | |
| 77 url_ = url; | |
| 78 index_offset_ = index_offset; | |
| 79 page_offset_ = page_offset; | |
| 80 InvalidateCachedValues(); | |
| 81 } | |
| 82 | |
| 83 bool TemplateURLRef::ParseParameter(size_t start, | |
| 84 size_t end, | |
| 85 std::wstring* url, | |
| 86 Replacements* replacements) const { | |
| 87 DCHECK(start != std::string::npos && | |
| 88 end != std::string::npos && end > start); | |
| 89 size_t length = end - start - 1; | |
| 90 bool optional = false; | |
| 91 if ((*url)[end - 1] == kOptional) { | |
| 92 optional = true; | |
| 93 length--; | |
| 94 } | |
| 95 std::wstring parameter(url->substr(start + 1, length)); | |
| 96 // Remove the parameter from the string. | |
| 97 url->erase(start, end - start + 1); | |
| 98 if (parameter == kSearchTermsParameter) { | |
| 99 replacements->push_back(Replacement(SEARCH_TERMS, static_cast<int>(start))); | |
| 100 } else if (parameter == kCountParameter) { | |
| 101 if (!optional) | |
| 102 url->insert(start, kDefaultCount); | |
| 103 } else if (parameter == kStartIndexParameter) { | |
| 104 if (!optional) { | |
| 105 url->insert(start, IntToWString(index_offset_)); | |
| 106 } | |
| 107 } else if (parameter == kStartPageParameter) { | |
| 108 if (!optional) { | |
| 109 url->insert(start, IntToWString(page_offset_)); | |
| 110 } | |
| 111 } else if (parameter == kLanguageParameter) { | |
| 112 replacements->push_back(Replacement(LANGUAGE, static_cast<int>(start))); | |
| 113 } else if (parameter == kInputEncodingParameter) { | |
| 114 replacements->push_back(Replacement(ENCODING, static_cast<int>(start))); | |
| 115 } else if (parameter == kOutputEncodingParameter) { | |
| 116 if (!optional) | |
| 117 url->insert(start, kOutputEncodingType); | |
| 118 } else if (parameter == kGoogleAcceptedSuggestionParameter) { | |
| 119 replacements->push_back(Replacement(GOOGLE_ACCEPTED_SUGGESTION, | |
| 120 static_cast<int>(start))); | |
| 121 } else if (parameter == kGoogleBaseURLParameter) { | |
| 122 replacements->push_back(Replacement(GOOGLE_BASE_URL, | |
| 123 static_cast<int>(start))); | |
| 124 } else if (parameter == kGoogleBaseSuggestURLParameter) { | |
| 125 replacements->push_back(Replacement(GOOGLE_BASE_SUGGEST_URL, | |
| 126 static_cast<int>(start))); | |
| 127 } else if (parameter == kGoogleOriginalQueryForSuggestionParameter) { | |
| 128 replacements->push_back(Replacement(GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION, | |
| 129 static_cast<int>(start))); | |
| 130 } else if (parameter == kGoogleRLZParameter) { | |
| 131 replacements->push_back(Replacement(GOOGLE_RLZ, static_cast<int>(start))); | |
| 132 } else if (parameter == kGoogleUnescapedSearchTermsParameter) { | |
| 133 replacements->push_back(Replacement(GOOGLE_UNESCAPED_SEARCH_TERMS, | |
| 134 static_cast<int>(start))); | |
| 135 } else if (!optional) { | |
| 136 // Unknown required parameter. No idea what to replace this with, | |
| 137 // so fail. | |
| 138 return false; | |
| 139 } | |
| 140 return true; | |
| 141 } | |
| 142 | |
| 143 std::wstring TemplateURLRef::ParseURL(const std::wstring& url, | |
| 144 Replacements* replacements, | |
| 145 bool* valid) const { | |
| 146 *valid = false; | |
| 147 std::wstring parsed_url = url; | |
| 148 for (size_t last = 0; last != std::string::npos; ) { | |
| 149 last = parsed_url.find(kStartParameter, last); | |
| 150 if (last != std::string::npos) { | |
| 151 size_t endTemplate = parsed_url.find(kEndParameter, last); | |
| 152 if (endTemplate != std::string::npos) { | |
| 153 if (!ParseParameter(last, endTemplate, &parsed_url, replacements)) { | |
| 154 // Not a valid parameter, return. | |
| 155 return std::wstring(); | |
| 156 } | |
| 157 // ParseParamter erases from the string, as such we don't need | |
| 158 // to update last. | |
| 159 } else { | |
| 160 // Open brace without a closing brace, return. | |
| 161 return std::wstring(); | |
| 162 } | |
| 163 } | |
| 164 } | |
| 165 *valid = true; | |
| 166 return parsed_url; | |
| 167 } | |
| 168 | |
| 169 void TemplateURLRef::ParseIfNecessary() const { | |
| 170 if (!parsed_) { | |
| 171 parsed_ = true; | |
| 172 parsed_url_ = ParseURL(url_, &replacements_, &valid_); | |
| 173 supports_replacements_ = false; | |
| 174 if (valid_) { | |
| 175 bool has_only_one_search_term = false; | |
| 176 for (Replacements::const_iterator i = replacements_.begin(); | |
| 177 i != replacements_.end(); ++i) { | |
| 178 if ((i->type == SEARCH_TERMS) || | |
| 179 (i->type == GOOGLE_UNESCAPED_SEARCH_TERMS)) { | |
| 180 if (has_only_one_search_term) { | |
| 181 has_only_one_search_term = false; | |
| 182 break; | |
| 183 } | |
| 184 has_only_one_search_term = true; | |
| 185 supports_replacements_ = true; | |
| 186 } | |
| 187 } | |
| 188 // Only parse the host/key if there is one search term. Technically there | |
| 189 // could be more than one term, but it's uncommon; so we punt. | |
| 190 if (has_only_one_search_term) | |
| 191 ParseHostAndSearchTermKey(); | |
| 192 } | |
| 193 } | |
| 194 } | |
| 195 | |
| 196 void TemplateURLRef::ParseHostAndSearchTermKey() const { | |
| 197 std::wstring url_string = url_; | |
| 198 ReplaceSubstringsAfterOffset(&url_string, 0, kGoogleBaseURLParameterFull, | |
| 199 GoogleBaseURLValue()); | |
| 200 ReplaceSubstringsAfterOffset(&url_string, 0, | |
| 201 kGoogleBaseSuggestURLParameterFull, | |
| 202 GoogleBaseSuggestURLValue()); | |
| 203 | |
| 204 GURL url(WideToUTF8(url_string)); | |
| 205 if (!url.is_valid()) | |
| 206 return; | |
| 207 | |
| 208 std::string query_string = url.query(); | |
| 209 if (query_string.empty()) | |
| 210 return; | |
| 211 | |
| 212 url_parse::Component query, key, value; | |
| 213 query.len = static_cast<int>(query_string.size()); | |
| 214 while (url_parse::ExtractQueryKeyValue(query_string.c_str(), &query, &key, | |
| 215 &value)) { | |
| 216 if (key.is_nonempty() && value.is_nonempty()) { | |
| 217 std::string value_string = query_string.substr(value.begin, value.len); | |
| 218 if (value_string.find(WideToASCII(kSearchTermsParameterFull), 0) != | |
| 219 std::string::npos || | |
| 220 value_string.find( | |
| 221 WideToASCII(kGoogleUnescapedSearchTermsParameterFull), 0) != | |
| 222 std::string::npos) { | |
| 223 search_term_key_ = query_string.substr(key.begin, key.len); | |
| 224 host_ = url.host(); | |
| 225 path_ = url.path(); | |
| 226 break; | |
| 227 } | |
| 228 } | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 GURL TemplateURLRef::ReplaceSearchTerms( | |
| 233 const TemplateURL& host, | |
| 234 const std::wstring& terms, | |
| 235 int accepted_suggestion, | |
| 236 const std::wstring& original_query_for_suggestion) const { | |
| 237 ParseIfNecessary(); | |
| 238 if (!valid_) | |
| 239 return GURL(); | |
| 240 | |
| 241 if (replacements_.empty()) | |
| 242 return GURL(WideToUTF8(parsed_url_)); | |
| 243 | |
| 244 // Encode the search terms so that we know the encoding. | |
| 245 const std::vector<std::string>& encodings = host.input_encodings(); | |
| 246 std::wstring encoded_terms; | |
| 247 std::wstring encoded_original_query; | |
| 248 std::wstring input_encoding; | |
| 249 for (size_t i = 0; i < encodings.size(); ++i) { | |
| 250 if (EscapeQueryParamValue(terms, encodings[i].c_str(), &encoded_terms)) { | |
| 251 if (!original_query_for_suggestion.empty()) { | |
| 252 EscapeQueryParamValue(original_query_for_suggestion, | |
| 253 encodings[i].c_str(), &encoded_original_query); | |
| 254 } | |
| 255 input_encoding = ASCIIToWide(encodings[i]); | |
| 256 break; | |
| 257 } | |
| 258 } | |
| 259 if (input_encoding.empty()) { | |
| 260 encoded_terms = EscapeQueryParamValueUTF8(terms); | |
| 261 if (!original_query_for_suggestion.empty()) { | |
| 262 encoded_original_query = | |
| 263 EscapeQueryParamValueUTF8(original_query_for_suggestion); | |
| 264 } | |
| 265 input_encoding = L"UTF-8"; | |
| 266 } | |
| 267 | |
| 268 std::wstring url = parsed_url_; | |
| 269 | |
| 270 // replacements_ is ordered in ascending order, as such we need to iterate | |
| 271 // from the back. | |
| 272 for (Replacements::reverse_iterator i = replacements_.rbegin(); | |
| 273 i != replacements_.rend(); ++i) { | |
| 274 switch (i->type) { | |
| 275 case ENCODING: | |
| 276 url.insert(i->index, input_encoding); | |
| 277 break; | |
| 278 | |
| 279 case GOOGLE_ACCEPTED_SUGGESTION: | |
| 280 if (accepted_suggestion == NO_SUGGESTION_CHOSEN) | |
| 281 url.insert(i->index, L"aq=f&"); | |
| 282 else if (accepted_suggestion != NO_SUGGESTIONS_AVAILABLE) | |
| 283 url.insert(i->index, StringPrintf(L"aq=%d&", accepted_suggestion)); | |
| 284 break; | |
| 285 | |
| 286 case GOOGLE_BASE_URL: | |
| 287 url.insert(i->index, GoogleBaseURLValue()); | |
| 288 break; | |
| 289 | |
| 290 case GOOGLE_BASE_SUGGEST_URL: | |
| 291 url.insert(i->index, GoogleBaseSuggestURLValue()); | |
| 292 break; | |
| 293 | |
| 294 case GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION: | |
| 295 if (accepted_suggestion >= 0) | |
| 296 url.insert(i->index, L"oq=" + encoded_original_query + L"&"); | |
| 297 break; | |
| 298 | |
| 299 case GOOGLE_RLZ: { | |
| 300 std::wstring rlz_string; | |
| 301 RLZTracker::GetAccessPointRlz(RLZTracker::CHROME_OMNIBOX, &rlz_string); | |
| 302 if (!rlz_string.empty()) { | |
| 303 rlz_string = L"rlz=" + rlz_string + L"&"; | |
| 304 url.insert(i->index, rlz_string); | |
| 305 } | |
| 306 break; | |
| 307 } | |
| 308 | |
| 309 case GOOGLE_UNESCAPED_SEARCH_TERMS: { | |
| 310 std::string unescaped_terms; | |
| 311 WideToCodepage(terms, WideToASCII(input_encoding).c_str(), | |
| 312 OnStringUtilConversionError::SKIP, &unescaped_terms); | |
| 313 url.insert(i->index, std::wstring(unescaped_terms.begin(), | |
| 314 unescaped_terms.end())); | |
| 315 break; | |
| 316 } | |
| 317 | |
| 318 case LANGUAGE: | |
| 319 url.insert(i->index, g_browser_process->GetApplicationLocale()); | |
| 320 break; | |
| 321 | |
| 322 case SEARCH_TERMS: | |
| 323 url.insert(i->index, encoded_terms); | |
| 324 break; | |
| 325 | |
| 326 default: | |
| 327 NOTREACHED(); | |
| 328 break; | |
| 329 } | |
| 330 } | |
| 331 | |
| 332 return GURL(WideToUTF8(url)); | |
| 333 } | |
| 334 | |
| 335 bool TemplateURLRef::SupportsReplacement() const { | |
| 336 ParseIfNecessary(); | |
| 337 return valid_ && supports_replacements_; | |
| 338 } | |
| 339 | |
| 340 bool TemplateURLRef::IsValid() const { | |
| 341 ParseIfNecessary(); | |
| 342 return valid_; | |
| 343 } | |
| 344 | |
| 345 std::wstring TemplateURLRef::DisplayURL() const { | |
| 346 ParseIfNecessary(); | |
| 347 if (!valid_) | |
| 348 return url_; // If we're not valid, don't escape anything. | |
| 349 | |
| 350 if (replacements_.empty()) | |
| 351 return url_; // Nothing to replace, return the url. | |
| 352 | |
| 353 std::wstring result = url_; | |
| 354 ReplaceSubstringsAfterOffset(&result, 0, kSearchTermsParameterFull, | |
| 355 kDisplaySearchTerms); | |
| 356 | |
| 357 ReplaceSubstringsAfterOffset(&result, 0, | |
| 358 kGoogleUnescapedSearchTermsParameterFull, | |
| 359 kDisplayUnescapedSearchTerms); | |
| 360 | |
| 361 return result; | |
| 362 } | |
| 363 | |
| 364 // static | |
| 365 std::wstring TemplateURLRef::DisplayURLToURLRef( | |
| 366 const std::wstring& display_url) { | |
| 367 std::wstring result = display_url; | |
| 368 ReplaceSubstringsAfterOffset(&result, 0, kDisplaySearchTerms, | |
| 369 kSearchTermsParameterFull); | |
| 370 ReplaceSubstringsAfterOffset(&result, 0, kDisplayUnescapedSearchTerms, | |
| 371 kGoogleUnescapedSearchTermsParameterFull); | |
| 372 return result; | |
| 373 } | |
| 374 | |
| 375 const std::string& TemplateURLRef::GetHost() const { | |
| 376 ParseIfNecessary(); | |
| 377 return host_; | |
| 378 } | |
| 379 | |
| 380 const std::string& TemplateURLRef::GetPath() const { | |
| 381 ParseIfNecessary(); | |
| 382 return path_; | |
| 383 } | |
| 384 | |
| 385 const std::string& TemplateURLRef::GetSearchTermKey() const { | |
| 386 ParseIfNecessary(); | |
| 387 return search_term_key_; | |
| 388 } | |
| 389 | |
| 390 std::wstring TemplateURLRef::SearchTermToWide(const TemplateURL& host, | |
| 391 const std::string& term) const { | |
| 392 const std::vector<std::string>& encodings = host.input_encodings(); | |
| 393 std::wstring result; | |
| 394 | |
| 395 std::string unescaped = | |
| 396 UnescapeURLComponent(term, UnescapeRule::REPLACE_PLUS_WITH_SPACE); | |
| 397 for (size_t i = 0; i < encodings.size(); ++i) { | |
| 398 if (CodepageToWide(unescaped, encodings[i].c_str(), | |
| 399 OnStringUtilConversionError::FAIL, &result)) | |
| 400 return result; | |
| 401 } | |
| 402 | |
| 403 // Always fall back on UTF-8 if it works. | |
| 404 if (CodepageToWide(unescaped, "UTF-8", | |
| 405 OnStringUtilConversionError::FAIL, &result)) | |
| 406 return result; | |
| 407 | |
| 408 // When nothing worked, just use the escaped text. We have no idea what the | |
| 409 // encoding is. We need to substitute spaces for pluses ourselves since we're | |
| 410 // not sending it through an unescaper. | |
| 411 result = UTF8ToWide(term); | |
| 412 std::replace(result.begin(), result.end(), '+', ' '); | |
| 413 return result; | |
| 414 } | |
| 415 | |
| 416 bool TemplateURLRef::HasGoogleBaseURLs() const { | |
| 417 ParseIfNecessary(); | |
| 418 for (size_t i = 0; i < replacements_.size(); ++i) { | |
| 419 if ((replacements_[i].type == GOOGLE_BASE_URL) || | |
| 420 (replacements_[i].type == GOOGLE_BASE_SUGGEST_URL)) | |
| 421 return true; | |
| 422 } | |
| 423 return false; | |
| 424 } | |
| 425 | |
| 426 void TemplateURLRef::InvalidateCachedValues() const { | |
| 427 supports_replacements_ = valid_ = parsed_ = false; | |
| 428 host_.clear(); | |
| 429 path_.clear(); | |
| 430 search_term_key_.clear(); | |
| 431 replacements_.clear(); | |
| 432 } | |
| 433 | |
| 434 // Returns the value to use for replacements of type GOOGLE_BASE_URL. | |
| 435 // static | |
| 436 std::wstring TemplateURLRef::GoogleBaseURLValue() { | |
| 437 return google_base_url_ ? | |
| 438 (*google_base_url_) : UTF8ToWide(GoogleURLTracker::GoogleURL().spec()); | |
| 439 } | |
| 440 | |
| 441 // Returns the value to use for replacements of type GOOGLE_BASE_SUGGEST_URL. | |
| 442 // static | |
| 443 std::wstring TemplateURLRef::GoogleBaseSuggestURLValue() { | |
| 444 // The suggest base URL we want at the end is something like | |
| 445 // "http://clients1.google.TLD/complete/". The key bit we want from the | |
| 446 // original Google base URL is the TLD. | |
| 447 | |
| 448 // Start with the Google base URL. | |
| 449 const GURL base_url(google_base_url_ ? | |
| 450 GURL(WideToUTF8(*google_base_url_)) : GoogleURLTracker::GoogleURL()); | |
| 451 DCHECK(base_url.is_valid()); | |
| 452 | |
| 453 // Change "www." to "clients1." in the hostname. If no "www." was found, just | |
| 454 // prepend "clients1.". | |
| 455 const std::string base_host(base_url.host()); | |
| 456 GURL::Replacements repl; | |
| 457 const std::string suggest_host("clients1." + | |
| 458 (base_host.compare(0, 4, "www.") ? base_host : base_host.substr(4))); | |
| 459 repl.SetHostStr(suggest_host); | |
| 460 | |
| 461 // Replace any existing path with "/complete/". | |
| 462 static const std::string suggest_path("/complete/"); | |
| 463 repl.SetPathStr(suggest_path); | |
| 464 | |
| 465 // Clear the query and ref. | |
| 466 repl.ClearQuery(); | |
| 467 repl.ClearRef(); | |
| 468 return UTF8ToWide(base_url.ReplaceComponents(repl).spec()); | |
| 469 } | |
| 470 | |
| 471 // TemplateURL ---------------------------------------------------------------- | |
| 472 | |
| 473 // static | |
| 474 GURL TemplateURL::GenerateFaviconURL(const GURL& url) { | |
| 475 DCHECK(url.is_valid()); | |
| 476 GURL::Replacements rep; | |
| 477 | |
| 478 const char favicon_path[] = "/favicon.ico"; | |
| 479 int favicon_path_len = arraysize(favicon_path) - 1; | |
| 480 | |
| 481 rep.SetPath(favicon_path, url_parse::Component(0, favicon_path_len)); | |
| 482 rep.ClearUsername(); | |
| 483 rep.ClearPassword(); | |
| 484 rep.ClearQuery(); | |
| 485 rep.ClearRef(); | |
| 486 return url.ReplaceComponents(rep); | |
| 487 } | |
| 488 | |
| 489 void TemplateURL::SetSuggestionsURL(const std::wstring& suggestions_url, | |
| 490 int index_offset, | |
| 491 int page_offset) { | |
| 492 suggestions_url_.Set(suggestions_url, index_offset, page_offset); | |
| 493 } | |
| 494 | |
| 495 void TemplateURL::SetURL(const std::wstring& url, | |
| 496 int index_offset, | |
| 497 int page_offset) { | |
| 498 url_.Set(url, index_offset, page_offset); | |
| 499 } | |
| 500 | |
| 501 void TemplateURL::set_keyword(const std::wstring& keyword) { | |
| 502 // Case sensitive keyword matching is confusing. As such, we force all | |
| 503 // keywords to be lower case. | |
| 504 keyword_ = l10n_util::ToLower(keyword); | |
| 505 autogenerate_keyword_ = false; | |
| 506 } | |
| 507 | |
| 508 const std::wstring& TemplateURL::keyword() const { | |
| 509 if (autogenerate_keyword_ && keyword_.empty()) { | |
| 510 // Generate a keyword and cache it. | |
| 511 keyword_ = TemplateURLModel::GenerateKeyword( | |
| 512 TemplateURLModel::GenerateSearchURL(this).GetWithEmptyPath(), true); | |
| 513 } | |
| 514 return keyword_; | |
| 515 } | |
| 516 | |
| 517 bool TemplateURL::ShowInDefaultList() const { | |
| 518 return show_in_default_list() && url() && url()->SupportsReplacement(); | |
| 519 } | |
| 520 | |
| 521 void TemplateURL::SetFavIconURL(const GURL& url) { | |
| 522 for (std::vector<ImageRef>::iterator i = image_refs_.begin(); | |
| 523 i != image_refs_.end(); ++i) { | |
| 524 if (i->type == L"image/x-icon" && | |
| 525 i->width == kFavIconSize && i->height == kFavIconSize) { | |
| 526 if (!url.is_valid()) | |
| 527 image_refs_.erase(i); | |
| 528 else | |
| 529 i->url = url; | |
| 530 return; | |
| 531 } | |
| 532 } | |
| 533 // Don't have one yet, add it. | |
| 534 if (url.is_valid()) { | |
| 535 add_image_ref( | |
| 536 TemplateURL::ImageRef(L"image/x-icon", kFavIconSize, kFavIconSize, | |
| 537 url)); | |
| 538 } | |
| 539 } | |
| 540 | |
| 541 GURL TemplateURL::GetFavIconURL() const { | |
| 542 for (std::vector<ImageRef>::const_iterator i = image_refs_.begin(); | |
| 543 i != image_refs_.end(); ++i) { | |
| 544 if ((i->type == L"image/x-icon" || i->type == L"image/vnd.microsoft.icon") | |
| 545 && i->width == kFavIconSize && i->height == kFavIconSize) { | |
| 546 return i->url; | |
| 547 } | |
| 548 } | |
| 549 return GURL(); | |
| 550 } | |
| 551 | |
| 552 void TemplateURL::InvalidateCachedValues() const { | |
| 553 url_.InvalidateCachedValues(); | |
| 554 suggestions_url_.InvalidateCachedValues(); | |
| 555 if (autogenerate_keyword_) | |
| 556 keyword_.clear(); | |
| 557 } | |
| 558 | |
| OLD | NEW |