Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / search / search.cc
blob7fe3c5194da9adeb4f501c5714cae0943e595957
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/prefs/pref_service.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/google/google_util.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.h"
20 #include "chrome/browser/search_engines/template_url_service_factory.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/sessions/serialized_navigation_entry.h"
30 #include "components/user_prefs/pref_registry_syncable.h"
31 #include "content/public/browser/navigation_entry.h"
32 #include "content/public/browser/render_process_host.h"
33 #include "content/public/browser/web_contents.h"
34 #include "grit/generated_resources.h"
35 #include "ui/base/l10n/l10n_util.h"
37 #if defined(ENABLE_MANAGED_USERS)
38 #include "chrome/browser/managed_mode/managed_mode_url_filter.h"
39 #include "chrome/browser/managed_mode/managed_user_service.h"
40 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
41 #endif
43 namespace chrome {
45 namespace {
47 // Configuration options for Embedded Search.
48 // EmbeddedSearch field trials are named in such a way that we can parse out
49 // the experiment configuration from the trial's group name in order to give
50 // us maximum flexability in running experiments.
51 // Field trial groups should be named things like "Group7 espv:2 instant:1".
52 // The first token is always GroupN for some integer N, followed by a
53 // space-delimited list of key:value pairs which correspond to these flags:
54 const char kEmbeddedPageVersionFlagName[] = "espv";
55 #if defined(OS_IOS) || defined(OS_ANDROID)
56 const uint64 kEmbeddedPageVersionDefault = 1;
57 #else
58 const uint64 kEmbeddedPageVersionDefault = 2;
59 #endif
61 const char kHideVerbatimFlagName[] = "hide_verbatim";
62 const char kPrefetchSearchResultsFlagName[] = "prefetch_results";
63 const char kPrefetchSearchResultsOnSRP[] = "prefetch_results_srp";
64 const char kDisplaySearchButtonFlagName[] = "display_search_button";
65 const char kOriginChipFlagName[] = "origin_chip";
66 #if !defined(OS_IOS) && !defined(OS_ANDROID)
67 const char kEnableQueryExtractionFlagName[] = "query_extraction";
68 #endif
70 // Constants for the field trial name and group prefix.
71 // Note in M30 and below this field trial was named "InstantExtended" and in
72 // M31 was renamed to EmbeddedSearch for clarity and cleanliness. Since we
73 // can't easilly sync up Finch configs with the pushing of this change to
74 // Dev & Canary, for now the code accepts both names.
75 // TODO(dcblack): Remove the InstantExtended name once M31 hits the Beta
76 // channel.
77 const char kInstantExtendedFieldTrialName[] = "InstantExtended";
78 const char kEmbeddedSearchFieldTrialName[] = "EmbeddedSearch";
80 // If the field trial's group name ends with this string its configuration will
81 // be ignored and Instant Extended will not be enabled by default.
82 const char kDisablingSuffix[] = "DISABLED";
84 // Used to set the Instant support state of the Navigation entry.
85 const char kInstantSupportStateKey[] = "instant_support_state";
87 const char kInstantSupportEnabled[] = "Instant support enabled";
88 const char kInstantSupportDisabled[] = "Instant support disabled";
89 const char kInstantSupportUnknown[] = "Instant support unknown";
91 InstantSupportState StringToInstantSupportState(const base::string16& value) {
92 if (value == base::ASCIIToUTF16(kInstantSupportEnabled))
93 return INSTANT_SUPPORT_YES;
94 else if (value == base::ASCIIToUTF16(kInstantSupportDisabled))
95 return INSTANT_SUPPORT_NO;
96 else
97 return INSTANT_SUPPORT_UNKNOWN;
100 base::string16 InstantSupportStateToString(InstantSupportState state) {
101 switch (state) {
102 case INSTANT_SUPPORT_NO:
103 return base::ASCIIToUTF16(kInstantSupportDisabled);
104 case INSTANT_SUPPORT_YES:
105 return base::ASCIIToUTF16(kInstantSupportEnabled);
106 case INSTANT_SUPPORT_UNKNOWN:
107 return base::ASCIIToUTF16(kInstantSupportUnknown);
109 return base::ASCIIToUTF16(kInstantSupportUnknown);
112 TemplateURL* GetDefaultSearchProviderTemplateURL(Profile* profile) {
113 TemplateURLService* template_url_service =
114 TemplateURLServiceFactory::GetForProfile(profile);
115 if (template_url_service)
116 return template_url_service->GetDefaultSearchProvider();
117 return NULL;
120 GURL TemplateURLRefToGURL(const TemplateURLRef& ref,
121 int start_margin,
122 bool append_extra_query_params,
123 bool force_instant_results) {
124 TemplateURLRef::SearchTermsArgs search_terms_args =
125 TemplateURLRef::SearchTermsArgs(base::string16());
126 search_terms_args.omnibox_start_margin = start_margin;
127 search_terms_args.append_extra_query_params = append_extra_query_params;
128 search_terms_args.force_instant_results = force_instant_results;
129 return GURL(ref.ReplaceSearchTerms(search_terms_args));
132 bool MatchesAnySearchURL(const GURL& url, TemplateURL* template_url) {
133 GURL search_url =
134 TemplateURLRefToGURL(template_url->url_ref(), kDisableStartMargin, false,
135 false);
136 if (search_url.is_valid() &&
137 search::MatchesOriginAndPath(url, search_url))
138 return true;
140 // "URLCount() - 1" because we already tested url_ref above.
141 for (size_t i = 0; i < template_url->URLCount() - 1; ++i) {
142 TemplateURLRef ref(template_url, i);
143 search_url = TemplateURLRefToGURL(ref, kDisableStartMargin, false, false);
144 if (search_url.is_valid() &&
145 search::MatchesOriginAndPath(url, search_url))
146 return true;
149 return false;
152 // Returns true if |contents| is rendered inside the Instant process for
153 // |profile|.
154 bool IsRenderedInInstantProcess(const content::WebContents* contents,
155 Profile* profile) {
156 const content::RenderProcessHost* process_host =
157 contents->GetRenderProcessHost();
158 if (!process_host)
159 return false;
161 const InstantService* instant_service =
162 InstantServiceFactory::GetForProfile(profile);
163 if (!instant_service)
164 return false;
166 return instant_service->IsInstantProcess(process_host->GetID());
169 // Returns true if |url| passes some basic checks that must succeed for it to be
170 // usable as an instant URL:
171 // (1) It contains the search terms replacement key of |template_url|, which is
172 // expected to be the TemplateURL* for the default search provider.
173 // (2) Either it has a secure scheme, or else the user has manually specified a
174 // --google-base-url and it uses that 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 const GURL instant_url =
204 TemplateURLRefToGURL(instant_url_ref, kDisableStartMargin, false, false);
205 if (!instant_url.is_valid())
206 return false;
208 if (search::MatchesOriginAndPath(url, instant_url))
209 return true;
211 return IsQueryExtractionEnabled() && MatchesAnySearchURL(url, template_url);
214 base::string16 GetSearchTermsImpl(const content::WebContents* contents,
215 const content::NavigationEntry* entry) {
216 if (!contents || !IsQueryExtractionEnabled())
217 return base::string16();
219 // For security reasons, don't extract search terms if the page is not being
220 // rendered in the privileged Instant renderer process. This is to protect
221 // against a malicious page somehow scripting the search results page and
222 // faking search terms in the URL. Random pages can't get into the Instant
223 // renderer and scripting doesn't work cross-process, so if the page is in
224 // the Instant process, we know it isn't being exploited.
225 // Since iOS and Android doesn't use the instant framework, these checks are
226 // disabled for the two platforms.
227 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
228 #if !defined(OS_IOS) && !defined(OS_ANDROID)
229 if (!IsRenderedInInstantProcess(contents, profile) &&
230 ((entry == contents->GetController().GetLastCommittedEntry()) ||
231 !ShouldAssignURLToInstantRenderer(entry->GetURL(), profile)))
232 return base::string16();
233 #endif // !defined(OS_IOS) && !defined(OS_ANDROID)
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 // Otherwise, extract from the URL.
240 return GetSearchTermsFromURL(profile, entry->GetVirtualURL());
243 bool IsURLAllowedForSupervisedUser(const GURL& url, Profile* profile) {
244 #if defined(ENABLE_MANAGED_USERS)
245 ManagedUserService* managed_user_service =
246 ManagedUserServiceFactory::GetForProfile(profile);
247 ManagedModeURLFilter* url_filter =
248 managed_user_service->GetURLFilterForUIThread();
249 if (url_filter->GetFilteringBehaviorForURL(url) ==
250 ManagedModeURLFilter::BLOCK) {
251 return false;
253 #endif
254 return true;
257 } // namespace
259 // Negative start-margin values prevent the "es_sm" parameter from being used.
260 const int kDisableStartMargin = -1;
262 bool IsInstantExtendedAPIEnabled() {
263 #if defined(OS_IOS) || defined(OS_ANDROID)
264 return false;
265 #else
266 return true;
267 #endif // defined(OS_IOS) || defined(OS_ANDROID)
270 // Determine what embedded search page version to request from the user's
271 // default search provider. If 0, the embedded search UI should not be enabled.
272 uint64 EmbeddedSearchPageVersion() {
273 FieldTrialFlags flags;
274 if (GetFieldTrialInfo(&flags)) {
275 return GetUInt64ValueForFlagWithDefault(kEmbeddedPageVersionFlagName,
276 kEmbeddedPageVersionDefault,
277 flags);
279 return kEmbeddedPageVersionDefault;
282 bool IsQueryExtractionEnabled() {
283 #if defined(OS_IOS) || defined(OS_ANDROID)
284 return true;
285 #else
286 if (!IsInstantExtendedAPIEnabled())
287 return false;
289 const CommandLine* command_line = CommandLine::ForCurrentProcess();
290 if (command_line->HasSwitch(switches::kEnableQueryExtraction))
291 return true;
293 FieldTrialFlags flags;
294 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
295 kEnableQueryExtractionFlagName, false, flags);
296 #endif // defined(OS_IOS) || defined(OS_ANDROID)
299 base::string16 GetSearchTermsFromURL(Profile* profile, const GURL& url) {
300 if (url.is_valid() && url == GetSearchResultPrefetchBaseURL(profile)) {
301 // InstantSearchPrerenderer has the search query for the Instant search base
302 // page.
303 InstantSearchPrerenderer* prerenderer =
304 InstantSearchPrerenderer::GetForProfile(profile);
305 DCHECK(prerenderer);
306 return prerenderer->get_last_query();
309 base::string16 search_terms;
310 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
311 if (template_url && IsSuitableURLForInstant(url, template_url))
312 template_url->ExtractSearchTermsFromURL(url, &search_terms);
313 return search_terms;
316 base::string16 GetSearchTermsFromNavigationEntry(
317 const content::NavigationEntry* entry) {
318 base::string16 search_terms;
319 if (entry)
320 entry->GetExtraData(sessions::kSearchTermsKey, &search_terms);
321 return search_terms;
324 base::string16 GetSearchTerms(const content::WebContents* contents) {
325 if (!contents)
326 return base::string16();
328 const content::NavigationEntry* entry =
329 contents->GetController().GetVisibleEntry();
330 if (!entry)
331 return base::string16();
333 #if !defined(OS_IOS) && !defined(OS_ANDROID)
334 // iOS and Android doesn't use the Instant framework, disable this check for
335 // the two platforms.
336 InstantSupportState state = GetInstantSupportStateFromNavigationEntry(*entry);
337 if (state == INSTANT_SUPPORT_NO)
338 return base::string16();
339 #endif // !defined(OS_IOS) && !defined(OS_ANDROID)
341 return GetSearchTermsImpl(contents, entry);
344 bool ShouldAssignURLToInstantRenderer(const GURL& url, Profile* profile) {
345 return url.is_valid() &&
346 profile &&
347 IsInstantExtendedAPIEnabled() &&
348 (url.SchemeIs(chrome::kChromeSearchScheme) ||
349 IsInstantURL(url, profile));
352 bool ShouldUseProcessPerSiteForInstantURL(const GURL& url, Profile* profile) {
353 return ShouldAssignURLToInstantRenderer(url, profile) &&
354 (url.host() == chrome::kChromeSearchLocalNtpHost ||
355 url.host() == chrome::kChromeSearchOnlineNtpHost);
358 bool IsNTPURL(const GURL& url, Profile* profile) {
359 if (!url.is_valid())
360 return false;
362 if (!IsInstantExtendedAPIEnabled())
363 return url == GURL(chrome::kChromeUINewTabURL);
365 return profile &&
366 ((IsInstantURL(url, profile) &&
367 GetSearchTermsFromURL(profile, url).empty()) ||
368 url == GURL(chrome::kChromeSearchLocalNtpUrl));
371 bool IsInstantNTP(const content::WebContents* contents) {
372 if (!contents)
373 return false;
375 return NavEntryIsInstantNTP(contents,
376 contents->GetController().GetVisibleEntry());
379 bool NavEntryIsInstantNTP(const content::WebContents* contents,
380 const content::NavigationEntry* entry) {
381 if (!contents || !entry || !IsInstantExtendedAPIEnabled())
382 return false;
384 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
385 if (!IsRenderedInInstantProcess(contents, profile))
386 return false;
388 if (entry->GetURL() == GetLocalInstantURL(profile))
389 return true;
391 GURL new_tab_url(GetNewTabPageURL(profile));
392 return new_tab_url.is_valid() &&
393 search::MatchesOriginAndPath(entry->GetURL(), new_tab_url);
396 bool IsSuggestPrefEnabled(Profile* profile) {
397 return profile && !profile->IsOffTheRecord() && profile->GetPrefs() &&
398 profile->GetPrefs()->GetBoolean(prefs::kSearchSuggestEnabled);
401 GURL GetInstantURL(Profile* profile, int start_margin,
402 bool force_instant_results) {
403 if (!IsInstantExtendedAPIEnabled() || !IsSuggestPrefEnabled(profile))
404 return GURL();
406 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
407 if (!template_url)
408 return GURL();
410 GURL instant_url =
411 TemplateURLRefToGURL(template_url->instant_url_ref(), start_margin, true,
412 force_instant_results);
413 if (!instant_url.is_valid() ||
414 !template_url->HasSearchTermsReplacementKey(instant_url))
415 return GURL();
417 // Extended mode requires HTTPS. Force it unless the base URL was overridden
418 // on the command line, in which case we allow HTTP (see comments on
419 // IsSuitableURLForInstant()).
420 if (!instant_url.SchemeIsSecure() &&
421 !google_util::StartsWithCommandLineGoogleBaseURL(instant_url)) {
422 GURL::Replacements replacements;
423 const std::string secure_scheme(content::kHttpsScheme);
424 replacements.SetSchemeStr(secure_scheme);
425 instant_url = instant_url.ReplaceComponents(replacements);
428 if (!IsURLAllowedForSupervisedUser(instant_url, profile))
429 return GURL();
431 return instant_url;
434 // Returns URLs associated with the default search engine for |profile|.
435 std::vector<GURL> GetSearchURLs(Profile* profile) {
436 std::vector<GURL> result;
437 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
438 if (!template_url)
439 return result;
440 for (size_t i = 0; i < template_url->URLCount(); ++i) {
441 TemplateURLRef ref(template_url, i);
442 result.push_back(TemplateURLRefToGURL(ref, kDisableStartMargin, false,
443 false));
445 return result;
448 GURL GetNewTabPageURL(Profile* profile) {
449 if (!profile || profile->IsOffTheRecord())
450 return GURL();
452 if (!IsSuggestPrefEnabled(profile))
453 return GURL(chrome::kChromeSearchLocalNtpUrl);
455 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
456 if (!template_url)
457 return GURL(chrome::kChromeSearchLocalNtpUrl);
459 GURL url(TemplateURLRefToGURL(template_url->new_tab_url_ref(),
460 kDisableStartMargin, false, false));
461 if (!url.is_valid() || !url.SchemeIsSecure())
462 return GURL(chrome::kChromeSearchLocalNtpUrl);
464 if (!IsURLAllowedForSupervisedUser(url, profile))
465 return GURL(chrome::kChromeSearchLocalNtpUrl);
467 return url;
470 GURL GetSearchResultPrefetchBaseURL(Profile* profile) {
471 return ShouldPrefetchSearchResults() ?
472 GetInstantURL(profile, kDisableStartMargin, true) : GURL();
475 bool ShouldPrefetchSearchResults() {
476 FieldTrialFlags flags;
477 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
478 kPrefetchSearchResultsFlagName, false, flags);
481 GURL GetLocalInstantURL(Profile* profile) {
482 return GURL(chrome::kChromeSearchLocalNtpUrl);
485 bool ShouldHideTopVerbatimMatch() {
486 FieldTrialFlags flags;
487 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
488 kHideVerbatimFlagName, false, flags);
491 DisplaySearchButtonConditions GetDisplaySearchButtonConditions() {
492 const CommandLine* cl = CommandLine::ForCurrentProcess();
493 if (cl->HasSwitch(switches::kDisableSearchButtonInOmnibox)) {
494 return DISPLAY_SEARCH_BUTTON_NEVER;
495 } else if (cl->HasSwitch(switches::kEnableSearchButtonInOmniboxForStr)) {
496 return DISPLAY_SEARCH_BUTTON_FOR_STR;
497 } else if (cl->HasSwitch(switches::kEnableSearchButtonInOmniboxForStrOrIip)) {
498 return DISPLAY_SEARCH_BUTTON_FOR_STR_OR_IIP;
499 } else if (cl->HasSwitch(switches::kEnableSearchButtonInOmniboxAlways)) {
500 return DISPLAY_SEARCH_BUTTON_ALWAYS;
503 FieldTrialFlags flags;
504 if (!GetFieldTrialInfo(&flags))
505 return DISPLAY_SEARCH_BUTTON_NEVER;
506 uint64 value =
507 GetUInt64ValueForFlagWithDefault(kDisplaySearchButtonFlagName, 0, flags);
508 return (value < DISPLAY_SEARCH_BUTTON_NUM_VALUES) ?
509 static_cast<DisplaySearchButtonConditions>(value) :
510 DISPLAY_SEARCH_BUTTON_NEVER;
513 bool ShouldDisplayOriginChip() {
514 return GetOriginChipPosition() != ORIGIN_CHIP_DISABLED;
517 OriginChipPosition GetOriginChipPosition() {
518 const CommandLine* cl = CommandLine::ForCurrentProcess();
519 if (cl->HasSwitch(switches::kDisableOriginChip)) {
520 return ORIGIN_CHIP_DISABLED;
521 } else if (cl->HasSwitch(switches::kEnableOriginChipLeadingLocationBar)) {
522 return ORIGIN_CHIP_LEADING_LOCATION_BAR;
523 } else if (cl->HasSwitch(switches::kEnableOriginChip) ||
524 cl->HasSwitch(switches::kEnableOriginChipTrailingLocationBar)) {
525 return ORIGIN_CHIP_TRAILING_LOCATION_BAR;
526 } else if (cl->HasSwitch(switches::kEnableOriginChipLeadingMenuButton)) {
527 return ORIGIN_CHIP_LEADING_MENU_BUTTON;
530 FieldTrialFlags flags;
531 if (!GetFieldTrialInfo(&flags))
532 return ORIGIN_CHIP_DISABLED;
533 uint64 value =
534 GetUInt64ValueForFlagWithDefault(kOriginChipFlagName, 0, flags);
535 return (value < ORIGIN_CHIP_NUM_VALUES) ?
536 static_cast<OriginChipPosition>(value) :
537 ORIGIN_CHIP_DISABLED;
540 GURL GetEffectiveURLForInstant(const GURL& url, Profile* profile) {
541 CHECK(ShouldAssignURLToInstantRenderer(url, profile))
542 << "Error granting Instant access.";
544 if (url.SchemeIs(chrome::kChromeSearchScheme))
545 return url;
547 GURL effective_url(url);
549 // Replace the scheme with "chrome-search:".
550 url_canon::Replacements<char> replacements;
551 std::string search_scheme(chrome::kChromeSearchScheme);
552 replacements.SetScheme(search_scheme.data(),
553 url_parse::Component(0, search_scheme.length()));
555 // If the URL corresponds to an online NTP, replace the host with
556 // "online-ntp".
557 std::string online_ntp_host(chrome::kChromeSearchOnlineNtpHost);
558 TemplateURL* template_url = GetDefaultSearchProviderTemplateURL(profile);
559 if (template_url) {
560 const GURL instant_url = TemplateURLRefToGURL(
561 template_url->instant_url_ref(), kDisableStartMargin, false, false);
562 if (instant_url.is_valid() &&
563 search::MatchesOriginAndPath(url, instant_url)) {
564 replacements.SetHost(online_ntp_host.c_str(),
565 url_parse::Component(0, online_ntp_host.length()));
569 effective_url = effective_url.ReplaceComponents(replacements);
570 return effective_url;
573 bool HandleNewTabURLRewrite(GURL* url,
574 content::BrowserContext* browser_context) {
575 if (!IsInstantExtendedAPIEnabled())
576 return false;
578 if (!url->SchemeIs(chrome::kChromeUIScheme) ||
579 url->host() != chrome::kChromeUINewTabHost)
580 return false;
582 Profile* profile = Profile::FromBrowserContext(browser_context);
583 GURL new_tab_url(GetNewTabPageURL(profile));
584 if (!new_tab_url.is_valid())
585 return false;
587 *url = new_tab_url;
588 return true;
591 bool HandleNewTabURLReverseRewrite(GURL* url,
592 content::BrowserContext* browser_context) {
593 if (!IsInstantExtendedAPIEnabled())
594 return false;
596 Profile* profile = Profile::FromBrowserContext(browser_context);
597 GURL new_tab_url(GetNewTabPageURL(profile));
598 if (!new_tab_url.is_valid() ||
599 !search::MatchesOriginAndPath(new_tab_url, *url))
600 return false;
602 *url = GURL(chrome::kChromeUINewTabURL);
603 return true;
606 void SetInstantSupportStateInNavigationEntry(InstantSupportState state,
607 content::NavigationEntry* entry) {
608 if (!entry)
609 return;
611 entry->SetExtraData(kInstantSupportStateKey,
612 InstantSupportStateToString(state));
615 InstantSupportState GetInstantSupportStateFromNavigationEntry(
616 const content::NavigationEntry& entry) {
617 base::string16 value;
618 if (!entry.GetExtraData(kInstantSupportStateKey, &value))
619 return INSTANT_SUPPORT_UNKNOWN;
621 return StringToInstantSupportState(value);
624 bool ShouldPrefetchSearchResultsOnSRP() {
625 FieldTrialFlags flags;
626 return GetFieldTrialInfo(&flags) && GetBoolValueForFlagWithDefault(
627 kPrefetchSearchResultsOnSRP, false, flags);
630 void EnableQueryExtractionForTesting() {
631 CommandLine* cl = CommandLine::ForCurrentProcess();
632 cl->AppendSwitch(switches::kEnableQueryExtraction);
635 bool GetFieldTrialInfo(FieldTrialFlags* flags) {
636 // Get the group name. If the EmbeddedSearch trial doesn't exist, look for
637 // the older InstantExtended name.
638 std::string group_name = base::FieldTrialList::FindFullName(
639 kEmbeddedSearchFieldTrialName);
640 if (group_name.empty()) {
641 group_name = base::FieldTrialList::FindFullName(
642 kInstantExtendedFieldTrialName);
645 if (EndsWith(group_name, kDisablingSuffix, true))
646 return false;
648 // We have a valid trial that isn't disabled. Extract the flags.
649 std::string group_prefix(group_name);
650 size_t first_space = group_name.find(" ");
651 if (first_space != std::string::npos) {
652 // There is a flags section of the group name. Split that out and parse it.
653 group_prefix = group_name.substr(0, first_space);
654 if (!base::SplitStringIntoKeyValuePairs(group_name.substr(first_space),
655 ':', ' ', flags)) {
656 // Failed to parse the flags section. Assume the whole group name is
657 // invalid.
658 return false;
661 return true;
664 // Given a FieldTrialFlags object, returns the string value of the provided
665 // flag.
666 std::string GetStringValueForFlagWithDefault(const std::string& flag,
667 const std::string& default_value,
668 const FieldTrialFlags& flags) {
669 FieldTrialFlags::const_iterator i;
670 for (i = flags.begin(); i != flags.end(); i++) {
671 if (i->first == flag)
672 return i->second;
674 return default_value;
677 // Given a FieldTrialFlags object, returns the uint64 value of the provided
678 // flag.
679 uint64 GetUInt64ValueForFlagWithDefault(const std::string& flag,
680 uint64 default_value,
681 const FieldTrialFlags& flags) {
682 uint64 value;
683 std::string str_value =
684 GetStringValueForFlagWithDefault(flag, std::string(), flags);
685 if (base::StringToUint64(str_value, &value))
686 return value;
687 return default_value;
690 // Given a FieldTrialFlags object, returns the boolean value of the provided
691 // flag.
692 bool GetBoolValueForFlagWithDefault(const std::string& flag,
693 bool default_value,
694 const FieldTrialFlags& flags) {
695 return !!GetUInt64ValueForFlagWithDefault(flag, default_value ? 1 : 0, flags);
698 } // namespace chrome