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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/search/search.h" 6 7 #include "base/command_line.h" 8 #include "base/metrics/field_trial.h" 9 #include "base/metrics/histogram.h" 10 #include "base/prefs/pref_service.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_split.h" 13 #include "base/strings/utf_string_conversions.h" 14 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile_manager.h" 17 #include "chrome/browser/search/instant_service.h" 18 #include "chrome/browser/search/instant_service_factory.h" 19 #include "chrome/browser/search_engines/template_url_service_factory.h" 20 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h" 21 #include "chrome/browser/ui/browser.h" 22 #include "chrome/browser/ui/browser_instant_controller.h" 23 #include "chrome/browser/ui/browser_iterator.h" 24 #include "chrome/browser/ui/search/instant_search_prerenderer.h" 25 #include "chrome/common/chrome_switches.h" 26 #include "chrome/common/pref_names.h" 27 #include "chrome/common/search_urls.h" 28 #include "chrome/common/url_constants.h" 29 #include "components/google/core/browser/google_util.h" 30 #include "components/pref_registry/pref_registry_syncable.h" 31 #include "components/search/search.h" 32 #include "components/search_engines/template_url_service.h" 33 #include "components/sessions/serialized_navigation_entry.h" 34 #include "content/public/browser/navigation_entry.h" 35 #include "content/public/browser/render_process_host.h" 36 #include "content/public/browser/web_contents.h" 37 38 #if defined(ENABLE_MANAGED_USERS) 39 #include "chrome/browser/supervised_user/supervised_user_service.h" 40 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" 41 #include "chrome/browser/supervised_user/supervised_user_url_filter.h" 42 #endif 43 44 namespace chrome { 45 46 namespace { 47 48 const char kPrefetchSearchResultsOnSRP[] = "prefetch_results_srp"; 49 const char kAllowPrefetchNonDefaultMatch[] = "allow_prefetch_non_default_match"; 50 const char kPrerenderInstantUrlOnOmniboxFocus[] = 51 "prerender_instant_url_on_omnibox_focus"; 52 53 #if defined(OS_ANDROID) 54 const char kPrefetchSearchResultsFlagName[] = "prefetch_results"; 55 56 // Controls whether to reuse prerendered Instant Search base page to commit any 57 // search query. 58 const char kReuseInstantSearchBasePage[] = "reuse_instant_search_base_page"; 59 #endif 60 61 // Controls whether to use the alternate Instant search base URL. This allows 62 // experimentation of Instant search. 63 const char kUseAltInstantURL[] = "use_alternate_instant_url"; 64 const char kUseSearchPathForInstant[] = "use_search_path_for_instant"; 65 const char kAltInstantURLPath[] = "search"; 66 const char kAltInstantURLQueryParams[] = "&qbp=1"; 67 68 const char kDisplaySearchButtonFlagName[] = "display_search_button"; 69 const char kOriginChipFlagName[] = "origin_chip"; 70 #if !defined(OS_IOS) && !defined(OS_ANDROID) 71 const char kEnableQueryExtractionFlagName[] = "query_extraction"; 72 #endif 73 const char kShouldShowGoogleLocalNTPFlagName[] = "google_local_ntp"; 74 75 // Status of the New Tab URL for the default Search provider. NOTE: Used in a 76 // UMA histogram so values should only be added at the end and not reordered. 77 enum NewTabURLState { 78 // Valid URL that should be used. 79 NEW_TAB_URL_VALID = 0, 80 81 // Corrupt state (e.g. no profile or template url). 82 NEW_TAB_URL_BAD = 1, 83 84 // URL should not be used because in incognito window. 85 NEW_TAB_URL_INCOGNITO = 2, 86 87 // No New Tab URL set for provider. 88 NEW_TAB_URL_NOT_SET = 3, 89 90 // URL is not secure. 91 NEW_TAB_URL_INSECURE = 4, 92 93 // URL should not be used because Suggest is disabled. 94 // Not used anymore, see crbug.com/340424. 95 // NEW_TAB_URL_SUGGEST_OFF = 5, 96 97 // URL should not be used because it is blocked for a supervised user. 98 NEW_TAB_URL_BLOCKED = 6, 99 100 NEW_TAB_URL_MAX 101 }; 102 103 // Used to set the Instant support state of the Navigation entry. 104 const char kInstantSupportStateKey[] = "instant_support_state"; 105 106 const char kInstantSupportEnabled[] = "Instant support enabled"; 107 const char kInstantSupportDisabled[] = "Instant support disabled"; 108 const char kInstantSupportUnknown[] = "Instant support unknown"; 109 110 InstantSupportState StringToInstantSupportState(const base::string16& value) { 111 if (value == base::ASCIIToUTF16(kInstantSupportEnabled)) 112 return INSTANT_SUPPORT_YES; 113 else if (value == base::ASCIIToUTF16(kInstantSupportDisabled)) 114 return INSTANT_SUPPORT_NO; 115 else 116 return INSTANT_SUPPORT_UNKNOWN; 117 } 118 119 base::string16 InstantSupportStateToString(InstantSupportState state) { 120 switch (state) { 121 case INSTANT_SUPPORT_NO: 122 return base::ASCIIToUTF16(kInstantSupportDisabled); 123 case INSTANT_SUPPORT_YES: 124 return base::ASCIIToUTF16(kInstantSupportEnabled); 125 case INSTANT_SUPPORT_UNKNOWN: 126 return base::ASCIIToUTF16(kInstantSupportUnknown); 127 } 128 return base::ASCIIToUTF16(kInstantSupportUnknown); 129 } 130 131 TemplateURL* GetDefaultSearchProviderTemplateURL(Profile* profile) { 132 if (profile) { 133 TemplateURLService* template_url_service = 134 TemplateURLServiceFactory::GetForProfile(profile); 135 if (template_url_service) 136 return template_url_service->GetDefaultSearchProvider(); 137 } 138 return NULL; 139 } 140 141 GURL TemplateURLRefToGURL(const TemplateURLRef& ref, 142 const SearchTermsData& search_terms_data, 143 bool append_extra_query_params, 144 bool force_instant_results) { 145 TemplateURLRef::SearchTermsArgs search_terms_args = 146 TemplateURLRef::SearchTermsArgs(base::string16()); 147 search_terms_args.append_extra_query_params = append_extra_query_params; 148 search_terms_args.force_instant_results = force_instant_results; 149 return GURL(ref.ReplaceSearchTerms(search_terms_args, search_terms_data)); 150 } 151 152 bool MatchesAnySearchURL(const GURL& url, 153 TemplateURL* template_url, 154 const SearchTermsData& search_terms_data) { 155 GURL search_url = TemplateURLRefToGURL(template_url->url_ref(), 156 search_terms_data, false, false); 157 if (search_url.is_valid() && 158 search::MatchesOriginAndPath(url, search_url)) 159 return true; 160 161 // "URLCount() - 1" because we already tested url_ref above. 162 for (size_t i = 0; i < template_url->URLCount() - 1; ++i) { 163 TemplateURLRef ref(template_url, i); 164 search_url = TemplateURLRefToGURL(ref, search_terms_data, false, false); 165 if (search_url.is_valid() && 166 search::MatchesOriginAndPath(url, search_url)) 167 return true; 168 } 169 170 return false; 171 } 172 173 174 175 // |url| should either have a secure scheme or have a non-HTTPS base URL that 176 // the user specified using --google-base-url. (This allows testers to use 177 // --google-base-url to point at non-HTTPS servers, which eases testing.) 178 bool IsSuitableURLForInstant(const GURL& url, const TemplateURL* template_url) { 179 return template_url->HasSearchTermsReplacementKey(url) && 180 (url.SchemeIsSecure() || 181 google_util::StartsWithCommandLineGoogleBaseURL(url)); 182 } 183 184 // Returns true if |url| can be used as an Instant URL for |profile|. 185 bool IsInstantURL(const GURL& url, Profile* profile) { 186 if (!IsInstantExtendedAPIEnabled()) 187 return false; 188 189 if (!url.is_valid()) 190 return false; 191 192 const GURL new_tab_url(GetNewTabPageURL(profile)); 193 if (new_tab_url.is_valid() && 194 search::MatchesOriginAndPath(url, new_tab_url)) 195 return true; 196 197 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); 198 if (!template_url) 199 return false; 200 201 if (!IsSuitableURLForInstant(url, template_url)) 202 return false; 203 204 const TemplateURLRef& instant_url_ref = template_url->instant_url_ref(); 205 UIThreadSearchTermsData search_terms_data(profile); 206 const GURL instant_url = TemplateURLRefToGURL( 207 instant_url_ref, search_terms_data, false, false); 208 if (!instant_url.is_valid()) 209 return false; 210 211 if (search::MatchesOriginAndPath(url, instant_url)) 212 return true; 213 214 return IsQueryExtractionEnabled() && 215 MatchesAnySearchURL(url, template_url, search_terms_data); 216 } 217 218 base::string16 GetSearchTermsImpl(const content::WebContents* contents, 219 const content::NavigationEntry* entry) { 220 if (!contents || !IsQueryExtractionEnabled()) 221 return base::string16(); 222 223 // For security reasons, don't extract search terms if the page is not being 224 // rendered in the privileged Instant renderer process. This is to protect 225 // against a malicious page somehow scripting the search results page and 226 // faking search terms in the URL. Random pages can't get into the Instant 227 // renderer and scripting doesn't work cross-process, so if the page is in 228 // the Instant process, we know it isn't being exploited. 229 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 230 if (IsInstantExtendedAPIEnabled() && 231 !IsRenderedInInstantProcess(contents, profile) && 232 ((entry == contents->GetController().GetLastCommittedEntry()) || 233 !ShouldAssignURLToInstantRenderer(entry->GetURL(), profile))) 234 return base::string16(); 235 236 // Check to see if search terms have already been extracted. 237 base::string16 search_terms = GetSearchTermsFromNavigationEntry(entry); 238 if (!search_terms.empty()) 239 return search_terms; 240 241 if (!IsQueryExtractionAllowedForURL(profile, entry->GetVirtualURL())) 242 return base::string16(); 243 244 // Otherwise, extract from the URL. 245 return ExtractSearchTermsFromURL(profile, entry->GetVirtualURL()); 246 } 247 248 bool IsURLAllowedForSupervisedUser(const GURL& url, Profile* profile) { 249 #if defined(ENABLE_MANAGED_USERS) 250 SupervisedUserService* supervised_user_service = 251 SupervisedUserServiceFactory::GetForProfile(profile); 252 SupervisedUserURLFilter* url_filter = 253 supervised_user_service->GetURLFilterForUIThread(); 254 if (url_filter->GetFilteringBehaviorForURL(url) == 255 SupervisedUserURLFilter::BLOCK) { 256 return false; 257 } 258 #endif 259 return true; 260 } 261 262 // Returns whether |new_tab_url| can be used as a URL for the New Tab page. 263 // NEW_TAB_URL_VALID means a valid URL; other enum values imply an invalid URL. 264 NewTabURLState IsValidNewTabURL(Profile* profile, const GURL& new_tab_url) { 265 if (profile->IsOffTheRecord()) 266 return NEW_TAB_URL_INCOGNITO; 267 if (!new_tab_url.is_valid()) 268 return NEW_TAB_URL_NOT_SET; 269 if (!new_tab_url.SchemeIsSecure()) 270 return NEW_TAB_URL_INSECURE; 271 if (!IsURLAllowedForSupervisedUser(new_tab_url, profile)) 272 return NEW_TAB_URL_BLOCKED; 273 return NEW_TAB_URL_VALID; 274 } 275 276 // Used to look up the URL to use for the New Tab page. Also tracks how we 277 // arrived at that URL so it can be logged with UMA. 278 struct NewTabURLDetails { 279 NewTabURLDetails(const GURL& url, NewTabURLState state) 280 : url(url), state(state) {} 281 282 static NewTabURLDetails ForProfile(Profile* profile) { 283 const GURL local_url(chrome::kChromeSearchLocalNtpUrl); 284 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); 285 if (!profile || !template_url) 286 return NewTabURLDetails(local_url, NEW_TAB_URL_BAD); 287 288 GURL search_provider_url = TemplateURLRefToGURL( 289 template_url->new_tab_url_ref(), UIThreadSearchTermsData(profile), 290 false, false); 291 NewTabURLState state = IsValidNewTabURL(profile, search_provider_url); 292 switch (state) { 293 case NEW_TAB_URL_VALID: 294 // We can use the search provider's page. 295 return NewTabURLDetails(search_provider_url, state); 296 case NEW_TAB_URL_INCOGNITO: 297 // Incognito has its own New Tab. 298 return NewTabURLDetails(GURL(), state); 299 default: 300 // Use the local New Tab otherwise. 301 return NewTabURLDetails(local_url, state); 302 } 303 } 304 305 GURL url; 306 NewTabURLState state; 307 }; 308 309 } // namespace 310 311 // Negative start-margin values prevent the "es_sm" parameter from being used. 312 const int kDisableStartMargin = -1; 313 314 std::string InstantExtendedEnabledParam(bool for_search) { 315 if (for_search && !chrome::IsQueryExtractionEnabled()) 316 return std::string(); 317 return std::string(google_util::kInstantExtendedAPIParam) + "=" + 318 base::Uint64ToString(EmbeddedSearchPageVersion()) + "&"; 319 } 320 321 std::string ForceInstantResultsParam(bool for_prerender) { 322 return (for_prerender || !IsInstantExtendedAPIEnabled()) ? 323 "ion=1&" : std::string(); 324 } 325 326 bool IsQueryExtractionEnabled() { 327 #if defined(OS_IOS) || defined(OS_ANDROID) 328 return true; 329 #else 330 if (!IsInstantExtendedAPIEnabled()) 331 return false; 332 333 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 334 if (command_line->HasSwitch(switches::kEnableQueryExtraction)) 335 return true; 336 337 FieldTrialFlags flags; 338 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault( 339 kEnableQueryExtractionFlagName, false, flags); 340 #endif // defined(OS_IOS) || defined(OS_ANDROID) 341 } 342 343 base::string16 ExtractSearchTermsFromURL(Profile* profile, const GURL& url) { 344 if (url.is_valid() && url == GetSearchResultPrefetchBaseURL(profile)) { 345 // InstantSearchPrerenderer has the search query for the Instant search base 346 // page. 347 InstantSearchPrerenderer* prerenderer = 348 InstantSearchPrerenderer::GetForProfile(profile); 349 // TODO(kmadhusu): Remove this CHECK after the investigation of 350 // crbug.com/367204. 351 CHECK(prerenderer); 352 return prerenderer->get_last_query(); 353 } 354 355 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); 356 base::string16 search_terms; 357 if (template_url) 358 template_url->ExtractSearchTermsFromURL( 359 url, UIThreadSearchTermsData(profile), &search_terms); 360 return search_terms; 361 } 362 363 bool IsQueryExtractionAllowedForURL(Profile* profile, const GURL& url) { 364 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); 365 return template_url && IsSuitableURLForInstant(url, template_url); 366 } 367 368 base::string16 GetSearchTermsFromNavigationEntry( 369 const content::NavigationEntry* entry) { 370 base::string16 search_terms; 371 if (entry) 372 entry->GetExtraData(sessions::kSearchTermsKey, &search_terms); 373 return search_terms; 374 } 375 376 base::string16 GetSearchTerms(const content::WebContents* contents) { 377 if (!contents) 378 return base::string16(); 379 380 const content::NavigationEntry* entry = 381 contents->GetController().GetVisibleEntry(); 382 if (!entry) 383 return base::string16(); 384 385 if (IsInstantExtendedAPIEnabled()) { 386 InstantSupportState state = 387 GetInstantSupportStateFromNavigationEntry(*entry); 388 if (state == INSTANT_SUPPORT_NO) 389 return base::string16(); 390 } 391 392 return GetSearchTermsImpl(contents, entry); 393 } 394 395 bool ShouldAssignURLToInstantRenderer(const GURL& url, Profile* profile) { 396 return url.is_valid() && 397 profile && 398 IsInstantExtendedAPIEnabled() && 399 (url.SchemeIs(chrome::kChromeSearchScheme) || 400 IsInstantURL(url, profile)); 401 } 402 403 bool IsRenderedInInstantProcess(const content::WebContents* contents, 404 Profile* profile) { 405 const content::RenderProcessHost* process_host = 406 contents->GetRenderProcessHost(); 407 if (!process_host) 408 return false; 409 410 const InstantService* instant_service = 411 InstantServiceFactory::GetForProfile(profile); 412 if (!instant_service) 413 return false; 414 415 return instant_service->IsInstantProcess(process_host->GetID()); 416 } 417 418 bool ShouldUseProcessPerSiteForInstantURL(const GURL& url, Profile* profile) { 419 return ShouldAssignURLToInstantRenderer(url, profile) && 420 (url.host() == chrome::kChromeSearchLocalNtpHost || 421 url.host() == chrome::kChromeSearchRemoteNtpHost); 422 } 423 424 bool IsNTPURL(const GURL& url, Profile* profile) { 425 if (!url.is_valid()) 426 return false; 427 428 if (!IsInstantExtendedAPIEnabled()) 429 return url == GURL(chrome::kChromeUINewTabURL); 430 431 const base::string16 search_terms = ExtractSearchTermsFromURL(profile, url); 432 return profile && 433 ((IsInstantURL(url, profile) && search_terms.empty()) || 434 url == GURL(chrome::kChromeSearchLocalNtpUrl)); 435 } 436 437 bool IsInstantNTP(const content::WebContents* contents) { 438 if (!contents) 439 return false; 440 441 return NavEntryIsInstantNTP(contents, 442 contents->GetController().GetVisibleEntry()); 443 } 444 445 bool NavEntryIsInstantNTP(const content::WebContents* contents, 446 const content::NavigationEntry* entry) { 447 if (!contents || !entry || !IsInstantExtendedAPIEnabled()) 448 return false; 449 450 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 451 if (!IsRenderedInInstantProcess(contents, profile)) 452 return false; 453 454 if (entry->GetURL() == GetLocalInstantURL(profile)) 455 return true; 456 457 GURL new_tab_url(GetNewTabPageURL(profile)); 458 return new_tab_url.is_valid() && 459 search::MatchesOriginAndPath(entry->GetURL(), new_tab_url); 460 } 461 462 bool IsSuggestPrefEnabled(Profile* profile) { 463 return profile && !profile->IsOffTheRecord() && profile->GetPrefs() && 464 profile->GetPrefs()->GetBoolean(prefs::kSearchSuggestEnabled); 465 } 466 467 GURL GetInstantURL(Profile* profile, bool force_instant_results) { 468 if (!IsInstantExtendedAPIEnabled() || !IsSuggestPrefEnabled(profile)) 469 return GURL(); 470 471 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); 472 if (!template_url) 473 return GURL(); 474 475 GURL instant_url = TemplateURLRefToGURL( 476 template_url->instant_url_ref(), UIThreadSearchTermsData(profile), 477 true, force_instant_results); 478 if (!instant_url.is_valid() || 479 !template_url->HasSearchTermsReplacementKey(instant_url)) 480 return GURL(); 481 482 // Extended mode requires HTTPS. Force it unless the base URL was overridden 483 // on the command line, in which case we allow HTTP (see comments on 484 // IsSuitableURLForInstant()). 485 if (!instant_url.SchemeIsSecure() && 486 !google_util::StartsWithCommandLineGoogleBaseURL(instant_url)) { 487 GURL::Replacements replacements; 488 const std::string secure_scheme(url::kHttpsScheme); 489 replacements.SetSchemeStr(secure_scheme); 490 instant_url = instant_url.ReplaceComponents(replacements); 491 } 492 493 if (!IsURLAllowedForSupervisedUser(instant_url, profile)) 494 return GURL(); 495 496 if (ShouldUseAltInstantURL()) { 497 GURL::Replacements replacements; 498 const std::string path( 499 ShouldUseSearchPathForInstant() ? kAltInstantURLPath : std::string()); 500 if (!path.empty()) 501 replacements.SetPathStr(path); 502 const std::string query( 503 instant_url.query() + std::string(kAltInstantURLQueryParams)); 504 replacements.SetQueryStr(query); 505 instant_url = instant_url.ReplaceComponents(replacements); 506 } 507 return instant_url; 508 } 509 510 // Returns URLs associated with the default search engine for |profile|. 511 std::vector<GURL> GetSearchURLs(Profile* profile) { 512 std::vector<GURL> result; 513 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile); 514 if (!template_url) 515 return result; 516 for (size_t i = 0; i < template_url->URLCount(); ++i) { 517 TemplateURLRef ref(template_url, i); 518 result.push_back(TemplateURLRefToGURL(ref, UIThreadSearchTermsData(profile), 519 false, false)); 520 } 521 return result; 522 } 523 524 GURL GetNewTabPageURL(Profile* profile) { 525 return NewTabURLDetails::ForProfile(profile).url; 526 } 527 528 GURL GetSearchResultPrefetchBaseURL(Profile* profile) { 529 return ShouldPrefetchSearchResults() ? GetInstantURL(profile, true) : GURL(); 530 } 531 532 bool ShouldPrefetchSearchResults() { 533 if (!IsInstantExtendedAPIEnabled()) 534 return false; 535 536 #if defined(OS_ANDROID) 537 if (CommandLine::ForCurrentProcess()->HasSwitch( 538 switches::kPrefetchSearchResults)) { 539 return true; 540 } 541 542 FieldTrialFlags flags; 543 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault( 544 kPrefetchSearchResultsFlagName, false, flags); 545 #else 546 return true; 547 #endif 548 } 549 550 bool ShouldAllowPrefetchNonDefaultMatch() { 551 if (!ShouldPrefetchSearchResults()) 552 return false; 553 554 FieldTrialFlags flags; 555 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault( 556 kAllowPrefetchNonDefaultMatch, false, flags); 557 } 558 559 bool ShouldPrerenderInstantUrlOnOmniboxFocus() { 560 if (!ShouldPrefetchSearchResults()) 561 return false; 562 563 FieldTrialFlags flags; 564 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault( 565 kPrerenderInstantUrlOnOmniboxFocus, false, flags); 566 } 567 568 bool ShouldReuseInstantSearchBasePage() { 569 if (!ShouldPrefetchSearchResults()) 570 return false; 571 572 #if defined(OS_ANDROID) 573 FieldTrialFlags flags; 574 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault( 575 kReuseInstantSearchBasePage, false, flags); 576 #else 577 return true; 578 #endif 579 } 580 581 GURL GetLocalInstantURL(Profile* profile) { 582 return GURL(chrome::kChromeSearchLocalNtpUrl); 583 } 584 585 DisplaySearchButtonConditions GetDisplaySearchButtonConditions() { 586 const CommandLine* cl = CommandLine::ForCurrentProcess(); 587 if (cl->HasSwitch(switches::kDisableSearchButtonInOmnibox)) 588 return DISPLAY_SEARCH_BUTTON_NEVER; 589 if (cl->HasSwitch(switches::kEnableSearchButtonInOmniboxForStr)) 590 return DISPLAY_SEARCH_BUTTON_FOR_STR; 591 if (cl->HasSwitch(switches::kEnableSearchButtonInOmniboxForStrOrIip)) 592 return DISPLAY_SEARCH_BUTTON_FOR_STR_OR_IIP; 593 if (cl->HasSwitch(switches::kEnableSearchButtonInOmniboxAlways)) 594 return DISPLAY_SEARCH_BUTTON_ALWAYS; 595 596 FieldTrialFlags flags; 597 if (!GetFieldTrialInfo(&flags)) 598 return DISPLAY_SEARCH_BUTTON_NEVER; 599 uint64 value = 600 GetUInt64ValueForFlagWithDefault(kDisplaySearchButtonFlagName, 0, flags); 601 return (value < DISPLAY_SEARCH_BUTTON_NUM_VALUES) ? 602 static_cast<DisplaySearchButtonConditions>(value) : 603 DISPLAY_SEARCH_BUTTON_NEVER; 604 } 605 606 bool ShouldDisplayOriginChip() { 607 return GetOriginChipCondition() != ORIGIN_CHIP_DISABLED; 608 } 609 610 OriginChipCondition GetOriginChipCondition() { 611 const CommandLine* cl = CommandLine::ForCurrentProcess(); 612 if (cl->HasSwitch(switches::kDisableOriginChip)) 613 return ORIGIN_CHIP_DISABLED; 614 if (cl->HasSwitch(switches::kEnableOriginChipAlways)) 615 return ORIGIN_CHIP_ALWAYS; 616 if (cl->HasSwitch(switches::kEnableOriginChipOnSrp)) 617 return ORIGIN_CHIP_ON_SRP; 618 619 FieldTrialFlags flags; 620 if (!GetFieldTrialInfo(&flags)) 621 return ORIGIN_CHIP_DISABLED; 622 uint64 value = 623 GetUInt64ValueForFlagWithDefault(kOriginChipFlagName, 0, flags); 624 return (value < ORIGIN_CHIP_NUM_VALUES) ? 625 static_cast<OriginChipCondition>(value) : ORIGIN_CHIP_DISABLED; 626 } 627 628 bool ShouldShowGoogleLocalNTP() { 629 FieldTrialFlags flags; 630 return !GetFieldTrialInfo(&flags) || GetBoolValueForFlagWithDefault( 631 kShouldShowGoogleLocalNTPFlagName, true, flags); 632 } 633 634 GURL GetEffectiveURLForInstant(const GURL& url, Profile* profile) { 635 CHECK(ShouldAssignURLToInstantRenderer(url, profile)) 636 << "Error granting Instant access."; 637 638 if (url.SchemeIs(chrome::kChromeSearchScheme)) 639 return url; 640 641 GURL effective_url(url); 642 643 // Replace the scheme with "chrome-search:". 644 url::Replacements<char> replacements; 645 std::string search_scheme(chrome::kChromeSearchScheme); 646 replacements.SetScheme(search_scheme.data(), 647 url::Component(0, search_scheme.length())); 648 649 // If this is the URL for a server-provided NTP, replace the host with 650 // "remote-ntp". 651 std::string remote_ntp_host(chrome::kChromeSearchRemoteNtpHost); 652 NewTabURLDetails details = NewTabURLDetails::ForProfile(profile); 653 if (details.state == NEW_TAB_URL_VALID && 654 search::MatchesOriginAndPath(url, details.url)) { 655 replacements.SetHost(remote_ntp_host.c_str(), 656 url::Component(0, remote_ntp_host.length())); 657 } 658 659 effective_url = effective_url.ReplaceComponents(replacements); 660 return effective_url; 661 } 662 663 bool HandleNewTabURLRewrite(GURL* url, 664 content::BrowserContext* browser_context) { 665 if (!IsInstantExtendedAPIEnabled()) 666 return false; 667 668 if (!url->SchemeIs(content::kChromeUIScheme) || 669 url->host() != chrome::kChromeUINewTabHost) 670 return false; 671 672 Profile* profile = Profile::FromBrowserContext(browser_context); 673 NewTabURLDetails details(NewTabURLDetails::ForProfile(profile)); 674 UMA_HISTOGRAM_ENUMERATION("NewTabPage.URLState", 675 details.state, NEW_TAB_URL_MAX); 676 if (details.url.is_valid()) { 677 *url = details.url; 678 return true; 679 } 680 return false; 681 } 682 683 bool HandleNewTabURLReverseRewrite(GURL* url, 684 content::BrowserContext* browser_context) { 685 if (!IsInstantExtendedAPIEnabled()) 686 return false; 687 688 // Do nothing in incognito. 689 Profile* profile = Profile::FromBrowserContext(browser_context); 690 if (profile && profile->IsOffTheRecord()) 691 return false; 692 693 if (search::MatchesOriginAndPath( 694 GURL(chrome::kChromeSearchLocalNtpUrl), *url)) { 695 *url = GURL(chrome::kChromeUINewTabURL); 696 return true; 697 } 698 699 GURL new_tab_url(GetNewTabPageURL(profile)); 700 if (new_tab_url.is_valid() && 701 search::MatchesOriginAndPath(new_tab_url, *url)) { 702 *url = GURL(chrome::kChromeUINewTabURL); 703 return true; 704 } 705 706 return false; 707 } 708 709 void SetInstantSupportStateInNavigationEntry(InstantSupportState state, 710 content::NavigationEntry* entry) { 711 if (!entry) 712 return; 713 714 entry->SetExtraData(kInstantSupportStateKey, 715 InstantSupportStateToString(state)); 716 } 717 718 InstantSupportState GetInstantSupportStateFromNavigationEntry( 719 const content::NavigationEntry& entry) { 720 base::string16 value; 721 if (!entry.GetExtraData(kInstantSupportStateKey, &value)) 722 return INSTANT_SUPPORT_UNKNOWN; 723 724 return StringToInstantSupportState(value); 725 } 726 727 bool ShouldPrefetchSearchResultsOnSRP() { 728 FieldTrialFlags flags; 729 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault( 730 kPrefetchSearchResultsOnSRP, false, flags); 731 } 732 733 void EnableQueryExtractionForTesting() { 734 CommandLine* cl = CommandLine::ForCurrentProcess(); 735 cl->AppendSwitch(switches::kEnableQueryExtraction); 736 } 737 738 bool ShouldUseAltInstantURL() { 739 FieldTrialFlags flags; 740 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault( 741 kUseAltInstantURL, false, flags); 742 } 743 744 bool ShouldUseSearchPathForInstant() { 745 FieldTrialFlags flags; 746 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault( 747 kUseSearchPathForInstant, false, flags); 748 } 749 750 } // namespace chrome 751