Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / search / search.cc
blob21254bc815755e6b70ffd08d310837f4f235212a
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.
5 #include "chrome/browser/search/search.h"
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"
38 #if defined(ENABLE_SUPERVISED_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
44 namespace chrome {
46 namespace {
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";
53 #if defined(OS_ANDROID)
54 const char kPrefetchSearchResultsFlagName[] = "prefetch_results";
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
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";
68 #if !defined(OS_IOS) && !defined(OS_ANDROID)
69 const char kEnableQueryExtractionFlagName[] = "query_extraction";
70 #endif
71 const char kShouldShowGoogleLocalNTPFlagName[] = "google_local_ntp";
73 // Status of the New Tab URL for the default Search provider. NOTE: Used in a
74 // UMA histogram so values should only be added at the end and not reordered.
75 enum NewTabURLState {
76 // Valid URL that should be used.
77 NEW_TAB_URL_VALID = 0,
79 // Corrupt state (e.g. no profile or template url).
80 NEW_TAB_URL_BAD = 1,
82 // URL should not be used because in incognito window.
83 NEW_TAB_URL_INCOGNITO = 2,
85 // No New Tab URL set for provider.
86 NEW_TAB_URL_NOT_SET = 3,
88 // URL is not secure.
89 NEW_TAB_URL_INSECURE = 4,
91 // URL should not be used because Suggest is disabled.
92 // Not used anymore, see crbug.com/340424.
93 // NEW_TAB_URL_SUGGEST_OFF = 5,
95 // URL should not be used because it is blocked for a supervised user.
96 NEW_TAB_URL_BLOCKED = 6,
98 NEW_TAB_URL_MAX
101 // Used to set the Instant support state of the Navigation entry.
102 const char kInstantSupportStateKey[] = "instant_support_state";
104 const char kInstantSupportEnabled[] = "Instant support enabled";
105 const char kInstantSupportDisabled[] = "Instant support disabled";
106 const char kInstantSupportUnknown[] = "Instant support unknown";
108 InstantSupportState StringToInstantSupportState(const base::string16& value) {
109 if (value == base::ASCIIToUTF16(kInstantSupportEnabled))
110 return INSTANT_SUPPORT_YES;
111 else if (value == base::ASCIIToUTF16(kInstantSupportDisabled))
112 return INSTANT_SUPPORT_NO;
113 else
114 return INSTANT_SUPPORT_UNKNOWN;
117 base::string16 InstantSupportStateToString(InstantSupportState state) {
118 switch (state) {
119 case INSTANT_SUPPORT_NO:
120 return base::ASCIIToUTF16(kInstantSupportDisabled);
121 case INSTANT_SUPPORT_YES:
122 return base::ASCIIToUTF16(kInstantSupportEnabled);
123 case INSTANT_SUPPORT_UNKNOWN:
124 return base::ASCIIToUTF16(kInstantSupportUnknown);
126 return base::ASCIIToUTF16(kInstantSupportUnknown);
129 TemplateURL* GetDefaultSearchProviderTemplateURL(Profile* profile) {
130 if (profile) {
131 TemplateURLService* template_url_service =
132 TemplateURLServiceFactory::GetForProfile(profile);
133 if (template_url_service)
134 return template_url_service->GetDefaultSearchProvider();
136 return NULL;
139 GURL TemplateURLRefToGURL(const TemplateURLRef& ref,
140 const SearchTermsData& search_terms_data,
141 bool append_extra_query_params,
142 bool force_instant_results) {
143 TemplateURLRef::SearchTermsArgs search_terms_args =
144 TemplateURLRef::SearchTermsArgs(base::string16());
145 search_terms_args.append_extra_query_params = append_extra_query_params;
146 search_terms_args.force_instant_results = force_instant_results;
147 return GURL(ref.ReplaceSearchTerms(search_terms_args, search_terms_data));
150 bool MatchesAnySearchURL(const GURL& url,
151 TemplateURL* template_url,
152 const SearchTermsData& search_terms_data) {
153 GURL search_url = TemplateURLRefToGURL(template_url->url_ref(),
154 search_terms_data, false, false);
155 if (search_url.is_valid() &&
156 search::MatchesOriginAndPath(url, search_url))
157 return true;
159 // "URLCount() - 1" because we already tested url_ref above.
160 for (size_t i = 0; i < template_url->URLCount() - 1; ++i) {
161 TemplateURLRef ref(template_url, i);
162 search_url = TemplateURLRefToGURL(ref, search_terms_data, false, false);
163 if (search_url.is_valid() &&
164 search::MatchesOriginAndPath(url, search_url))
165 return true;
168 return false;
173 // |url| should either have a secure scheme or have a non-HTTPS base URL that
174 // the user specified using --google-base-url. (This allows testers to use
175 // --google-base-url to point at non-HTTPS servers, which eases testing.)
176 bool IsSuitableURLForInstant(const GURL& url, const TemplateURL* template_url) {
177 return template_url->HasSearchTermsReplacementKey(url) &&
178 (url.SchemeIsSecure() ||
179 google_util::StartsWithCommandLineGoogleBaseURL(url));
182 // Returns true if |url| can be used as an Instant URL for |profile|.
183 bool IsInstantURL(const GURL& url, Profile* profile) {
184 if (!IsInstantExtendedAPIEnabled())
185 return false;
187 if (!url.is_valid())
188 return false;
190 const GURL new_tab_url(GetNewTabPageURL(profile));
191 if (new_tab_url.is_valid() &&
192 search::MatchesOriginAndPath(url, new_tab_url))
193 return true;
195 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
196 if (!template_url)
197 return false;
199 if (!IsSuitableURLForInstant(url, template_url))
200 return false;
202 const TemplateURLRef& instant_url_ref = template_url->instant_url_ref();
203 UIThreadSearchTermsData search_terms_data(profile);
204 const GURL instant_url = TemplateURLRefToGURL(
205 instant_url_ref, search_terms_data, false, false);
206 if (!instant_url.is_valid())
207 return false;
209 if (search::MatchesOriginAndPath(url, instant_url))
210 return true;
212 return IsQueryExtractionEnabled() &&
213 MatchesAnySearchURL(url, template_url, search_terms_data);
216 base::string16 GetSearchTermsImpl(const content::WebContents* contents,
217 const content::NavigationEntry* entry) {
218 if (!contents || !IsQueryExtractionEnabled())
219 return base::string16();
221 // For security reasons, don't extract search terms if the page is not being
222 // rendered in the privileged Instant renderer process. This is to protect
223 // against a malicious page somehow scripting the search results page and
224 // faking search terms in the URL. Random pages can't get into the Instant
225 // renderer and scripting doesn't work cross-process, so if the page is in
226 // the Instant process, we know it isn't being exploited.
227 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
228 if (IsInstantExtendedAPIEnabled() &&
229 !IsRenderedInInstantProcess(contents, profile) &&
230 ((entry == contents->GetController().GetLastCommittedEntry()) ||
231 !ShouldAssignURLToInstantRenderer(entry->GetURL(), profile)))
232 return base::string16();
234 // Check to see if search terms have already been extracted.
235 base::string16 search_terms = GetSearchTermsFromNavigationEntry(entry);
236 if (!search_terms.empty())
237 return search_terms;
239 if (!IsQueryExtractionAllowedForURL(profile, entry->GetVirtualURL()))
240 return base::string16();
242 // Otherwise, extract from the URL.
243 return ExtractSearchTermsFromURL(profile, entry->GetVirtualURL());
246 bool IsURLAllowedForSupervisedUser(const GURL& url, Profile* profile) {
247 #if defined(ENABLE_SUPERVISED_USERS)
248 SupervisedUserService* supervised_user_service =
249 SupervisedUserServiceFactory::GetForProfile(profile);
250 SupervisedUserURLFilter* url_filter =
251 supervised_user_service->GetURLFilterForUIThread();
252 if (url_filter->GetFilteringBehaviorForURL(url) ==
253 SupervisedUserURLFilter::BLOCK) {
254 return false;
256 #endif
257 return true;
260 // Returns whether |new_tab_url| can be used as a URL for the New Tab page.
261 // NEW_TAB_URL_VALID means a valid URL; other enum values imply an invalid URL.
262 NewTabURLState IsValidNewTabURL(Profile* profile, const GURL& new_tab_url) {
263 if (profile->IsOffTheRecord())
264 return NEW_TAB_URL_INCOGNITO;
265 if (!new_tab_url.is_valid())
266 return NEW_TAB_URL_NOT_SET;
267 if (!new_tab_url.SchemeIsSecure())
268 return NEW_TAB_URL_INSECURE;
269 if (!IsURLAllowedForSupervisedUser(new_tab_url, profile))
270 return NEW_TAB_URL_BLOCKED;
271 return NEW_TAB_URL_VALID;
274 // Used to look up the URL to use for the New Tab page. Also tracks how we
275 // arrived at that URL so it can be logged with UMA.
276 struct NewTabURLDetails {
277 NewTabURLDetails(const GURL& url, NewTabURLState state)
278 : url(url), state(state) {}
280 static NewTabURLDetails ForProfile(Profile* profile) {
281 const GURL local_url(chrome::kChromeSearchLocalNtpUrl);
282 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
283 if (!profile || !template_url)
284 return NewTabURLDetails(local_url, NEW_TAB_URL_BAD);
286 GURL search_provider_url = TemplateURLRefToGURL(
287 template_url->new_tab_url_ref(), UIThreadSearchTermsData(profile),
288 false, false);
289 NewTabURLState state = IsValidNewTabURL(profile, search_provider_url);
290 switch (state) {
291 case NEW_TAB_URL_VALID:
292 // We can use the search provider's page.
293 return NewTabURLDetails(search_provider_url, state);
294 case NEW_TAB_URL_INCOGNITO:
295 // Incognito has its own New Tab.
296 return NewTabURLDetails(GURL(), state);
297 default:
298 // Use the local New Tab otherwise.
299 return NewTabURLDetails(local_url, state);
303 GURL url;
304 NewTabURLState state;
307 } // namespace
309 // Negative start-margin values prevent the "es_sm" parameter from being used.
310 const int kDisableStartMargin = -1;
312 std::string InstantExtendedEnabledParam(bool for_search) {
313 if (for_search && !chrome::IsQueryExtractionEnabled())
314 return std::string();
315 return std::string(google_util::kInstantExtendedAPIParam) + "=" +
316 base::Uint64ToString(EmbeddedSearchPageVersion()) + "&";
319 std::string ForceInstantResultsParam(bool for_prerender) {
320 return (for_prerender || !IsInstantExtendedAPIEnabled()) ?
321 "ion=1&" : std::string();
324 bool IsQueryExtractionEnabled() {
325 #if defined(OS_IOS) || defined(OS_ANDROID)
326 return true;
327 #else
328 if (!IsInstantExtendedAPIEnabled())
329 return false;
331 const base::CommandLine* command_line =
332 base::CommandLine::ForCurrentProcess();
333 if (command_line->HasSwitch(switches::kEnableQueryExtraction))
334 return true;
336 FieldTrialFlags flags;
337 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
338 kEnableQueryExtractionFlagName, false, flags);
339 #endif // defined(OS_IOS) || defined(OS_ANDROID)
342 base::string16 ExtractSearchTermsFromURL(Profile* profile, const GURL& url) {
343 if (url.is_valid() && url == GetSearchResultPrefetchBaseURL(profile)) {
344 // InstantSearchPrerenderer has the search query for the Instant search base
345 // page.
346 InstantSearchPrerenderer* prerenderer =
347 InstantSearchPrerenderer::GetForProfile(profile);
348 // TODO(kmadhusu): Remove this CHECK after the investigation of
349 // crbug.com/367204.
350 CHECK(prerenderer);
351 return prerenderer->get_last_query();
354 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
355 base::string16 search_terms;
356 if (template_url)
357 template_url->ExtractSearchTermsFromURL(
358 url, UIThreadSearchTermsData(profile), &search_terms);
359 return search_terms;
362 bool IsQueryExtractionAllowedForURL(Profile* profile, const GURL& url) {
363 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
364 return template_url && IsSuitableURLForInstant(url, template_url);
367 base::string16 GetSearchTermsFromNavigationEntry(
368 const content::NavigationEntry* entry) {
369 base::string16 search_terms;
370 if (entry)
371 entry->GetExtraData(sessions::kSearchTermsKey, &search_terms);
372 return search_terms;
375 base::string16 GetSearchTerms(const content::WebContents* contents) {
376 if (!contents)
377 return base::string16();
379 const content::NavigationEntry* entry =
380 contents->GetController().GetVisibleEntry();
381 if (!entry)
382 return base::string16();
384 if (IsInstantExtendedAPIEnabled()) {
385 InstantSupportState state =
386 GetInstantSupportStateFromNavigationEntry(*entry);
387 if (state == INSTANT_SUPPORT_NO)
388 return base::string16();
391 return GetSearchTermsImpl(contents, entry);
394 bool ShouldAssignURLToInstantRenderer(const GURL& url, Profile* profile) {
395 return url.is_valid() &&
396 profile &&
397 IsInstantExtendedAPIEnabled() &&
398 (url.SchemeIs(chrome::kChromeSearchScheme) ||
399 IsInstantURL(url, profile));
402 bool IsRenderedInInstantProcess(const content::WebContents* contents,
403 Profile* profile) {
404 const content::RenderProcessHost* process_host =
405 contents->GetRenderProcessHost();
406 if (!process_host)
407 return false;
409 const InstantService* instant_service =
410 InstantServiceFactory::GetForProfile(profile);
411 if (!instant_service)
412 return false;
414 return instant_service->IsInstantProcess(process_host->GetID());
417 bool ShouldUseProcessPerSiteForInstantURL(const GURL& url, Profile* profile) {
418 return ShouldAssignURLToInstantRenderer(url, profile) &&
419 (url.host() == chrome::kChromeSearchLocalNtpHost ||
420 url.host() == chrome::kChromeSearchRemoteNtpHost);
423 bool IsNTPURL(const GURL& url, Profile* profile) {
424 if (!url.is_valid())
425 return false;
427 if (!IsInstantExtendedAPIEnabled())
428 return url == GURL(chrome::kChromeUINewTabURL);
430 const base::string16 search_terms = ExtractSearchTermsFromURL(profile, url);
431 return profile &&
432 ((IsInstantURL(url, profile) && search_terms.empty()) ||
433 url == GURL(chrome::kChromeSearchLocalNtpUrl));
436 bool IsInstantNTP(const content::WebContents* contents) {
437 if (!contents)
438 return false;
440 return NavEntryIsInstantNTP(contents,
441 contents->GetController().GetVisibleEntry());
444 bool NavEntryIsInstantNTP(const content::WebContents* contents,
445 const content::NavigationEntry* entry) {
446 if (!contents || !entry || !IsInstantExtendedAPIEnabled())
447 return false;
449 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
450 if (!IsRenderedInInstantProcess(contents, profile))
451 return false;
453 if (entry->GetURL() == GetLocalInstantURL(profile))
454 return true;
456 GURL new_tab_url(GetNewTabPageURL(profile));
457 return new_tab_url.is_valid() &&
458 search::MatchesOriginAndPath(entry->GetURL(), new_tab_url);
461 bool IsSuggestPrefEnabled(Profile* profile) {
462 return profile && !profile->IsOffTheRecord() && profile->GetPrefs() &&
463 profile->GetPrefs()->GetBoolean(prefs::kSearchSuggestEnabled);
466 GURL GetInstantURL(Profile* profile, bool force_instant_results) {
467 if (!IsInstantExtendedAPIEnabled() || !IsSuggestPrefEnabled(profile))
468 return GURL();
470 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
471 if (!template_url)
472 return GURL();
474 GURL instant_url = TemplateURLRefToGURL(
475 template_url->instant_url_ref(), UIThreadSearchTermsData(profile),
476 true, force_instant_results);
477 if (!instant_url.is_valid() ||
478 !template_url->HasSearchTermsReplacementKey(instant_url))
479 return GURL();
481 // Extended mode requires HTTPS. Force it unless the base URL was overridden
482 // on the command line, in which case we allow HTTP (see comments on
483 // IsSuitableURLForInstant()).
484 if (!instant_url.SchemeIsSecure() &&
485 !google_util::StartsWithCommandLineGoogleBaseURL(instant_url)) {
486 GURL::Replacements replacements;
487 replacements.SetSchemeStr(url::kHttpsScheme);
488 instant_url = instant_url.ReplaceComponents(replacements);
491 if (!IsURLAllowedForSupervisedUser(instant_url, profile))
492 return GURL();
494 if (ShouldUseAltInstantURL()) {
495 GURL::Replacements replacements;
496 const std::string path(
497 ShouldUseSearchPathForInstant() ? kAltInstantURLPath : std::string());
498 if (!path.empty())
499 replacements.SetPathStr(path);
500 const std::string query(
501 instant_url.query() + std::string(kAltInstantURLQueryParams));
502 replacements.SetQueryStr(query);
503 instant_url = instant_url.ReplaceComponents(replacements);
505 return instant_url;
508 // Returns URLs associated with the default search engine for |profile|.
509 std::vector<GURL> GetSearchURLs(Profile* profile) {
510 std::vector<GURL> result;
511 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
512 if (!template_url)
513 return result;
514 for (size_t i = 0; i < template_url->URLCount(); ++i) {
515 TemplateURLRef ref(template_url, i);
516 result.push_back(TemplateURLRefToGURL(ref, UIThreadSearchTermsData(profile),
517 false, false));
519 return result;
522 GURL GetNewTabPageURL(Profile* profile) {
523 return NewTabURLDetails::ForProfile(profile).url;
526 GURL GetSearchResultPrefetchBaseURL(Profile* profile) {
527 return ShouldPrefetchSearchResults() ? GetInstantURL(profile, true) : GURL();
530 bool ShouldPrefetchSearchResults() {
531 if (!IsInstantExtendedAPIEnabled())
532 return false;
534 #if defined(OS_ANDROID)
535 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
536 switches::kPrefetchSearchResults)) {
537 return true;
540 FieldTrialFlags flags;
541 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
542 kPrefetchSearchResultsFlagName, false, flags);
543 #else
544 return true;
545 #endif
548 bool ShouldAllowPrefetchNonDefaultMatch() {
549 if (!ShouldPrefetchSearchResults())
550 return false;
552 FieldTrialFlags flags;
553 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
554 kAllowPrefetchNonDefaultMatch, false, flags);
557 bool ShouldPrerenderInstantUrlOnOmniboxFocus() {
558 if (!ShouldPrefetchSearchResults())
559 return false;
561 FieldTrialFlags flags;
562 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
563 kPrerenderInstantUrlOnOmniboxFocus, false, flags);
566 bool ShouldReuseInstantSearchBasePage() {
567 if (!ShouldPrefetchSearchResults())
568 return false;
570 #if defined(OS_ANDROID)
571 FieldTrialFlags flags;
572 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
573 kReuseInstantSearchBasePage, false, flags);
574 #else
575 return true;
576 #endif
579 GURL GetLocalInstantURL(Profile* profile) {
580 return GURL(chrome::kChromeSearchLocalNtpUrl);
583 bool ShouldShowGoogleLocalNTP() {
584 FieldTrialFlags flags;
585 return !GetFieldTrialInfo(&flags) || GetBoolValueForFlagWithDefault(
586 kShouldShowGoogleLocalNTPFlagName, true, flags);
589 GURL GetEffectiveURLForInstant(const GURL& url, Profile* profile) {
590 CHECK(ShouldAssignURLToInstantRenderer(url, profile))
591 << "Error granting Instant access.";
593 if (url.SchemeIs(chrome::kChromeSearchScheme))
594 return url;
596 GURL effective_url(url);
598 // Replace the scheme with "chrome-search:".
599 url::Replacements<char> replacements;
600 std::string search_scheme(chrome::kChromeSearchScheme);
601 replacements.SetScheme(search_scheme.data(),
602 url::Component(0, search_scheme.length()));
604 // If this is the URL for a server-provided NTP, replace the host with
605 // "remote-ntp".
606 std::string remote_ntp_host(chrome::kChromeSearchRemoteNtpHost);
607 NewTabURLDetails details = NewTabURLDetails::ForProfile(profile);
608 if (details.state == NEW_TAB_URL_VALID &&
609 search::MatchesOriginAndPath(url, details.url)) {
610 replacements.SetHost(remote_ntp_host.c_str(),
611 url::Component(0, remote_ntp_host.length()));
614 effective_url = effective_url.ReplaceComponents(replacements);
615 return effective_url;
618 bool HandleNewTabURLRewrite(GURL* url,
619 content::BrowserContext* browser_context) {
620 if (!IsInstantExtendedAPIEnabled())
621 return false;
623 if (!url->SchemeIs(content::kChromeUIScheme) ||
624 url->host() != chrome::kChromeUINewTabHost)
625 return false;
627 Profile* profile = Profile::FromBrowserContext(browser_context);
628 NewTabURLDetails details(NewTabURLDetails::ForProfile(profile));
629 UMA_HISTOGRAM_ENUMERATION("NewTabPage.URLState",
630 details.state, NEW_TAB_URL_MAX);
631 if (details.url.is_valid()) {
632 *url = details.url;
633 return true;
635 return false;
638 bool HandleNewTabURLReverseRewrite(GURL* url,
639 content::BrowserContext* browser_context) {
640 if (!IsInstantExtendedAPIEnabled())
641 return false;
643 // Do nothing in incognito.
644 Profile* profile = Profile::FromBrowserContext(browser_context);
645 if (profile && profile->IsOffTheRecord())
646 return false;
648 if (search::MatchesOriginAndPath(
649 GURL(chrome::kChromeSearchLocalNtpUrl), *url)) {
650 *url = GURL(chrome::kChromeUINewTabURL);
651 return true;
654 GURL new_tab_url(GetNewTabPageURL(profile));
655 if (new_tab_url.is_valid() &&
656 search::MatchesOriginAndPath(new_tab_url, *url)) {
657 *url = GURL(chrome::kChromeUINewTabURL);
658 return true;
661 return false;
664 void SetInstantSupportStateInNavigationEntry(InstantSupportState state,
665 content::NavigationEntry* entry) {
666 if (!entry)
667 return;
669 entry->SetExtraData(kInstantSupportStateKey,
670 InstantSupportStateToString(state));
673 InstantSupportState GetInstantSupportStateFromNavigationEntry(
674 const content::NavigationEntry& entry) {
675 base::string16 value;
676 if (!entry.GetExtraData(kInstantSupportStateKey, &value))
677 return INSTANT_SUPPORT_UNKNOWN;
679 return StringToInstantSupportState(value);
682 bool ShouldPrefetchSearchResultsOnSRP() {
683 FieldTrialFlags flags;
684 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
685 kPrefetchSearchResultsOnSRP, false, flags);
688 void EnableQueryExtractionForTesting() {
689 base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
690 cl->AppendSwitch(switches::kEnableQueryExtraction);
693 bool ShouldUseAltInstantURL() {
694 FieldTrialFlags flags;
695 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
696 kUseAltInstantURL, false, flags);
699 bool ShouldUseSearchPathForInstant() {
700 FieldTrialFlags flags;
701 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
702 kUseSearchPathForInstant, false, flags);
705 } // namespace chrome