Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/search/search.h" | 5 #include "chrome/browser/search/search.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 93 } | 93 } |
| 94 | 94 |
| 95 bool MatchesOrigin(const GURL& my_url, const GURL& other_url) { | 95 bool MatchesOrigin(const GURL& my_url, const GURL& other_url) { |
| 96 return my_url.host() == other_url.host() && | 96 return my_url.host() == other_url.host() && |
| 97 my_url.port() == other_url.port() && | 97 my_url.port() == other_url.port() && |
| 98 (my_url.scheme() == other_url.scheme() || | 98 (my_url.scheme() == other_url.scheme() || |
| 99 (my_url.SchemeIs(chrome::kHttpsScheme) && | 99 (my_url.SchemeIs(chrome::kHttpsScheme) && |
| 100 other_url.SchemeIs(chrome::kHttpScheme))); | 100 other_url.SchemeIs(chrome::kHttpScheme))); |
| 101 } | 101 } |
| 102 | 102 |
| 103 bool IsCommandLineInstantURL(const GURL& url) { | |
| 104 const CommandLine* cl = CommandLine::ForCurrentProcess(); | |
| 105 const GURL instant_url(cl->GetSwitchValueASCII(switches::kInstantURL)); | |
| 106 return instant_url.is_valid() && MatchesOrigin(url, instant_url); | |
| 107 } | |
| 108 | |
| 109 bool MatchesAnySearchURL(const GURL& url, TemplateURL* template_url) { | 103 bool MatchesAnySearchURL(const GURL& url, TemplateURL* template_url) { |
| 110 GURL search_url = | 104 GURL search_url = |
| 111 TemplateURLRefToGURL(template_url->url_ref(), kDisableStartMargin); | 105 TemplateURLRefToGURL(template_url->url_ref(), kDisableStartMargin); |
| 112 if (search_url.is_valid() && MatchesOriginAndPath(url, search_url)) | 106 if (search_url.is_valid() && MatchesOriginAndPath(url, search_url)) |
| 113 return true; | 107 return true; |
| 114 | 108 |
| 115 // "URLCount() - 1" because we already tested url_ref above. | 109 // "URLCount() - 1" because we already tested url_ref above. |
| 116 for (size_t i = 0; i < template_url->URLCount() - 1; ++i) { | 110 for (size_t i = 0; i < template_url->URLCount() - 1; ++i) { |
| 117 TemplateURLRef ref(template_url, i); | 111 TemplateURLRef ref(template_url, i); |
| 118 search_url = TemplateURLRefToGURL(ref, kDisableStartMargin); | 112 search_url = TemplateURLRefToGURL(ref, kDisableStartMargin); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 return false; | 181 return false; |
| 188 | 182 |
| 189 const InstantService* instant_service = | 183 const InstantService* instant_service = |
| 190 InstantServiceFactory::GetForProfile(profile); | 184 InstantServiceFactory::GetForProfile(profile); |
| 191 if (!instant_service) | 185 if (!instant_service) |
| 192 return false; | 186 return false; |
| 193 | 187 |
| 194 return instant_service->IsInstantProcess(process_host->GetID()); | 188 return instant_service->IsInstantProcess(process_host->GetID()); |
| 195 } | 189 } |
| 196 | 190 |
| 191 // Returns true if |url| starts with a command-line-specified Google base URL. | |
| 192 bool StartsWithCommandLineGoogleBaseURL(const GURL& url) { | |
| 193 const std::string base_url(CommandLine::ForCurrentProcess()-> | |
| 194 GetSwitchValueASCII(switches::kGoogleBaseURL)); | |
| 195 // We do a direct string comparison because we're not worried about trying to | |
| 196 // support e.g. one URL saying ":80" after the hostname. | |
| 197 return !base_url.empty() && | |
| 198 StartsWithASCII(url.possibly_invalid_spec(), base_url, true); | |
| 199 } | |
| 200 | |
| 201 // Returns true if |url| passes some basic checks that must succeed for it to be | |
| 202 // usable as an instant URL: | |
| 203 // (1) It contains the search terms replacement key of |default_turl|, which is | |
| 204 // expected to be the TemplateURL* for the default search provider. | |
| 205 // (2) Either it has a secure scheme, or else the user has manually specified a | |
| 206 // --google-base-url and it uses that base URL. (This allows testers to use | |
| 207 // --google-base-url to point at non-HTTPS servers, which eases testing.) | |
| 208 bool IsSuitableURLForInstant(const GURL& url, const TemplateURL* default_turl) { | |
|
Jered
2013/06/25 16:30:39
default_turl -> search_template or template_url ("
Peter Kasting
2013/06/25 23:06:36
Changed, though I actually preferred the old termi
| |
| 209 return default_turl->HasSearchTermsReplacementKey(url) && | |
| 210 (url.SchemeIsSecure() || StartsWithCommandLineGoogleBaseURL(url)); | |
| 211 } | |
| 212 | |
| 197 // Returns true if |url| can be used as an Instant URL for |profile|. | 213 // Returns true if |url| can be used as an Instant URL for |profile|. |
| 198 bool IsInstantURL(const GURL& url, Profile* profile) { | 214 bool IsInstantURL(const GURL& url, Profile* profile) { |
| 215 if (!url.is_valid()) | |
| 216 return false; | |
| 217 | |
| 199 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); | 218 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); |
| 200 if (!template_url) | 219 if (!template_url) |
| 201 return false; | 220 return false; |
| 202 | 221 |
| 203 const TemplateURLRef& instant_url_ref = template_url->instant_url_ref(); | |
| 204 const bool extended_api_enabled = IsInstantExtendedAPIEnabled(); | 222 const bool extended_api_enabled = IsInstantExtendedAPIEnabled(); |
| 205 GURL effective_url = url; | 223 if (extended_api_enabled && !IsSuitableURLForInstant(url, template_url)) |
| 206 | |
| 207 if (IsCommandLineInstantURL(url)) | |
| 208 effective_url = CoerceCommandLineURLToTemplateURL(url, instant_url_ref, | |
| 209 kDisableStartMargin); | |
| 210 | |
| 211 if (!effective_url.is_valid()) | |
| 212 return false; | 224 return false; |
| 213 | 225 |
| 214 if (extended_api_enabled && !effective_url.SchemeIsSecure()) | 226 const TemplateURLRef& instant_url_ref = template_url->instant_url_ref(); |
| 215 return false; | |
| 216 | |
| 217 if (extended_api_enabled && | |
| 218 !template_url->HasSearchTermsReplacementKey(effective_url)) | |
| 219 return false; | |
| 220 | |
| 221 const GURL instant_url = | 227 const GURL instant_url = |
| 222 TemplateURLRefToGURL(instant_url_ref, kDisableStartMargin); | 228 TemplateURLRefToGURL(instant_url_ref, kDisableStartMargin); |
| 223 if (!instant_url.is_valid()) | 229 return instant_url.is_valid() && |
| 224 return false; | 230 (MatchesOriginAndPath(url, instant_url) || |
| 225 | 231 (extended_api_enabled && MatchesAnySearchURL(url, template_url))); |
| 226 if (MatchesOriginAndPath(effective_url, instant_url)) | |
| 227 return true; | |
| 228 | |
| 229 if (extended_api_enabled && MatchesAnySearchURL(effective_url, template_url)) | |
| 230 return true; | |
| 231 | |
| 232 return false; | |
| 233 } | 232 } |
| 234 | 233 |
| 235 string16 GetSearchTermsImpl(const content::WebContents* contents, | 234 string16 GetSearchTermsImpl(const content::WebContents* contents, |
| 236 const content::NavigationEntry* entry) { | 235 const content::NavigationEntry* entry) { |
| 237 // For security reasons, don't extract search terms if the page is not being | 236 // For security reasons, don't extract search terms if the page is not being |
| 238 // rendered in the privileged Instant renderer process. This is to protect | 237 // rendered in the privileged Instant renderer process. This is to protect |
| 239 // against a malicious page somehow scripting the search results page and | 238 // against a malicious page somehow scripting the search results page and |
| 240 // faking search terms in the URL. Random pages can't get into the Instant | 239 // faking search terms in the URL. Random pages can't get into the Instant |
| 241 // renderer and scripting doesn't work cross-process, so if the page is in | 240 // renderer and scripting doesn't work cross-process, so if the page is in |
| 242 // the Instant process, we know it isn't being exploited. | 241 // the Instant process, we know it isn't being exploited. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 305 | 304 |
| 306 FieldTrialFlags flags; | 305 FieldTrialFlags flags; |
| 307 if (GetFieldTrialInfo( | 306 if (GetFieldTrialInfo( |
| 308 base::FieldTrialList::FindFullName(kInstantExtendedFieldTrialName), | 307 base::FieldTrialList::FindFullName(kInstantExtendedFieldTrialName), |
| 309 &flags, NULL)) { | 308 &flags, NULL)) { |
| 310 return GetBoolValueForFlagWithDefault(kLocalOnlyFlagName, false, flags); | 309 return GetBoolValueForFlagWithDefault(kLocalOnlyFlagName, false, flags); |
| 311 } | 310 } |
| 312 return false; | 311 return false; |
| 313 } | 312 } |
| 314 | 313 |
| 315 string16 GetSearchTermsFromURL(Profile* profile, const GURL& in_url) { | 314 string16 GetSearchTermsFromURL(Profile* profile, const GURL& url) { |
| 316 GURL url(in_url); | |
| 317 string16 search_terms; | 315 string16 search_terms; |
| 318 | |
| 319 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); | 316 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); |
| 320 if (!template_url) | 317 if (template_url && IsSuitableURLForInstant(url, template_url)) |
| 321 return string16(); | |
| 322 | |
| 323 if (IsCommandLineInstantURL(url)) | |
| 324 url = CoerceCommandLineURLToTemplateURL(url, template_url->url_ref(), | |
| 325 kDisableStartMargin); | |
| 326 | |
| 327 if (url.SchemeIsSecure() && template_url->HasSearchTermsReplacementKey(url)) | |
| 328 template_url->ExtractSearchTermsFromURL(url, &search_terms); | 318 template_url->ExtractSearchTermsFromURL(url, &search_terms); |
| 329 | |
| 330 return search_terms; | 319 return search_terms; |
| 331 } | 320 } |
| 332 | 321 |
| 333 string16 GetSearchTermsFromNavigationEntry( | 322 string16 GetSearchTermsFromNavigationEntry( |
| 334 const content::NavigationEntry* entry) { | 323 const content::NavigationEntry* entry) { |
| 335 string16 search_terms; | 324 string16 search_terms; |
| 336 if (entry) | 325 if (entry) |
| 337 entry->GetExtraData(sessions::kSearchTermsKey, &search_terms); | 326 entry->GetExtraData(sessions::kSearchTermsKey, &search_terms); |
| 338 return search_terms; | 327 return search_terms; |
| 339 } | 328 } |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 return l10n_util::GetStringUTF16(IDS_INSTANT_CHECKBOX_PREDICTION_DISABLED); | 465 return l10n_util::GetStringUTF16(IDS_INSTANT_CHECKBOX_PREDICTION_DISABLED); |
| 477 | 466 |
| 478 DCHECK(IsInstantCheckboxEnabled(profile)); | 467 DCHECK(IsInstantCheckboxEnabled(profile)); |
| 479 return l10n_util::GetStringUTF16(IDS_INSTANT_CHECKBOX_ENABLED); | 468 return l10n_util::GetStringUTF16(IDS_INSTANT_CHECKBOX_ENABLED); |
| 480 } | 469 } |
| 481 | 470 |
| 482 GURL GetInstantURL(Profile* profile, int start_margin) { | 471 GURL GetInstantURL(Profile* profile, int start_margin) { |
| 483 if (!IsInstantCheckboxEnabled(profile)) | 472 if (!IsInstantCheckboxEnabled(profile)) |
| 484 return GURL(); | 473 return GURL(); |
| 485 | 474 |
| 475 // In non-extended mode, the checkbox must be checked. | |
|
Jered
2013/06/25 16:30:39
There is no checkbox. Can you update this comment
Peter Kasting
2013/06/25 23:06:36
No. There are a variety of functions throughout t
| |
| 486 const bool extended_api_enabled = IsInstantExtendedAPIEnabled(); | 476 const bool extended_api_enabled = IsInstantExtendedAPIEnabled(); |
| 487 | |
| 488 // In non-extended mode, the checkbox must be checked. | |
| 489 if (!extended_api_enabled && !IsInstantCheckboxChecked(profile)) | 477 if (!extended_api_enabled && !IsInstantCheckboxChecked(profile)) |
| 490 return GURL(); | 478 return GURL(); |
| 491 | 479 |
| 492 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); | 480 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); |
| 493 CommandLine* cl = CommandLine::ForCurrentProcess(); | 481 GURL instant_url = |
| 494 if (cl->HasSwitch(switches::kInstantURL)) { | 482 TemplateURLRefToGURL(template_url->instant_url_ref(), start_margin); |
| 495 GURL instant_url(cl->GetSwitchValueASCII(switches::kInstantURL)); | 483 |
| 496 if (extended_api_enabled) { | 484 GURL::Replacements replacements; |
| 497 // Extended mode won't work if the search terms replacement key is absent. | 485 |
| 498 GURL coerced_url = CoerceCommandLineURLToTemplateURL( | 486 // Extended mode requires HTTPS. Force it unless the base URL was overridden |
| 499 instant_url, template_url->instant_url_ref(), start_margin); | 487 // on the command line, in which case we allow HTTP (see comments on |
| 500 if (!template_url->HasSearchTermsReplacementKey(coerced_url)) | 488 // IsSuitableURLForInstant()). |
| 501 return GURL(); | 489 const std::string secure_scheme(chrome::kHttpsScheme); |
| 502 } | 490 if (extended_api_enabled && !instant_url.SchemeIsSecure() && |
| 503 return instant_url; | 491 !StartsWithCommandLineGoogleBaseURL(instant_url)) |
| 492 replacements.SetSchemeStr(secure_scheme); | |
| 493 | |
| 494 // If the user specified additional query params on the command line, add | |
| 495 // them. | |
| 496 std::string query_params(CommandLine::ForCurrentProcess()-> | |
| 497 GetSwitchValueASCII(switches::kExtraSearchQueryParams)); | |
|
Jered
2013/06/25 16:30:39
Indent two more spaces.
Peter Kasting
2013/06/25 23:06:36
Done.
| |
| 498 if (!query_params.empty()) { | |
| 499 const std::string existing_query_params(instant_url.query()); | |
| 500 if (!existing_query_params.empty()) | |
| 501 query_params += "&" + existing_query_params; | |
| 502 replacements.SetQueryStr(query_params); | |
|
Jered
2013/06/25 16:30:39
Developers might find it confusing that --extra-se
Peter Kasting
2013/06/25 23:06:36
I haven't yet made it apply to the search URL, but
| |
| 504 } | 503 } |
| 505 | 504 |
| 506 GURL instant_url = | 505 return instant_url.ReplaceComponents(replacements); |
| 507 TemplateURLRefToGURL(template_url->instant_url_ref(), start_margin); | |
| 508 if (extended_api_enabled && !instant_url.SchemeIsSecure()) { | |
| 509 // Extended mode requires HTTPS. Force it if necessary. | |
| 510 const std::string secure_scheme = chrome::kHttpsScheme; | |
| 511 GURL::Replacements replacements; | |
| 512 replacements.SetSchemeStr(secure_scheme); | |
| 513 instant_url = instant_url.ReplaceComponents(replacements); | |
| 514 } | |
| 515 | |
| 516 return instant_url; | |
| 517 } | 506 } |
| 518 | 507 |
| 519 GURL GetLocalInstantURL(Profile* profile) { | 508 GURL GetLocalInstantURL(Profile* profile) { |
| 520 const TemplateURL* default_provider = | 509 const TemplateURL* default_provider = |
| 521 GetDefaultSearchProviderTemplateURL(profile); | 510 GetDefaultSearchProviderTemplateURL(profile); |
| 522 | 511 |
| 523 if (default_provider && | 512 if (default_provider && |
| 524 (TemplateURLPrepopulateData::GetEngineType(default_provider->url()) == | 513 (TemplateURLPrepopulateData::GetEngineType(default_provider->url()) == |
|
samarth
2013/06/21 23:57:25
It's not terribly important, but this check is fai
Peter Kasting
2013/06/25 23:06:36
Fixed, by fixing some of the lower-level functions
| |
| 525 SEARCH_ENGINE_GOOGLE)) { | 514 SEARCH_ENGINE_GOOGLE)) { |
| 526 return GURL(chrome::kChromeSearchLocalGoogleNtpUrl); | 515 return GURL(chrome::kChromeSearchLocalGoogleNtpUrl); |
| 527 } | 516 } |
| 528 return GURL(chrome::kChromeSearchLocalNtpUrl); | 517 return GURL(chrome::kChromeSearchLocalNtpUrl); |
| 529 } | 518 } |
| 530 | 519 |
| 531 bool IsInstantEnabled(Profile* profile) { | 520 bool IsInstantEnabled(Profile* profile) { |
| 532 return GetInstantURL(profile, kDisableStartMargin).is_valid(); | 521 return GetInstantURL(profile, kDisableStartMargin).is_valid(); |
| 533 } | 522 } |
| 534 | 523 |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 700 } | 689 } |
| 701 | 690 |
| 702 // Given a FieldTrialFlags object, returns the boolean value of the provided | 691 // Given a FieldTrialFlags object, returns the boolean value of the provided |
| 703 // flag. | 692 // flag. |
| 704 bool GetBoolValueForFlagWithDefault(const std::string& flag, | 693 bool GetBoolValueForFlagWithDefault(const std::string& flag, |
| 705 bool default_value, | 694 bool default_value, |
| 706 const FieldTrialFlags& flags) { | 695 const FieldTrialFlags& flags) { |
| 707 return !!GetUInt64ValueForFlagWithDefault(flag, default_value ? 1 : 0, flags); | 696 return !!GetUInt64ValueForFlagWithDefault(flag, default_value ? 1 : 0, flags); |
| 708 } | 697 } |
| 709 | 698 |
| 710 // Coerces the commandline Instant URL to look like a template URL, so that we | |
| 711 // can extract search terms from it. | |
| 712 GURL CoerceCommandLineURLToTemplateURL(const GURL& instant_url, | |
| 713 const TemplateURLRef& ref, | |
| 714 int start_margin) { | |
| 715 GURL search_url = TemplateURLRefToGURL(ref, start_margin); | |
| 716 | |
| 717 // NOTE(samarth): GURL returns temporaries which we must save because | |
| 718 // GURL::Replacements expects the replacements to live until | |
| 719 // ReplaceComponents is called. | |
| 720 const std::string search_scheme = chrome::kHttpsScheme; | |
| 721 const std::string search_host = search_url.host(); | |
| 722 const std::string search_port = search_url.port(); | |
| 723 | |
| 724 GURL::Replacements replacements; | |
| 725 replacements.SetSchemeStr(search_scheme); | |
| 726 replacements.SetHostStr(search_host); | |
| 727 replacements.SetPortStr(search_port); | |
| 728 return instant_url.ReplaceComponents(replacements); | |
| 729 } | |
| 730 | |
| 731 bool DefaultSearchProviderSupportsInstant(Profile* profile) { | 699 bool DefaultSearchProviderSupportsInstant(Profile* profile) { |
| 732 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); | 700 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); |
| 733 if (!template_url) | 701 if (!template_url) |
| 734 return false; | 702 return false; |
| 735 | 703 |
| 736 GURL instant_url = TemplateURLRefToGURL(template_url->instant_url_ref(), | 704 GURL instant_url = TemplateURLRefToGURL(template_url->instant_url_ref(), |
| 737 kDisableStartMargin); | 705 kDisableStartMargin); |
| 738 // Extended mode instant requires a search terms replacement key. | 706 // Extended mode instant requires a search terms replacement key. |
| 739 return instant_url.is_valid() && | 707 return instant_url.is_valid() && |
| 740 (!IsInstantExtendedAPIEnabled() || | 708 (!IsInstantExtendedAPIEnabled() || |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 754 for (size_t i = 0; i < items_b.size(); ++i) { | 722 for (size_t i = 0; i < items_b.size(); ++i) { |
| 755 if (items_b[i].url != items_a[i].url || | 723 if (items_b[i].url != items_a[i].url || |
| 756 items_b[i].title != items_a[i].title) { | 724 items_b[i].title != items_a[i].title) { |
| 757 return false; | 725 return false; |
| 758 } | 726 } |
| 759 } | 727 } |
| 760 return true; | 728 return true; |
| 761 } | 729 } |
| 762 | 730 |
| 763 } // namespace chrome | 731 } // namespace chrome |
| OLD | NEW |