1 // Copyright (c) 2013 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 "base/command_line.h"
6 #include "base/metrics/field_trial.h"
7 #include "base/metrics/histogram_base.h"
8 #include "base/metrics/histogram_samples.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/search/instant_service.h"
12 #include "chrome/browser/search/instant_service_factory.h"
13 #include "chrome/browser/search/search.h"
14 #include "chrome/browser/search_engines/template_url_service_factory.h"
15 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
16 #include "chrome/browser/supervised_user/supervised_user_service.h"
17 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
18 #include "chrome/browser/supervised_user/supervised_user_url_filter.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/common/url_constants.h"
23 #include "chrome/test/base/browser_with_test_window_test.h"
24 #include "chrome/test/base/ui_test_utils.h"
25 #include "components/google/core/browser/google_switches.h"
26 #include "components/search/search.h"
27 #include "components/search_engines/search_engines_switches.h"
28 #include "components/search_engines/template_url_service.h"
29 #include "components/variations/entropy_provider.h"
30 #include "content/public/browser/render_process_host.h"
31 #include "content/public/browser/render_view_host.h"
32 #include "content/public/browser/site_instance.h"
33 #include "content/public/browser/web_contents.h"
34 #include "content/public/common/renderer_preferences.h"
39 class SearchTest : public BrowserWithTestWindowTest {
41 virtual void SetUp() OVERRIDE {
42 BrowserWithTestWindowTest::SetUp();
43 field_trial_list_.reset(new base::FieldTrialList(
44 new metrics::SHA1EntropyProvider("42")));
45 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
46 profile(), &TemplateURLServiceFactory::BuildInstanceFor);
47 TemplateURLService* template_url_service =
48 TemplateURLServiceFactory::GetForProfile(profile());
49 ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
50 SetSearchProvider(true, false);
53 virtual void SetSearchProvider(bool set_ntp_url, bool insecure_ntp_url) {
54 TemplateURLService* template_url_service =
55 TemplateURLServiceFactory::GetForProfile(profile());
57 data.SetURL("http://foo.com/url?bar={searchTerms}");
58 data.instant_url = "http://foo.com/instant?"
59 "{google:forceInstantResults}foo=foo#foo=foo&strk";
61 data.new_tab_url = (insecure_ntp_url ? "http" : "https") +
62 std::string("://foo.com/newtab?strk");
64 data.alternate_urls.push_back("http://foo.com/alt#quux={searchTerms}");
65 data.search_terms_replacement_key = "strk";
67 TemplateURL* template_url = new TemplateURL(data);
68 // Takes ownership of |template_url|.
69 template_url_service->Add(template_url);
70 template_url_service->SetUserSelectedDefaultSearchProvider(template_url);
73 // Build an Instant URL with or without a valid search terms replacement key
74 // as per |has_search_term_replacement_key|. Set that URL as the instant URL
75 // for the default search provider.
76 void SetDefaultInstantTemplateUrl(bool has_search_term_replacement_key) {
77 TemplateURLService* template_url_service =
78 TemplateURLServiceFactory::GetForProfile(profile());
80 static const char kInstantURLWithStrk[] =
81 "http://foo.com/instant?foo=foo#foo=foo&strk";
82 static const char kInstantURLNoStrk[] =
83 "http://foo.com/instant?foo=foo#foo=foo";
86 data.SetURL("http://foo.com/url?bar={searchTerms}");
87 data.instant_url = (has_search_term_replacement_key ?
88 kInstantURLWithStrk : kInstantURLNoStrk);
89 data.search_terms_replacement_key = "strk";
91 TemplateURL* template_url = new TemplateURL(data);
92 // Takes ownership of |template_url|.
93 template_url_service->Add(template_url);
94 template_url_service->SetUserSelectedDefaultSearchProvider(template_url);
97 bool InInstantProcess(const content::WebContents* contents) {
98 InstantService* instant_service =
99 InstantServiceFactory::GetForProfile(profile());
100 return instant_service->IsInstantProcess(
101 contents->GetRenderProcessHost()->GetID());
104 scoped_ptr<base::FieldTrialList> field_trial_list_;
107 struct SearchTestCase {
109 bool expected_result;
113 TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedEnabled) {
114 EnableQueryExtractionForTesting();
116 const SearchTestCase kTestCases[] = {
117 {chrome::kChromeSearchLocalNtpUrl, true, ""},
118 {"https://foo.com/instant?strk", true, ""},
119 {"https://foo.com/instant#strk", true, ""},
120 {"https://foo.com/instant?strk=0", true, ""},
121 {"https://foo.com/url?strk", true, ""},
122 {"https://foo.com/alt?strk", true, ""},
123 {"http://foo.com/instant", false, "Non-HTTPS"},
124 {"http://foo.com/instant?strk", false, "Non-HTTPS"},
125 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"},
126 {"https://foo.com/instant", false, "No search terms replacement"},
127 {"https://foo.com/?strk", false, "Non-exact path"},
130 for (size_t i = 0; i < arraysize(kTestCases); ++i) {
131 const SearchTestCase& test = kTestCases[i];
132 EXPECT_EQ(test.expected_result,
133 ShouldAssignURLToInstantRenderer(GURL(test.url), profile()))
134 << test.url << " " << test.comment;
138 TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedEnabledNotOnSRP) {
139 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
140 "EmbeddedSearch", "Group1 espv:2 suppress_on_srp:1"));
142 const SearchTestCase kTestCases[] = {
143 {chrome::kChromeSearchLocalNtpUrl, true, ""},
144 {"https://foo.com/instant?strk", true, ""},
145 {"https://foo.com/instant#strk", true, ""},
146 {"https://foo.com/instant?strk=0", true, ""},
147 {"https://foo.com/url?strk", false, "Disabled on SRP"},
148 {"https://foo.com/alt?strk", false, "Disabled ON SRP"},
149 {"http://foo.com/instant", false, "Non-HTTPS"},
150 {"http://foo.com/instant?strk", false, "Non-HTTPS"},
151 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"},
152 {"https://foo.com/instant", false, "No search terms replacement"},
153 {"https://foo.com/?strk", false, "Non-exact path"},
156 for (size_t i = 0; i < arraysize(kTestCases); ++i) {
157 const SearchTestCase& test = kTestCases[i];
158 EXPECT_EQ(test.expected_result,
159 ShouldAssignURLToInstantRenderer(GURL(test.url), profile()))
160 << test.url << " " << test.comment;
164 TEST_F(SearchTest, ShouldUseProcessPerSiteForInstantURL) {
165 EnableQueryExtractionForTesting();
167 const SearchTestCase kTestCases[] = {
168 {"chrome-search://local-ntp", true, "Local NTP"},
169 {"chrome-search://remote-ntp", true, "Remote NTP"},
170 {"invalid-scheme://local-ntp", false, "Invalid Local NTP URL"},
171 {"invalid-scheme://online-ntp", false, "Invalid Online NTP URL"},
172 {"chrome-search://foo.com", false, "Search result page"},
173 {"https://foo.com/instant?strk", false, ""},
174 {"https://foo.com/instant#strk", false, ""},
175 {"https://foo.com/instant?strk=0", false, ""},
176 {"https://foo.com/url?strk", false, ""},
177 {"https://foo.com/alt?strk", false, ""},
178 {"http://foo.com/instant", false, "Non-HTTPS"},
179 {"http://foo.com/instant?strk", false, "Non-HTTPS"},
180 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"},
181 {"https://foo.com/instant", false, "No search terms replacement"},
182 {"https://foo.com/?strk", false, "Non-exact path"},
185 for (size_t i = 0; i < arraysize(kTestCases); ++i) {
186 const SearchTestCase& test = kTestCases[i];
187 EXPECT_EQ(test.expected_result,
188 ShouldUseProcessPerSiteForInstantURL(GURL(test.url), profile()))
189 << test.url << " " << test.comment;
193 // Each test case represents a navigation to |start_url| followed by a
194 // navigation to |end_url|. We will check whether each navigation lands in an
195 // Instant process, and also whether the navigation from start to end re-uses
196 // the same SiteInstance (and hence the same RenderViewHost, etc.).
197 const struct ProcessIsolationTestCase {
198 const char* description;
199 const char* start_url;
200 bool start_in_instant_process;
202 bool end_in_instant_process;
203 bool same_site_instance;
204 } kProcessIsolationTestCases[] = {
206 "chrome-search://local-ntp", true,
207 "https://foo.com/url?strk", true, false },
208 {"Local NTP -> Regular",
209 "chrome-search://local-ntp", true,
210 "https://foo.com/other", false, false },
211 {"Remote NTP -> SRP",
212 "https://foo.com/newtab?strk", true,
213 "https://foo.com/url?strk", true, false },
214 {"Remote NTP -> Regular",
215 "https://foo.com/newtab?strk", true,
216 "https://foo.com/other", false, false },
218 "https://foo.com/url?strk", true,
219 "https://foo.com/url?strk", true, true },
221 "https://foo.com/url?strk", true,
222 "https://foo.com/other", false, false },
224 "https://foo.com/other", false,
225 "https://foo.com/url?strk", true, false },
228 TEST_F(SearchTest, ProcessIsolation) {
229 EnableQueryExtractionForTesting();
231 for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) {
232 const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i];
233 AddTab(browser(), GURL("chrome://blank"));
234 const content::WebContents* contents =
235 browser()->tab_strip_model()->GetActiveWebContents();
237 // Navigate to start URL.
238 NavigateAndCommitActiveTab(GURL(test.start_url));
239 EXPECT_EQ(test.start_in_instant_process, InInstantProcess(contents))
243 const scoped_refptr<content::SiteInstance> start_site_instance =
244 contents->GetSiteInstance();
245 const content::RenderProcessHost* start_rph =
246 contents->GetRenderProcessHost();
247 const content::RenderViewHost* start_rvh =
248 contents->GetRenderViewHost();
250 // Navigate to end URL.
251 NavigateAndCommitActiveTab(GURL(test.end_url));
252 EXPECT_EQ(test.end_in_instant_process, InInstantProcess(contents))
255 EXPECT_EQ(test.same_site_instance,
256 start_site_instance.get() == contents->GetSiteInstance())
258 EXPECT_EQ(test.same_site_instance,
259 start_rvh == contents->GetRenderViewHost())
261 EXPECT_EQ(test.same_site_instance,
262 start_rph == contents->GetRenderProcessHost())
267 TEST_F(SearchTest, ProcessIsolation_RendererInitiated) {
268 EnableQueryExtractionForTesting();
270 for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) {
271 const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i];
272 AddTab(browser(), GURL("chrome://blank"));
273 content::WebContents* contents =
274 browser()->tab_strip_model()->GetActiveWebContents();
276 // Navigate to start URL.
277 NavigateAndCommitActiveTab(GURL(test.start_url));
278 EXPECT_EQ(test.start_in_instant_process, InInstantProcess(contents))
282 const scoped_refptr<content::SiteInstance> start_site_instance =
283 contents->GetSiteInstance();
284 const content::RenderProcessHost* start_rph =
285 contents->GetRenderProcessHost();
286 const content::RenderViewHost* start_rvh =
287 contents->GetRenderViewHost();
289 // Navigate to end URL via a renderer-initiated navigation.
290 content::NavigationController* controller = &contents->GetController();
291 content::NavigationController::LoadURLParams load_params(
293 load_params.is_renderer_initiated = true;
294 load_params.transition_type = ui::PAGE_TRANSITION_LINK;
296 controller->LoadURLWithParams(load_params);
297 CommitPendingLoad(controller);
298 EXPECT_EQ(test.end_in_instant_process, InInstantProcess(contents))
301 EXPECT_EQ(test.same_site_instance,
302 start_site_instance.get() == contents->GetSiteInstance())
304 EXPECT_EQ(test.same_site_instance,
305 start_rvh == contents->GetRenderViewHost())
307 EXPECT_EQ(test.same_site_instance,
308 start_rph == contents->GetRenderProcessHost())
313 const SearchTestCase kInstantNTPTestCases[] = {
314 {"https://foo.com/instant?strk", false, "Valid Instant URL"},
315 {"https://foo.com/instant#strk", false, "Valid Instant URL"},
316 {"https://foo.com/url?strk", false, "Valid search URL"},
317 {"https://foo.com/url#strk", false, "Valid search URL"},
318 {"https://foo.com/alt?strk", false, "Valid alternative URL"},
319 {"https://foo.com/alt#strk", false, "Valid alternative URL"},
320 {"https://foo.com/url?strk&bar=", false, "No query terms"},
321 {"https://foo.com/url?strk&q=abc", false, "No query terms key"},
322 {"https://foo.com/url?strk#bar=abc", false, "Query terms key in ref"},
323 {"https://foo.com/url?strk&bar=abc", false, "Has query terms"},
324 {"http://foo.com/instant?strk=1", false, "Insecure URL"},
325 {"https://foo.com/instant", false, "No search term replacement"},
326 {"chrome://blank/", false, "Chrome scheme"},
327 {"chrome-search://foo", false, "Chrome-search scheme"},
328 {"https://bar.com/instant?strk=1", false, "Random non-search page"},
329 {chrome::kChromeSearchLocalNtpUrl, true, "Local new tab page"},
330 {"https://foo.com/newtab?strk", true, "New tab URL"},
331 {"http://foo.com/newtab?strk", false, "Insecure New tab URL"},
334 TEST_F(SearchTest, InstantNTPExtendedEnabled) {
335 EnableQueryExtractionForTesting();
336 AddTab(browser(), GURL("chrome://blank"));
337 for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
338 const SearchTestCase& test = kInstantNTPTestCases[i];
339 NavigateAndCommitActiveTab(GURL(test.url));
340 const content::WebContents* contents =
341 browser()->tab_strip_model()->GetWebContentsAt(0);
342 EXPECT_EQ(test.expected_result, IsInstantNTP(contents))
343 << test.url << " " << test.comment;
347 TEST_F(SearchTest, InstantNTPCustomNavigationEntry) {
348 EnableQueryExtractionForTesting();
349 AddTab(browser(), GURL("chrome://blank"));
350 for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
351 const SearchTestCase& test = kInstantNTPTestCases[i];
352 NavigateAndCommitActiveTab(GURL(test.url));
353 content::WebContents* contents =
354 browser()->tab_strip_model()->GetWebContentsAt(0);
355 content::NavigationController& controller = contents->GetController();
356 controller.SetTransientEntry(
357 controller.CreateNavigationEntry(GURL("chrome://blank"),
359 ui::PAGE_TRANSITION_LINK,
362 contents->GetBrowserContext()));
363 // The active entry is chrome://blank and not an NTP.
364 EXPECT_FALSE(IsInstantNTP(contents));
365 EXPECT_EQ(test.expected_result,
366 NavEntryIsInstantNTP(contents,
367 controller.GetLastCommittedEntry()))
368 << test.url << " " << test.comment;
372 TEST_F(SearchTest, InstantCacheableNTPNavigationEntry) {
373 AddTab(browser(), GURL("chrome://blank"));
374 content::WebContents* contents =
375 browser()->tab_strip_model()->GetWebContentsAt(0);
376 content::NavigationController& controller = contents->GetController();
378 NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl));
379 EXPECT_TRUE(NavEntryIsInstantNTP(contents,
380 controller.GetLastCommittedEntry()));
381 // Instant page is not cacheable NTP.
382 NavigateAndCommitActiveTab(GetInstantURL(profile(), false));
383 EXPECT_FALSE(NavEntryIsInstantNTP(contents,
384 controller.GetLastCommittedEntry()));
385 // Test Cacheable NTP
386 NavigateAndCommitActiveTab(chrome::GetNewTabPageURL(profile()));
387 EXPECT_TRUE(NavEntryIsInstantNTP(contents,
388 controller.GetLastCommittedEntry()));
391 TEST_F(SearchTest, InstantCacheableNTPNavigationEntryNewProfile) {
392 SetSearchProvider(false, false);
393 AddTab(browser(), GURL(chrome::kChromeUINewTabURL));
394 content::WebContents* contents =
395 browser()->tab_strip_model()->GetWebContentsAt(0);
396 content::NavigationController& controller = contents->GetController();
397 // Test virtual url chrome://newtab for first NTP of a new profile
398 EXPECT_TRUE(NavEntryIsInstantNTP(contents,
399 controller.GetLastCommittedEntry()));
400 // The new_tab_url gets set after the first NTP is visible.
401 SetSearchProvider(true, false);
402 EXPECT_TRUE(NavEntryIsInstantNTP(contents,
403 controller.GetLastCommittedEntry()));
406 TEST_F(SearchTest, NoRewriteInIncognito) {
407 profile()->ForceIncognito(true);
408 EXPECT_EQ(GURL(), chrome::GetNewTabPageURL(profile()));
409 GURL new_tab_url(chrome::kChromeUINewTabURL);
410 EXPECT_FALSE(HandleNewTabURLRewrite(&new_tab_url, profile()));
411 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), new_tab_url);
414 TEST_F(SearchTest, UseLocalNTPIfNTPURLIsInsecure) {
415 // Set an insecure new tab page URL and verify that it's ignored.
416 SetSearchProvider(true, true);
417 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
418 chrome::GetNewTabPageURL(profile()));
419 GURL new_tab_url(chrome::kChromeUINewTabURL);
420 EXPECT_TRUE(HandleNewTabURLRewrite(&new_tab_url, profile()));
421 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), new_tab_url);
424 TEST_F(SearchTest, UseLocalNTPIfNTPURLIsNotSet) {
425 // Set an insecure new tab page URL and verify that it's ignored.
426 SetSearchProvider(false, true);
427 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
428 chrome::GetNewTabPageURL(profile()));
429 GURL new_tab_url(chrome::kChromeUINewTabURL);
430 EXPECT_TRUE(HandleNewTabURLRewrite(&new_tab_url, profile()));
431 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), new_tab_url);
434 TEST_F(SearchTest, UseLocalNTPIfNTPURLIsBlockedForSupervisedUser) {
435 // Block access to foo.com in the URL filter.
436 SupervisedUserService* supervised_user_service =
437 SupervisedUserServiceFactory::GetForProfile(profile());
438 SupervisedUserURLFilter* url_filter =
439 supervised_user_service->GetURLFilterForUIThread();
440 std::map<std::string, bool> hosts;
441 hosts["foo.com"] = false;
442 url_filter->SetManualHosts(&hosts);
444 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
445 chrome::GetNewTabPageURL(profile()));
446 GURL new_tab_url(chrome::kChromeUINewTabURL);
447 EXPECT_TRUE(HandleNewTabURLRewrite(&new_tab_url, profile()));
448 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), new_tab_url);
449 EXPECT_EQ(GURL(), GetInstantURL(profile(), false));
452 TEST_F(SearchTest, GetInstantURL) {
453 // No Instant URL because "strk" is missing.
454 SetDefaultInstantTemplateUrl(false);
455 EXPECT_EQ(GURL(), GetInstantURL(profile(), false));
457 // Set an Instant URL with a valid search terms replacement key.
458 SetDefaultInstantTemplateUrl(true);
460 // Now there should be a valid Instant URL. Note the HTTPS "upgrade".
461 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
462 GetInstantURL(profile(), false));
464 // Enable suggest. No difference.
465 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
466 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
467 GetInstantURL(profile(), false));
469 // Disable suggest. No Instant URL.
470 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
471 EXPECT_EQ(GURL(), GetInstantURL(profile(), false));
473 // Use alternate Instant search base URL.
474 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
475 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
476 "EmbeddedSearch", "Group1 espv:8 use_alternate_instant_url:1"));
477 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo&qbp=1#foo=foo&strk"),
478 GetInstantURL(profile(), false));
481 TEST_F(SearchTest, UseSearchPathForInstant) {
482 // Use alternate Instant search base URL path.
483 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
485 "Group1 use_alternate_instant_url:1 use_search_path_for_instant:1"));
486 EXPECT_EQ(GURL("https://foo.com/search?foo=foo&qbp=1#foo=foo&strk"),
487 GetInstantURL(profile(), false));
490 TEST_F(SearchTest, InstantSearchEnabledCGI) {
491 // Disable Instant Search.
492 // Make sure {google:forceInstantResults} is not set in the Instant URL.
493 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
494 GetInstantURL(profile(), false));
496 // Enable Instant Search.
497 // Make sure {google:forceInstantResults} is set in the Instant URL.
498 EXPECT_EQ(GURL("https://foo.com/instant?ion=1&foo=foo#foo=foo&strk"),
499 GetInstantURL(profile(), true));
502 TEST_F(SearchTest, CommandLineOverrides) {
503 GURL local_instant_url(GetLocalInstantURL(profile()));
504 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url);
506 TemplateURLService* template_url_service =
507 TemplateURLServiceFactory::GetForProfile(profile());
508 TemplateURLData data;
509 data.SetURL("{google:baseURL}search?q={searchTerms}");
510 data.instant_url = "{google:baseURL}webhp?strk";
511 data.search_terms_replacement_key = "strk";
512 TemplateURL* template_url = new TemplateURL(data);
513 // Takes ownership of |template_url|.
514 template_url_service->Add(template_url);
515 template_url_service->SetUserSelectedDefaultSearchProvider(template_url);
517 // By default, Instant Extended forces the instant URL to be HTTPS, so even if
518 // we set a Google base URL that is HTTP, we should get an HTTPS URL.
519 UIThreadSearchTermsData::SetGoogleBaseURL("http://www.foo.com/");
520 GURL instant_url(GetInstantURL(profile(), false));
521 ASSERT_TRUE(instant_url.is_valid());
522 EXPECT_EQ("https://www.foo.com/webhp?strk", instant_url.spec());
524 // However, if the Google base URL is specified on the command line, the
525 // instant URL should just use it, even if it's HTTP.
526 UIThreadSearchTermsData::SetGoogleBaseURL(std::string());
527 CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
528 "http://www.bar.com/");
529 instant_url = GetInstantURL(profile(), false);
530 ASSERT_TRUE(instant_url.is_valid());
531 EXPECT_EQ("http://www.bar.com/webhp?strk", instant_url.spec());
533 // Similarly, setting a Google base URL on the command line should allow you
534 // to get the Google version of the local NTP, even though search provider's
535 // URL doesn't contain "google".
536 local_instant_url = GetLocalInstantURL(profile());
537 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url);
539 // If we specify extra search query params, they should be inserted into the
540 // query portion of the instant URL.
541 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
542 switches::kExtraSearchQueryParams, "a=b");
543 instant_url = GetInstantURL(profile(), false);
544 ASSERT_TRUE(instant_url.is_valid());
545 EXPECT_EQ("http://www.bar.com/webhp?a=b&strk", instant_url.spec());
548 TEST_F(SearchTest, ShouldPrefetchSearchResults_InstantExtendedAPIEnabled) {
549 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
550 "EmbeddedSearch", "Group1 espv:2"));
552 EXPECT_EQ(1ul, EmbeddedSearchPageVersion());
553 EXPECT_TRUE(ShouldPrefetchSearchResults());
555 EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
556 EXPECT_TRUE(ShouldPrefetchSearchResults());
560 TEST_F(SearchTest, ShouldPrefetchSearchResults_Default) {
562 EXPECT_FALSE(ShouldPrefetchSearchResults());
564 EXPECT_TRUE(ShouldPrefetchSearchResults());
568 TEST_F(SearchTest, ShouldReuseInstantSearchBasePage_Default) {
570 EXPECT_FALSE(ShouldReuseInstantSearchBasePage());
572 EXPECT_TRUE(ShouldReuseInstantSearchBasePage());
576 TEST_F(SearchTest, ShouldAllowPrefetchNonDefaultMatch_DisabledViaFieldTrial) {
577 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
578 "EmbeddedSearch", "Group1 espv:89 allow_prefetch_non_default_match:0"));
579 EXPECT_FALSE(ShouldAllowPrefetchNonDefaultMatch());
580 EXPECT_EQ(89ul, EmbeddedSearchPageVersion());
583 TEST_F(SearchTest, ShouldAllowPrefetchNonDefaultMatch_EnabledViaFieldTrial) {
584 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
585 "EmbeddedSearch", "Group1 espv:80 allow_prefetch_non_default_match:1"));
586 EXPECT_TRUE(ShouldAllowPrefetchNonDefaultMatch());
587 EXPECT_EQ(80ul, EmbeddedSearchPageVersion());
590 TEST_F(SearchTest, ShouldUseAltInstantURL_DisabledViaFieldTrial) {
591 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
592 "EmbeddedSearch", "Group1 espv:8 use_alternate_instant_url:0"));
593 EXPECT_FALSE(ShouldUseAltInstantURL());
596 TEST_F(SearchTest, ShouldUseAltInstantURL_EnabledViaFieldTrial) {
597 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
598 "EmbeddedSearch", "Group1 espv:8 use_alternate_instant_url:1"));
599 EXPECT_TRUE(ShouldUseAltInstantURL());
602 TEST_F(SearchTest, ShouldUseSearchPathForInstant_DisabledViaFieldTrial) {
603 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
605 "Group1 use_alternate_instant_url:1 use_search_path_for_instant:0"));
606 EXPECT_FALSE(ShouldUseSearchPathForInstant());
609 TEST_F(SearchTest, ShouldUseSearchPathForInstant_EnabledViaFieldTrial) {
610 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
612 "Group1 use_alternate_instant_url:1 use_search_path_for_instant:1"));
613 EXPECT_TRUE(ShouldUseSearchPathForInstant());
617 ShouldPrerenderInstantUrlOnOmniboxFocus_DisabledViaFieldTrial) {
618 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
620 "Group1 espv:89 prerender_instant_url_on_omnibox_focus:0"));
621 EXPECT_FALSE(ShouldPrerenderInstantUrlOnOmniboxFocus());
622 EXPECT_EQ(89ul, EmbeddedSearchPageVersion());
626 ShouldPrerenderInstantUrlOnOmniboxFocus_EnabledViaFieldTrial) {
627 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
629 "Group1 espv:80 prerender_instant_url_on_omnibox_focus:1"));
630 EXPECT_TRUE(ShouldPrerenderInstantUrlOnOmniboxFocus());
631 EXPECT_EQ(80ul, EmbeddedSearchPageVersion());
636 TEST_F(SearchTest, ShouldShowGoogleLocalNTP_Default) {
637 EXPECT_TRUE(ShouldShowGoogleLocalNTP());
640 TEST_F(SearchTest, ShouldShowGoogleLocalNTP_EnabledViaFinch) {
641 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
642 "EmbeddedSearch", "Group1 espv:2 google_local_ntp:1"));
643 EXPECT_TRUE(ShouldShowGoogleLocalNTP());
646 TEST_F(SearchTest, ShouldShowGoogleLocalNTP_DisabledViaFinch) {
647 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
648 "EmbeddedSearch", "Group1 espv:2 google_local_ntp:0"));
649 EXPECT_FALSE(ShouldShowGoogleLocalNTP());
653 TEST_F(SearchTest, IsNTPURL) {
655 GURL ntp_url(chrome::kChromeUINewTabURL);
656 GURL local_ntp_url(GetLocalInstantURL(profile()));
658 EXPECT_FALSE(chrome::IsNTPURL(invalid_url, profile()));
660 EnableQueryExtractionForTesting();
661 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
662 GURL remote_ntp_url(GetInstantURL(profile(), false));
663 GURL search_url_with_search_terms("https://foo.com/url?strk&bar=abc");
664 GURL search_url_without_search_terms("https://foo.com/url?strk&bar");
666 EXPECT_FALSE(chrome::IsNTPURL(ntp_url, profile()));
667 EXPECT_TRUE(chrome::IsNTPURL(local_ntp_url, profile()));
668 EXPECT_TRUE(chrome::IsNTPURL(remote_ntp_url, profile()));
669 EXPECT_FALSE(chrome::IsNTPURL(search_url_with_search_terms, profile()));
670 EXPECT_TRUE(chrome::IsNTPURL(search_url_without_search_terms, profile()));
672 EXPECT_FALSE(chrome::IsNTPURL(ntp_url, NULL));
673 EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, NULL));
674 EXPECT_FALSE(chrome::IsNTPURL(remote_ntp_url, NULL));
675 EXPECT_FALSE(chrome::IsNTPURL(search_url_with_search_terms, NULL));
676 EXPECT_FALSE(chrome::IsNTPURL(search_url_without_search_terms, NULL));
679 TEST_F(SearchTest, GetSearchURLs) {
680 std::vector<GURL> search_urls = GetSearchURLs(profile());
681 EXPECT_EQ(2U, search_urls.size());
682 EXPECT_EQ("http://foo.com/alt#quux=", search_urls[0].spec());
683 EXPECT_EQ("http://foo.com/url?bar=", search_urls[1].spec());
686 TEST_F(SearchTest, GetSearchResultPrefetchBaseURL) {
688 EXPECT_FALSE(ShouldPrefetchSearchResults());
689 EXPECT_EQ(GURL(), GetSearchResultPrefetchBaseURL(profile()));
691 EXPECT_TRUE(ShouldPrefetchSearchResults());
692 EXPECT_EQ(GURL("https://foo.com/instant?ion=1&foo=foo#foo=foo&strk"),
693 GetSearchResultPrefetchBaseURL(profile()));
697 TEST_F(SearchTest, ForceInstantResultsParam) {
698 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
700 EXPECT_TRUE(IsInstantExtendedAPIEnabled());
701 EXPECT_EQ("ion=1&", ForceInstantResultsParam(true));
702 EXPECT_EQ(std::string(), ForceInstantResultsParam(false));
705 struct ExtractSearchTermsTestCase {
707 const char* expected_result;
711 TEST_F(SearchTest, ExtractSearchTermsFromURL) {
712 const ExtractSearchTermsTestCase kTestCases[] = {
713 {chrome::kChromeSearchLocalNtpUrl, "", "NTP url"},
714 {"https://foo.com/instant?strk", "", "Invalid search url"},
715 {"https://foo.com/instant#strk", "", "Invalid search url"},
716 {"https://foo.com/alt#quux=foo", "foo", "Valid search url"},
717 {"https://foo.com/alt#quux=foo&strk", "foo", "Valid search url"}
720 for (size_t i = 0; i < arraysize(kTestCases); ++i) {
721 const ExtractSearchTermsTestCase& test = kTestCases[i];
723 test.expected_result,
724 base::UTF16ToASCII(chrome::ExtractSearchTermsFromURL(profile(),
726 << test.url << " " << test.comment;
730 struct QueryExtractionAllowedTestCase {
732 bool expected_result;
736 TEST_F(SearchTest, IsQueryExtractionAllowedForURL) {
737 const QueryExtractionAllowedTestCase kTestCases[] = {
738 {"http://foo.com/instant?strk", false, "HTTP URL"},
739 {"https://foo.com/instant?strk", true, "Valid URL"},
740 {"https://foo.com/instant?", false,
741 "No search terms replacement key"},
742 {"https://foo.com/alt#quux=foo", false,
743 "No search terms replacement key"},
744 {"https://foo.com/alt#quux=foo&strk", true, "Valid search url"}
747 for (size_t i = 0; i < arraysize(kTestCases); ++i) {
748 const QueryExtractionAllowedTestCase& test = kTestCases[i];
749 EXPECT_EQ(test.expected_result,
750 chrome::IsQueryExtractionAllowedForURL(profile(), GURL(test.url)))
751 << test.url << " " << test.comment;
755 class SearchURLTest : public SearchTest {
757 virtual void SetSearchProvider(bool set_ntp_url, bool insecure_ntp_url)
759 TemplateURLService* template_url_service =
760 TemplateURLServiceFactory::GetForProfile(profile());
761 TemplateURLData data;
762 data.SetURL("{google:baseURL}search?"
763 "{google:instantExtendedEnabledParameter}q={searchTerms}");
764 data.search_terms_replacement_key = "espv";
765 template_url_ = new TemplateURL(data);
766 // |template_url_service| takes ownership of |template_url_|.
767 template_url_service->Add(template_url_);
768 template_url_service->SetUserSelectedDefaultSearchProvider(template_url_);
771 TemplateURL* template_url_;
774 TEST_F(SearchURLTest, QueryExtractionEnabled) {
775 UIThreadSearchTermsData::SetGoogleBaseURL("http://www.google.com/");
776 EnableQueryExtractionForTesting();
777 EXPECT_TRUE(IsQueryExtractionEnabled());
778 TemplateURLRef::SearchTermsArgs search_terms_args(base::ASCIIToUTF16("foo"));
779 GURL result(template_url_->url_ref().ReplaceSearchTerms(
780 search_terms_args, UIThreadSearchTermsData(profile())));
781 ASSERT_TRUE(result.is_valid());
782 // Query extraction is enabled. Make sure
783 // {google:instantExtendedEnabledParameter} is set in the search URL.
784 EXPECT_EQ("http://www.google.com/search?espv=2&q=foo", result.spec());
787 TEST_F(SearchURLTest, QueryExtractionDisabled) {
788 UIThreadSearchTermsData::SetGoogleBaseURL("http://www.google.com/");
789 EXPECT_FALSE(IsQueryExtractionEnabled());
790 TemplateURLRef::SearchTermsArgs search_terms_args(base::ASCIIToUTF16("foo"));
791 GURL result(template_url_->url_ref().ReplaceSearchTerms(
792 search_terms_args, UIThreadSearchTermsData(profile())));
793 ASSERT_TRUE(result.is_valid());
794 // Query extraction is disabled. Make sure
795 // {google:instantExtendedEnabledParameter} is not set in the search URL.
796 EXPECT_EQ("http://www.google.com/search?q=foo", result.spec());
799 typedef SearchTest InstantExtendedEnabledParamTest;
801 TEST_F(InstantExtendedEnabledParamTest, QueryExtractionDisabled) {
802 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
804 // Make sure InstantExtendedEnabledParam() returns an empty string for search
807 // Query extraction is always enabled on mobile.
808 EXPECT_TRUE(IsQueryExtractionEnabled());
809 EXPECT_EQ("espv=12&", InstantExtendedEnabledParam(true));
811 EXPECT_FALSE(IsQueryExtractionEnabled());
812 EXPECT_EQ("", InstantExtendedEnabledParam(true));
814 EXPECT_EQ("espv=12&", InstantExtendedEnabledParam(false));
817 TEST_F(InstantExtendedEnabledParamTest, QueryExtractionEnabled) {
818 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
819 "EmbeddedSearch", "Group1 espv:10 query_extraction:1"));
820 EXPECT_TRUE(IsQueryExtractionEnabled());
821 // Make sure InstantExtendedEnabledParam() returns a non-empty param string
822 // for search requests.
823 EXPECT_EQ("espv=10&", InstantExtendedEnabledParam(true));
824 EXPECT_EQ("espv=10&", InstantExtendedEnabledParam(false));
827 TEST_F(InstantExtendedEnabledParamTest, UseDefaultEmbeddedSearchPageVersion) {
828 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
829 "EmbeddedSearch", "Group1 espv:-1 query_extraction:1"));
830 EXPECT_TRUE(IsQueryExtractionEnabled());
832 EXPECT_EQ("espv=1&", InstantExtendedEnabledParam(true));
833 EXPECT_EQ("espv=1&", InstantExtendedEnabledParam(false));
835 EXPECT_EQ("espv=2&", InstantExtendedEnabledParam(true));
836 EXPECT_EQ("espv=2&", InstantExtendedEnabledParam(false));
840 typedef SearchTest IsQueryExtractionEnabledTest;
842 TEST_F(IsQueryExtractionEnabledTest, NotSet) {
843 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
844 "EmbeddedSearch", "Group1 espv:2"));
845 EXPECT_TRUE(IsInstantExtendedAPIEnabled());
846 EXPECT_FALSE(IsQueryExtractionEnabled());
847 EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
850 TEST_F(IsQueryExtractionEnabledTest, EnabledViaFieldTrial) {
851 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
852 "EmbeddedSearch", "Group1 espv:2 query_extraction:1"));
853 EXPECT_TRUE(IsInstantExtendedAPIEnabled());
854 EXPECT_TRUE(IsQueryExtractionEnabled());
855 EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
858 TEST_F(IsQueryExtractionEnabledTest, DisabledViaFieldTrial) {
859 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
860 "EmbeddedSearch", "Group1 espv:2 query_extraction:0"));
861 EXPECT_TRUE(IsInstantExtendedAPIEnabled());
862 EXPECT_FALSE(IsQueryExtractionEnabled());
863 EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
866 TEST_F(IsQueryExtractionEnabledTest, EnabledViaCommandLine) {
867 EnableQueryExtractionForTesting();
868 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
869 "EmbeddedSearch", "Group1 espv:2 query_extraction:0"));
870 EXPECT_TRUE(IsInstantExtendedAPIEnabled());
871 EXPECT_TRUE(IsQueryExtractionEnabled());
872 EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
875 typedef SearchTest DisplaySearchButtonTest;
877 TEST_F(DisplaySearchButtonTest, NotSet) {
878 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
879 "EmbeddedSearch", "Group1 espv:2"));
880 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions());
883 TEST_F(DisplaySearchButtonTest, Never) {
884 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
885 "EmbeddedSearch", "Group1 espv:2 display_search_button:0"));
886 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions());
889 TEST_F(DisplaySearchButtonTest, CommandLineNever) {
890 CommandLine::ForCurrentProcess()->AppendSwitch(
891 switches::kDisableSearchButtonInOmnibox);
892 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions());
894 // Command-line disable should override the field trial.
895 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
896 "EmbeddedSearch", "Group1 espv:2 display_search_button:1"));
897 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions());
900 TEST_F(DisplaySearchButtonTest, ForSearchTermReplacement) {
901 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
902 "EmbeddedSearch", "Group1 espv:2 display_search_button:1"));
903 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_FOR_STR, GetDisplaySearchButtonConditions());
906 TEST_F(DisplaySearchButtonTest, CommandLineForSearchTermReplacement) {
907 CommandLine::ForCurrentProcess()->AppendSwitch(
908 switches::kEnableSearchButtonInOmniboxForStr);
909 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_FOR_STR, GetDisplaySearchButtonConditions());
912 TEST_F(DisplaySearchButtonTest, ForSearchTermReplacementOrInputInProgress) {
913 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
914 "EmbeddedSearch", "Group1 espv:2 display_search_button:2"));
915 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_FOR_STR_OR_IIP,
916 GetDisplaySearchButtonConditions());
919 TEST_F(DisplaySearchButtonTest,
920 CommandLineForSearchTermReplacementOrInputInProgress) {
921 CommandLine::ForCurrentProcess()->AppendSwitch(
922 switches::kEnableSearchButtonInOmniboxForStrOrIip);
923 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_FOR_STR_OR_IIP,
924 GetDisplaySearchButtonConditions());
927 TEST_F(DisplaySearchButtonTest, Always) {
928 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
929 "EmbeddedSearch", "Group1 espv:2 display_search_button:3"));
930 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_ALWAYS, GetDisplaySearchButtonConditions());
933 TEST_F(DisplaySearchButtonTest, CommandLineAlways) {
934 CommandLine::ForCurrentProcess()->AppendSwitch(
935 switches::kEnableSearchButtonInOmniboxAlways);
936 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_ALWAYS, GetDisplaySearchButtonConditions());
939 TEST_F(DisplaySearchButtonTest, InvalidValue) {
940 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
941 "EmbeddedSearch", "Group1 espv:2 display_search_button:4"));
942 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions());
945 typedef SearchTest OriginChipTest;
947 TEST_F(OriginChipTest, NotSet) {
948 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
949 "EmbeddedSearch", "Group1 espv:2"));
950 EXPECT_FALSE(ShouldDisplayOriginChip());
951 EXPECT_EQ(ORIGIN_CHIP_DISABLED, GetOriginChipCondition());
954 TEST_F(OriginChipTest, Disabled) {
955 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
956 "EmbeddedSearch", "Group1 espv:2 origin_chip:0"));
957 EXPECT_FALSE(ShouldDisplayOriginChip());
958 EXPECT_EQ(ORIGIN_CHIP_DISABLED, GetOriginChipCondition());
961 TEST_F(OriginChipTest, Always) {
962 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
963 "EmbeddedSearch", "Group1 espv:2 origin_chip:1"));
964 EXPECT_TRUE(ShouldDisplayOriginChip());
965 EXPECT_EQ(ORIGIN_CHIP_ALWAYS, GetOriginChipCondition());
968 TEST_F(OriginChipTest, OnSrp) {
969 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
970 "EmbeddedSearch", "Group1 espv:2 origin_chip:2"));
971 EXPECT_TRUE(ShouldDisplayOriginChip());
972 EXPECT_EQ(ORIGIN_CHIP_ON_SRP, GetOriginChipCondition());
975 TEST_F(OriginChipTest, InvalidValue) {
976 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
977 "EmbeddedSearch", "Group1 espv:2 origin_chip:3"));
978 EXPECT_FALSE(ShouldDisplayOriginChip());
979 EXPECT_EQ(ORIGIN_CHIP_DISABLED, GetOriginChipCondition());
982 TEST_F(OriginChipTest, CommandLineDisabled) {
983 CommandLine::ForCurrentProcess()->AppendSwitch(
984 switches::kDisableOriginChip);
985 EXPECT_FALSE(ShouldDisplayOriginChip());
986 EXPECT_EQ(ORIGIN_CHIP_DISABLED, GetOriginChipCondition());
988 // Command-line disable should override the field trial.
989 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
990 "EmbeddedSearch", "Group1 espv:2 origin_chip:1"));
991 EXPECT_FALSE(ShouldDisplayOriginChip());
992 EXPECT_EQ(ORIGIN_CHIP_DISABLED, GetOriginChipCondition());
995 TEST_F(OriginChipTest, CommandLineAlways) {
996 CommandLine::ForCurrentProcess()->AppendSwitch(
997 switches::kEnableOriginChipAlways);
998 EXPECT_TRUE(ShouldDisplayOriginChip());
999 EXPECT_EQ(ORIGIN_CHIP_ALWAYS, GetOriginChipCondition());
1002 TEST_F(OriginChipTest, CommandLineOnSrp) {
1003 CommandLine::ForCurrentProcess()->AppendSwitch(
1004 switches::kEnableOriginChipOnSrp);
1005 EXPECT_TRUE(ShouldDisplayOriginChip());
1006 EXPECT_EQ(ORIGIN_CHIP_ON_SRP, GetOriginChipCondition());
1009 } // namespace chrome