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/metrics/statistics_recorder.h"
10 #include "base/prefs/pref_service.h"
11 #include "chrome/browser/managed_mode/managed_mode_url_filter.h"
12 #include "chrome/browser/managed_mode/managed_user_service.h"
13 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
14 #include "chrome/browser/search/instant_service.h"
15 #include "chrome/browser/search/instant_service_factory.h"
16 #include "chrome/browser/search/search.h"
17 #include "chrome/browser/search_engines/search_terms_data.h"
18 #include "chrome/browser/search_engines/template_url_service.h"
19 #include "chrome/browser/search_engines/template_url_service_factory.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/common/url_constants.h"
24 #include "chrome/test/base/browser_with_test_window_test.h"
25 #include "chrome/test/base/ui_test_utils.h"
26 #include "components/variations/entropy_provider.h"
27 #include "content/public/browser/render_process_host.h"
28 #include "content/public/browser/render_view_host.h"
29 #include "content/public/browser/site_instance.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/common/renderer_preferences.h"
36 class EmbeddedSearchFieldTrialTest : public testing::Test {
38 virtual void SetUp() {
39 field_trial_list_.reset(new base::FieldTrialList(
40 new metrics::SHA1EntropyProvider("42")));
41 base::StatisticsRecorder::Initialize();
42 ResetInstantExtendedOptInStateGateForTest();
46 scoped_ptr<base::FieldTrialList> field_trial_list_;
49 TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoEmptyAndValid) {
50 FieldTrialFlags flags;
51 uint64 group_number = 0;
53 EXPECT_TRUE(GetFieldTrialInfo(&flags, &group_number));
54 EXPECT_EQ(0ul, group_number);
55 EXPECT_EQ(0ul, flags.size());
57 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
58 "InstantExtended", "Group77"));
59 EXPECT_TRUE(GetFieldTrialInfo(&flags, &group_number));
60 EXPECT_EQ(77ul, group_number);
61 EXPECT_EQ(0ul, flags.size());
64 TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoInvalidNumber) {
65 FieldTrialFlags flags;
66 uint64 group_number = 0;
68 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
69 "InstantExtended", "Group77.2"));
70 EXPECT_FALSE(GetFieldTrialInfo(&flags, &group_number));
71 EXPECT_EQ(0ul, group_number);
72 EXPECT_EQ(0ul, flags.size());
75 TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoInvalidName) {
76 FieldTrialFlags flags;
77 uint64 group_number = 0;
79 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
80 "InstantExtended", "Invalid77"));
81 EXPECT_TRUE(GetFieldTrialInfo(&flags, &group_number));
82 EXPECT_EQ(0ul, group_number);
83 EXPECT_EQ(0ul, flags.size());
86 TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoValidGroup) {
87 FieldTrialFlags flags;
88 uint64 group_number = 0;
90 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
91 "InstantExtended", "Group77"));
92 EXPECT_TRUE(GetFieldTrialInfo(&flags, &group_number));
93 EXPECT_EQ(77ul, group_number);
94 EXPECT_EQ(0ul, flags.size());
97 TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoValidFlag) {
98 FieldTrialFlags flags;
99 uint64 group_number = 0;
101 EXPECT_EQ(9999ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags));
102 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
103 "InstantExtended", "Group77 foo:6"));
104 EXPECT_TRUE(GetFieldTrialInfo(&flags, &group_number));
105 EXPECT_EQ(77ul, group_number);
106 EXPECT_EQ(1ul, flags.size());
107 EXPECT_EQ(6ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags));
110 TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoNewName) {
111 FieldTrialFlags flags;
112 uint64 group_number = 0;
114 EXPECT_EQ(9999ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags));
115 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
116 "EmbeddedSearch", "Group77 foo:6"));
117 EXPECT_TRUE(GetFieldTrialInfo(&flags, &group_number));
118 EXPECT_EQ(77ul, group_number);
119 EXPECT_EQ(1ul, flags.size());
120 EXPECT_EQ(6ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags));
123 TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoNewNameOverridesOld) {
124 FieldTrialFlags flags;
125 uint64 group_number = 0;
127 EXPECT_EQ(9999ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags));
128 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
129 "EmbeddedSearch", "Group77 foo:6"));
130 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
131 "InstantExtended", "Group78 foo:5"));
132 EXPECT_TRUE(GetFieldTrialInfo(&flags, &group_number));
133 EXPECT_EQ(77ul, group_number);
134 EXPECT_EQ(1ul, flags.size());
135 EXPECT_EQ(6ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags));
138 TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoLotsOfFlags) {
139 FieldTrialFlags flags;
140 uint64 group_number = 0;
142 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
143 "InstantExtended", "Group77 bar:1 baz:7 cat:dogs"));
144 EXPECT_TRUE(GetFieldTrialInfo(&flags, &group_number));
145 EXPECT_EQ(77ul, group_number);
146 EXPECT_EQ(3ul, flags.size());
147 EXPECT_EQ(true, GetBoolValueForFlagWithDefault("bar", false, flags));
148 EXPECT_EQ(7ul, GetUInt64ValueForFlagWithDefault("baz", 0, flags));
150 GetStringValueForFlagWithDefault("cat", std::string(), flags));
152 GetStringValueForFlagWithDefault("moose", "default", flags));
155 TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoDisabled) {
156 FieldTrialFlags flags;
157 uint64 group_number = 0;
159 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
160 "InstantExtended", "Group77 bar:1 baz:7 cat:dogs DISABLED"));
161 EXPECT_FALSE(GetFieldTrialInfo(&flags, &group_number));
162 EXPECT_EQ(0ul, group_number);
163 EXPECT_EQ(0ul, flags.size());
166 TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoControlFlags) {
167 FieldTrialFlags flags;
168 uint64 group_number = 0;
170 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
171 "InstantExtended", "Control77 bar:1 baz:7 cat:dogs"));
172 EXPECT_TRUE(GetFieldTrialInfo(&flags, &group_number));
173 EXPECT_EQ(0ul, group_number);
174 EXPECT_EQ(3ul, flags.size());
177 class InstantExtendedAPIEnabledTest : public testing::Test {
179 InstantExtendedAPIEnabledTest() : histogram_(NULL) {
182 virtual void SetUp() {
183 field_trial_list_.reset(new base::FieldTrialList(
184 new metrics::SHA1EntropyProvider("42")));
185 base::StatisticsRecorder::Initialize();
186 ResetInstantExtendedOptInStateGateForTest();
187 previous_metrics_count_.resize(INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT, 0);
188 base::HistogramBase* histogram = GetHistogram();
190 scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
192 for (int state = INSTANT_EXTENDED_NOT_SET;
193 state < INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT; ++state) {
194 previous_metrics_count_[state] = samples->GetCount(state);
200 virtual CommandLine* GetCommandLine() const {
201 return CommandLine::ForCurrentProcess();
204 void ValidateMetrics(base::HistogramBase::Sample value) {
205 base::HistogramBase* histogram = GetHistogram();
207 scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
209 for (int state = INSTANT_EXTENDED_NOT_SET;
210 state < INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT; ++state) {
211 if (state == value) {
212 EXPECT_EQ(previous_metrics_count_[state] + 1,
213 samples->GetCount(state));
215 EXPECT_EQ(previous_metrics_count_[state], samples->GetCount(state));
223 base::HistogramBase* GetHistogram() {
225 histogram_ = base::StatisticsRecorder::FindHistogram(
226 "InstantExtended.OptInState");
230 base::HistogramBase* histogram_;
231 scoped_ptr<base::FieldTrialList> field_trial_list_;
232 std::vector<int> previous_metrics_count_;
235 TEST_F(InstantExtendedAPIEnabledTest, EnabledViaCommandLineFlag) {
236 GetCommandLine()->AppendSwitch(switches::kEnableInstantExtendedAPI);
237 EXPECT_TRUE(IsInstantExtendedAPIEnabled());
238 #if defined(OS_IOS) || defined(OS_ANDROID)
239 EXPECT_EQ(1ul, EmbeddedSearchPageVersion());
241 EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
243 ValidateMetrics(INSTANT_EXTENDED_OPT_IN);
246 TEST_F(InstantExtendedAPIEnabledTest, EnabledViaFinchFlag) {
247 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
249 EXPECT_TRUE(IsInstantExtendedAPIEnabled());
250 EXPECT_EQ(42ul, EmbeddedSearchPageVersion());
251 ValidateMetrics(INSTANT_EXTENDED_NOT_SET);
254 TEST_F(InstantExtendedAPIEnabledTest, DisabledViaCommandLineFlag) {
255 GetCommandLine()->AppendSwitch(switches::kDisableInstantExtendedAPI);
256 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
258 EXPECT_FALSE(IsInstantExtendedAPIEnabled());
259 EXPECT_EQ(0ul, EmbeddedSearchPageVersion());
260 ValidateMetrics(INSTANT_EXTENDED_OPT_OUT);
263 typedef InstantExtendedAPIEnabledTest ShouldHideTopVerbatimTest;
265 TEST_F(ShouldHideTopVerbatimTest, DoNotHideByDefault) {
266 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
267 "InstantExtended", "Control"));
268 EXPECT_FALSE(ShouldHideTopVerbatimMatch());
271 TEST_F(ShouldHideTopVerbatimTest, DoNotHideInInstantExtended) {
272 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
273 "InstantExtended", "Group1"));
274 EXPECT_FALSE(ShouldHideTopVerbatimMatch());
277 TEST_F(ShouldHideTopVerbatimTest, EnableByFlagInInstantExtended) {
278 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
279 "InstantExtended", "Group1 hide_verbatim:1"));
280 EXPECT_TRUE(ShouldHideTopVerbatimMatch());
283 TEST_F(ShouldHideTopVerbatimTest, EnableByFlagOutsideInstantExtended) {
284 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
285 "InstantExtended", "Controll1 hide_verbatim:1"));
286 EXPECT_TRUE(ShouldHideTopVerbatimMatch());
289 TEST_F(ShouldHideTopVerbatimTest, DisableByFlag) {
290 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
291 "InstantExtended", "Group1 hide_verbatim:0"));
292 EXPECT_FALSE(ShouldHideTopVerbatimMatch());
295 typedef InstantExtendedAPIEnabledTest ShouldSuppressInstantExtendedOnSRPTest;
297 TEST_F(ShouldSuppressInstantExtendedOnSRPTest, NotSet) {
298 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
299 "InstantExtended", "Group1 espv:2"));
300 EXPECT_FALSE(ShouldSuppressInstantExtendedOnSRP());
301 EXPECT_TRUE(IsInstantExtendedAPIEnabled());
302 EXPECT_TRUE(IsQueryExtractionEnabled());
303 EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
306 TEST_F(ShouldSuppressInstantExtendedOnSRPTest, NotSuppressOnSRP) {
307 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
308 "InstantExtended", "Group1 espv:2 suppress_on_srp:0"));
309 EXPECT_FALSE(ShouldSuppressInstantExtendedOnSRP());
310 EXPECT_TRUE(IsInstantExtendedAPIEnabled());
311 EXPECT_TRUE(IsQueryExtractionEnabled());
312 EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
315 TEST_F(ShouldSuppressInstantExtendedOnSRPTest, SuppressOnSRP) {
316 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
317 "InstantExtended", "Group1 espv:2 suppress_on_srp:1"));
318 EXPECT_TRUE(ShouldSuppressInstantExtendedOnSRP());
319 EXPECT_TRUE(IsInstantExtendedAPIEnabled());
320 EXPECT_FALSE(IsQueryExtractionEnabled());
321 EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
324 class SearchTest : public BrowserWithTestWindowTest {
326 virtual void SetUp() OVERRIDE {
327 BrowserWithTestWindowTest::SetUp();
328 field_trial_list_.reset(new base::FieldTrialList(
329 new metrics::SHA1EntropyProvider("42")));
330 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
331 profile(), &TemplateURLServiceFactory::BuildInstanceFor);
332 TemplateURLService* template_url_service =
333 TemplateURLServiceFactory::GetForProfile(profile());
334 ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
335 SetSearchProvider(true, false);
338 void SetSearchProvider(bool set_ntp_url, bool insecure_ntp_url) {
339 TemplateURLService* template_url_service =
340 TemplateURLServiceFactory::GetForProfile(profile());
341 TemplateURLData data;
342 data.SetURL("http://foo.com/url?bar={searchTerms}");
343 data.instant_url = "http://foo.com/instant?"
344 "{google:omniboxStartMarginParameter}{google:forceInstantResults}"
345 "foo=foo#foo=foo&strk";
347 data.new_tab_url = (insecure_ntp_url ? "http" : "https") +
348 std::string("://foo.com/newtab?strk");
350 data.alternate_urls.push_back("http://foo.com/alt#quux={searchTerms}");
351 data.search_terms_replacement_key = "strk";
353 TemplateURL* template_url = new TemplateURL(profile(), data);
354 // Takes ownership of |template_url|.
355 template_url_service->Add(template_url);
356 template_url_service->SetDefaultSearchProvider(template_url);
359 // Build an Instant URL with or without a valid search terms replacement key
360 // as per |has_search_term_replacement_key|. Set that URL as the instant URL
361 // for the default search provider.
362 void SetDefaultInstantTemplateUrl(bool has_search_term_replacement_key) {
363 TemplateURLService* template_url_service =
364 TemplateURLServiceFactory::GetForProfile(profile());
366 static const char kInstantURLWithStrk[] =
367 "http://foo.com/instant?foo=foo#foo=foo&strk";
368 static const char kInstantURLNoStrk[] =
369 "http://foo.com/instant?foo=foo#foo=foo";
371 TemplateURLData data;
372 data.SetURL("http://foo.com/url?bar={searchTerms}");
373 data.instant_url = (has_search_term_replacement_key ?
374 kInstantURLWithStrk : kInstantURLNoStrk);
375 data.search_terms_replacement_key = "strk";
377 TemplateURL* template_url = new TemplateURL(profile(), data);
378 // Takes ownership of |template_url|.
379 template_url_service->Add(template_url);
380 template_url_service->SetDefaultSearchProvider(template_url);
383 bool InInstantProcess(const content::WebContents* contents) {
384 InstantService* instant_service =
385 InstantServiceFactory::GetForProfile(profile());
386 return instant_service->IsInstantProcess(
387 contents->GetRenderProcessHost()->GetID());
390 scoped_ptr<base::FieldTrialList> field_trial_list_;
393 struct SearchTestCase {
395 bool expected_result;
399 TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedDisabled) {
400 DisableInstantExtendedAPIForTesting();
402 const SearchTestCase kTestCases[] = {
403 {"chrome-search://foo/bar", false, ""},
404 {"http://foo.com/instant", false, ""},
405 {"http://foo.com/instant?foo=bar", false, ""},
406 {"https://foo.com/instant", false, ""},
407 {"https://foo.com/instant#foo=bar", false, ""},
408 {"HtTpS://fOo.CoM/instant", false, ""},
409 {"http://foo.com:80/instant", false, ""},
410 {"invalid URL", false, "Invalid URL"},
411 {"unknown://scheme/path", false, "Unknown scheme"},
412 {"ftp://foo.com/instant", false, "Non-HTTP scheme"},
413 {"http://sub.foo.com/instant", false, "Non-exact host"},
414 {"http://foo.com:26/instant", false, "Non-default port"},
415 {"http://foo.com/instant/bar", false, "Non-exact path"},
416 {"http://foo.com/Instant", false, "Case sensitive path"},
417 {"http://foo.com/", false, "Non-exact path"},
418 {"https://foo.com/", false, "Non-exact path"},
419 {"https://foo.com/url?strk", false, "Non-extended mode"},
420 {"https://foo.com/alt?strk", false, "Non-extended mode"},
423 for (size_t i = 0; i < arraysize(kTestCases); ++i) {
424 const SearchTestCase& test = kTestCases[i];
425 EXPECT_EQ(test.expected_result,
426 ShouldAssignURLToInstantRenderer(GURL(test.url), profile()))
427 << test.url << " " << test.comment;
431 TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedEnabled) {
432 EnableInstantExtendedAPIForTesting();
434 const SearchTestCase kTestCases[] = {
435 {chrome::kChromeSearchLocalNtpUrl, true, ""},
436 {"https://foo.com/instant?strk", true, ""},
437 {"https://foo.com/instant#strk", true, ""},
438 {"https://foo.com/instant?strk=0", true, ""},
439 {"https://foo.com/url?strk", true, ""},
440 {"https://foo.com/alt?strk", true, ""},
441 {"http://foo.com/instant", false, "Non-HTTPS"},
442 {"http://foo.com/instant?strk", false, "Non-HTTPS"},
443 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"},
444 {"https://foo.com/instant", false, "No search terms replacement"},
445 {"https://foo.com/?strk", false, "Non-exact path"},
448 for (size_t i = 0; i < arraysize(kTestCases); ++i) {
449 const SearchTestCase& test = kTestCases[i];
450 EXPECT_EQ(test.expected_result,
451 ShouldAssignURLToInstantRenderer(GURL(test.url), profile()))
452 << test.url << " " << test.comment;
456 TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedEnabledNotOnSRP) {
457 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
458 "InstantExtended", "Group1 espv:2 suppress_on_srp:1"));
460 const SearchTestCase kTestCases[] = {
461 {chrome::kChromeSearchLocalNtpUrl, true, ""},
462 {"https://foo.com/instant?strk", true, ""},
463 {"https://foo.com/instant#strk", true, ""},
464 {"https://foo.com/instant?strk=0", true, ""},
465 {"https://foo.com/url?strk", false, "Disabled on SRP"},
466 {"https://foo.com/alt?strk", false, "Disabled ON SRP"},
467 {"http://foo.com/instant", false, "Non-HTTPS"},
468 {"http://foo.com/instant?strk", false, "Non-HTTPS"},
469 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"},
470 {"https://foo.com/instant", false, "No search terms replacement"},
471 {"https://foo.com/?strk", false, "Non-exact path"},
474 for (size_t i = 0; i < arraysize(kTestCases); ++i) {
475 const SearchTestCase& test = kTestCases[i];
476 EXPECT_EQ(test.expected_result,
477 ShouldAssignURLToInstantRenderer(GURL(test.url), profile()))
478 << test.url << " " << test.comment;
482 TEST_F(SearchTest, ShouldUseProcessPerSiteForInstantURL) {
483 EnableInstantExtendedAPIForTesting();
485 const SearchTestCase kTestCases[] = {
486 {"chrome-search://local-ntp", true, "Local NTP"},
487 {"chrome-search://online-ntp", true, "Online NTP"},
488 {"invalid-scheme://local-ntp", false, "Invalid Local NTP URL"},
489 {"invalid-scheme://online-ntp", false, "Invalid Online NTP URL"},
490 {"chrome-search://foo.com", false, "Search result page"},
491 {"https://foo.com/instant?strk", false, ""},
492 {"https://foo.com/instant#strk", false, ""},
493 {"https://foo.com/instant?strk=0", false, ""},
494 {"https://foo.com/url?strk", false, ""},
495 {"https://foo.com/alt?strk", false, ""},
496 {"http://foo.com/instant", false, "Non-HTTPS"},
497 {"http://foo.com/instant?strk", false, "Non-HTTPS"},
498 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"},
499 {"https://foo.com/instant", false, "No search terms replacement"},
500 {"https://foo.com/?strk", false, "Non-exact path"},
503 for (size_t i = 0; i < arraysize(kTestCases); ++i) {
504 const SearchTestCase& test = kTestCases[i];
505 EXPECT_EQ(test.expected_result,
506 ShouldUseProcessPerSiteForInstantURL(GURL(test.url), profile()))
507 << test.url << " " << test.comment;
511 // Each test case represents a navigation to |start_url| followed by a
512 // navigation to |end_url|. We will check whether each navigation lands in an
513 // Instant process, and also whether the navigation from start to end re-uses
514 // the same SiteInstance (and hence the same RenderViewHost, etc.).
515 const struct ProcessIsolationTestCase {
516 const char* description;
517 const char* start_url;
518 bool start_in_instant_process;
520 bool end_in_instant_process;
521 bool same_site_instance;
522 } kProcessIsolationTestCases[] = {
524 "chrome-search://local-ntp", true,
525 "https://foo.com/url?strk", true, false },
526 {"Local NTP -> Regular",
527 "chrome-search://local-ntp", true,
528 "https://foo.com/other", false, false },
529 {"Remote NTP -> SRP",
530 "https://foo.com/instant?strk", true,
531 "https://foo.com/url?strk", true, false },
532 {"Remote NTP -> Regular",
533 "https://foo.com/instant?strk", true,
534 "https://foo.com/other", false, false },
536 "https://foo.com/url?strk", true,
537 "https://foo.com/url?strk", true, true },
539 "https://foo.com/url?strk", true,
540 "https://foo.com/other", false, false },
542 "https://foo.com/other", false,
543 "https://foo.com/url?strk", true, false },
546 TEST_F(SearchTest, ProcessIsolation) {
547 EnableInstantExtendedAPIForTesting();
549 for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) {
550 const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i];
551 AddTab(browser(), GURL("chrome://blank"));
552 const content::WebContents* contents =
553 browser()->tab_strip_model()->GetActiveWebContents();
555 // Navigate to start URL.
556 NavigateAndCommitActiveTab(GURL(test.start_url));
557 EXPECT_EQ(test.start_in_instant_process, InInstantProcess(contents))
561 const scoped_refptr<content::SiteInstance> start_site_instance =
562 contents->GetSiteInstance();
563 const content::RenderProcessHost* start_rph =
564 contents->GetRenderProcessHost();
565 const content::RenderViewHost* start_rvh =
566 contents->GetRenderViewHost();
568 // Navigate to end URL.
569 NavigateAndCommitActiveTab(GURL(test.end_url));
570 EXPECT_EQ(test.end_in_instant_process, InInstantProcess(contents))
573 EXPECT_EQ(test.same_site_instance,
574 start_site_instance == contents->GetSiteInstance())
576 EXPECT_EQ(test.same_site_instance,
577 start_rvh == contents->GetRenderViewHost())
579 EXPECT_EQ(test.same_site_instance,
580 start_rph == contents->GetRenderProcessHost())
585 TEST_F(SearchTest, ProcessIsolation_RendererInitiated) {
586 EnableInstantExtendedAPIForTesting();
588 for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) {
589 const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i];
590 AddTab(browser(), GURL("chrome://blank"));
591 content::WebContents* contents =
592 browser()->tab_strip_model()->GetActiveWebContents();
594 // Navigate to start URL.
595 NavigateAndCommitActiveTab(GURL(test.start_url));
596 EXPECT_EQ(test.start_in_instant_process, InInstantProcess(contents))
600 const scoped_refptr<content::SiteInstance> start_site_instance =
601 contents->GetSiteInstance();
602 const content::RenderProcessHost* start_rph =
603 contents->GetRenderProcessHost();
604 const content::RenderViewHost* start_rvh =
605 contents->GetRenderViewHost();
607 // Navigate to end URL via a renderer-initiated navigation.
608 content::NavigationController* controller = &contents->GetController();
609 content::NavigationController::LoadURLParams load_params(
611 load_params.is_renderer_initiated = true;
612 load_params.transition_type = content::PAGE_TRANSITION_LINK;
614 controller->LoadURLWithParams(load_params);
615 CommitPendingLoad(controller);
616 EXPECT_EQ(test.end_in_instant_process, InInstantProcess(contents))
619 EXPECT_EQ(test.same_site_instance,
620 start_site_instance == contents->GetSiteInstance())
622 EXPECT_EQ(test.same_site_instance,
623 start_rvh == contents->GetRenderViewHost())
625 EXPECT_EQ(test.same_site_instance,
626 start_rph == contents->GetRenderProcessHost())
631 const SearchTestCase kInstantNTPTestCases[] = {
632 {"https://foo.com/instant?strk", true, "Valid Instant URL"},
633 {"https://foo.com/instant#strk", true, "Valid Instant URL"},
634 {"https://foo.com/url?strk", true, "Valid search URL"},
635 {"https://foo.com/url#strk", true, "Valid search URL"},
636 {"https://foo.com/alt?strk", true, "Valid alternative URL"},
637 {"https://foo.com/alt#strk", true, "Valid alternative URL"},
638 {"https://foo.com/url?strk&bar=", true, "No query terms"},
639 {"https://foo.com/url?strk&q=abc", true, "No query terms key"},
640 {"https://foo.com/url?strk#bar=abc", true, "Query terms key in ref"},
641 {"https://foo.com/url?strk&bar=abc", false, "Has query terms"},
642 {"http://foo.com/instant?strk=1", false, "Insecure URL"},
643 {"https://foo.com/instant", false, "No search term replacement"},
644 {"chrome://blank/", false, "Chrome scheme"},
645 {"chrome-search://foo", false, "Chrome-search scheme"},
646 {chrome::kChromeSearchLocalNtpUrl, true, "Local new tab page"},
647 {"https://bar.com/instant?strk=1", false, "Random non-search page"},
650 TEST_F(SearchTest, InstantNTPExtendedEnabled) {
651 EnableInstantExtendedAPIForTesting();
652 AddTab(browser(), GURL("chrome://blank"));
653 for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
654 const SearchTestCase& test = kInstantNTPTestCases[i];
655 NavigateAndCommitActiveTab(GURL(test.url));
656 const content::WebContents* contents =
657 browser()->tab_strip_model()->GetWebContentsAt(0);
658 EXPECT_EQ(test.expected_result, IsInstantNTP(contents))
659 << test.url << " " << test.comment;
663 TEST_F(SearchTest, InstantNTPExtendedDisabled) {
664 AddTab(browser(), GURL("chrome://blank"));
665 for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
666 const SearchTestCase& test = kInstantNTPTestCases[i];
667 NavigateAndCommitActiveTab(GURL(test.url));
668 const content::WebContents* contents =
669 browser()->tab_strip_model()->GetWebContentsAt(0);
670 EXPECT_FALSE(IsInstantNTP(contents)) << test.url << " " << test.comment;
674 TEST_F(SearchTest, InstantNTPCustomNavigationEntry) {
675 EnableInstantExtendedAPIForTesting();
676 AddTab(browser(), GURL("chrome://blank"));
677 for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
678 const SearchTestCase& test = kInstantNTPTestCases[i];
679 NavigateAndCommitActiveTab(GURL(test.url));
680 content::WebContents* contents =
681 browser()->tab_strip_model()->GetWebContentsAt(0);
682 content::NavigationController& controller = contents->GetController();
683 controller.SetTransientEntry(
684 controller.CreateNavigationEntry(GURL("chrome://blank"),
686 content::PAGE_TRANSITION_LINK,
689 contents->GetBrowserContext()));
690 // The active entry is chrome://blank and not an NTP.
691 EXPECT_FALSE(IsInstantNTP(contents));
692 EXPECT_EQ(test.expected_result,
693 NavEntryIsInstantNTP(contents,
694 controller.GetLastCommittedEntry()))
695 << test.url << " " << test.comment;
699 TEST_F(SearchTest, InstantCacheableNTPNavigationEntry) {
700 EnableInstantExtendedAPIForTesting();
701 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
702 "Group1 use_cacheable_ntp:1"));
704 AddTab(browser(), GURL("chrome://blank"));
705 content::WebContents* contents =
706 browser()->tab_strip_model()->GetWebContentsAt(0);
707 content::NavigationController& controller = contents->GetController();
709 NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl));
710 EXPECT_TRUE(NavEntryIsInstantNTP(contents,
711 controller.GetLastCommittedEntry()));
712 // Instant page is not cacheable NTP.
713 NavigateAndCommitActiveTab(GetInstantURL(profile(), kDisableStartMargin,
715 EXPECT_FALSE(NavEntryIsInstantNTP(contents,
716 controller.GetLastCommittedEntry()));
717 // Test Cacheable NTP
718 NavigateAndCommitActiveTab(chrome::GetNewTabPageURL(profile()));
719 EXPECT_TRUE(NavEntryIsInstantNTP(contents,
720 controller.GetLastCommittedEntry()));
723 TEST_F(SearchTest, UseLocalNTPInIncognito) {
724 EnableInstantExtendedAPIForTesting();
725 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
726 "Group1 use_cacheable_ntp:1"));
727 EXPECT_EQ(GURL(), chrome::GetNewTabPageURL(
728 profile()->GetOffTheRecordProfile()));
731 TEST_F(SearchTest, UseLocalNTPIfNTPURLIsInsecure) {
732 EnableInstantExtendedAPIForTesting();
733 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
734 "Group1 use_cacheable_ntp:1"));
735 // Set an insecure new tab page URL and verify that it's ignored.
736 SetSearchProvider(true, true);
737 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
738 chrome::GetNewTabPageURL(profile()));
741 TEST_F(SearchTest, UseLocalNTPIfNTPURLIsNotSet) {
742 EnableInstantExtendedAPIForTesting();
743 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
744 "Group1 use_cacheable_ntp:1"));
745 // Set an insecure new tab page URL and verify that it's ignored.
746 SetSearchProvider(false, true);
747 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
748 chrome::GetNewTabPageURL(profile()));
751 TEST_F(SearchTest, UseLocalNTPIfNTPURLIsBlockedForSupervisedUser) {
752 EnableInstantExtendedAPIForTesting();
753 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
754 "Group1 use_cacheable_ntp:1"));
756 // Block access to foo.com in the URL filter.
757 ManagedUserService* managed_user_service =
758 ManagedUserServiceFactory::GetForProfile(profile());
759 ManagedModeURLFilter* url_filter =
760 managed_user_service->GetURLFilterForUIThread();
761 std::map<std::string, bool> hosts;
762 hosts["foo.com"] = false;
763 url_filter->SetManualHosts(&hosts);
765 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
766 chrome::GetNewTabPageURL(profile()));
767 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false));
770 TEST_F(SearchTest, GetInstantURLExtendedEnabled) {
771 // Instant is disabled, so no Instant URL.
772 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false));
774 // Enable Instant. Still no Instant URL because "strk" is missing.
775 EnableInstantExtendedAPIForTesting();
776 SetDefaultInstantTemplateUrl(false);
777 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false));
779 // Set an Instant URL with a valid search terms replacement key.
780 SetDefaultInstantTemplateUrl(true);
782 // Now there should be a valid Instant URL. Note the HTTPS "upgrade".
783 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
784 GetInstantURL(profile(), kDisableStartMargin, false));
786 // Enable suggest. No difference.
787 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
788 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
789 GetInstantURL(profile(), kDisableStartMargin, false));
791 // Disable suggest. No Instant URL.
792 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
793 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false));
796 TEST_F(SearchTest, StartMarginCGI) {
797 // Instant is disabled, so no Instant URL.
798 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false));
800 // Enable Instant. No margin.
801 EnableInstantExtendedAPIForTesting();
802 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
804 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
805 GetInstantURL(profile(), kDisableStartMargin, false));
807 // With start margin.
808 EXPECT_EQ(GURL("https://foo.com/instant?es_sm=10&foo=foo#foo=foo&strk"),
809 GetInstantURL(profile(), 10, false));
812 TEST_F(SearchTest, InstantSearchEnabledCGI) {
813 EnableInstantExtendedAPIForTesting();
815 // Disable Instant Search.
816 // Make sure {google:forceInstantResults} is not set in the Instant URL.
817 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
818 GetInstantURL(profile(), kDisableStartMargin, false));
820 // Enable Instant Search.
821 // Make sure {google:forceInstantResults} is set in the Instant URL.
822 EXPECT_EQ(GURL("https://foo.com/instant?ion=1&foo=foo#foo=foo&strk"),
823 GetInstantURL(profile(), kDisableStartMargin, true));
826 TEST_F(SearchTest, CommandLineOverrides) {
827 EnableInstantExtendedAPIForTesting();
829 GURL local_instant_url(GetLocalInstantURL(profile()));
830 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url);
832 TemplateURLService* template_url_service =
833 TemplateURLServiceFactory::GetForProfile(profile());
834 TemplateURLData data;
835 data.SetURL("{google:baseURL}search?q={searchTerms}");
836 data.instant_url = "{google:baseURL}webhp?strk";
837 data.search_terms_replacement_key = "strk";
838 TemplateURL* template_url = new TemplateURL(profile(), data);
839 // Takes ownership of |template_url|.
840 template_url_service->Add(template_url);
841 template_url_service->SetDefaultSearchProvider(template_url);
843 // By default, Instant Extended forces the instant URL to be HTTPS, so even if
844 // we set a Google base URL that is HTTP, we should get an HTTPS URL.
845 UIThreadSearchTermsData::SetGoogleBaseURL("http://www.foo.com/");
846 GURL instant_url(GetInstantURL(profile(), kDisableStartMargin, false));
847 ASSERT_TRUE(instant_url.is_valid());
848 EXPECT_EQ("https://www.foo.com/webhp?strk", instant_url.spec());
850 // However, if the Google base URL is specified on the command line, the
851 // instant URL should just use it, even if it's HTTP.
852 UIThreadSearchTermsData::SetGoogleBaseURL(std::string());
853 CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
854 "http://www.bar.com/");
855 instant_url = GetInstantURL(profile(), kDisableStartMargin, false);
856 ASSERT_TRUE(instant_url.is_valid());
857 EXPECT_EQ("http://www.bar.com/webhp?strk", instant_url.spec());
859 // Similarly, setting a Google base URL on the command line should allow you
860 // to get the Google version of the local NTP, even though search provider's
861 // URL doesn't contain "google".
862 local_instant_url = GetLocalInstantURL(profile());
863 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url);
865 // If we specify extra search query params, they should be inserted into the
866 // query portion of the instant URL.
867 CommandLine::ForCurrentProcess()->AppendSwitchASCII(
868 switches::kExtraSearchQueryParams, "a=b");
869 instant_url = GetInstantURL(profile(), kDisableStartMargin, false);
870 ASSERT_TRUE(instant_url.is_valid());
871 EXPECT_EQ("http://www.bar.com/webhp?a=b&strk", instant_url.spec());
874 TEST_F(SearchTest, ShouldShowInstantNTP_Default) {
875 EnableInstantExtendedAPIForTesting();
876 EXPECT_TRUE(ShouldShowInstantNTP());
879 TEST_F(SearchTest, ShouldShowInstantNTP_DisabledViaFinch) {
880 EnableInstantExtendedAPIForTesting();
881 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
882 "Group1 show_ntp:0"));
883 EXPECT_FALSE(ShouldShowInstantNTP());
886 TEST_F(SearchTest, ShouldShowInstantNTP_DisabledByUseCacheableNTPFinchFlag) {
887 EnableInstantExtendedAPIForTesting();
888 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
889 "Group1 use_cacheable_ntp:1"));
890 EXPECT_FALSE(ShouldShowInstantNTP());
893 TEST_F(SearchTest, ShouldUseCacheableNTP_Default) {
894 EnableInstantExtendedAPIForTesting();
895 EXPECT_FALSE(ShouldUseCacheableNTP());
898 TEST_F(SearchTest, ShouldUseCacheableNTP_EnabledViaFinch) {
899 EnableInstantExtendedAPIForTesting();
900 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
901 "Group1 use_cacheable_ntp:1"));
902 EXPECT_TRUE(ShouldUseCacheableNTP());
905 TEST_F(SearchTest, ShouldUseCacheableNTP_EnabledViaCommandLine) {
906 EnableInstantExtendedAPIForTesting();
907 CommandLine::ForCurrentProcess()->
908 AppendSwitch(switches::kUseCacheableNewTabPage);
909 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
910 "Group1 use_cacheable_ntp:0"));
911 EXPECT_TRUE(ShouldUseCacheableNTP());
914 TEST_F(SearchTest, IsNTPURL) {
916 GURL ntp_url(chrome::kChromeUINewTabURL);
917 GURL local_ntp_url(GetLocalInstantURL(profile()));
919 EXPECT_FALSE(chrome::IsNTPURL(invalid_url, profile()));
920 EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, profile()));
922 EXPECT_TRUE(chrome::IsNTPURL(ntp_url, NULL));
923 EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, NULL));
925 // Enable Instant. No margin.
926 EnableInstantExtendedAPIForTesting();
927 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
928 GURL remote_ntp_url(GetInstantURL(profile(), kDisableStartMargin, false));
929 GURL search_url_with_search_terms("https://foo.com/url?strk&bar=abc");
930 GURL search_url_without_search_terms("https://foo.com/url?strk&bar");
932 EXPECT_FALSE(chrome::IsNTPURL(ntp_url, profile()));
933 EXPECT_TRUE(chrome::IsNTPURL(local_ntp_url, profile()));
934 EXPECT_TRUE(chrome::IsNTPURL(remote_ntp_url, profile()));
935 EXPECT_FALSE(chrome::IsNTPURL(search_url_with_search_terms, profile()));
936 EXPECT_TRUE(chrome::IsNTPURL(search_url_without_search_terms, profile()));
938 EXPECT_FALSE(chrome::IsNTPURL(ntp_url, NULL));
939 EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, NULL));
940 EXPECT_FALSE(chrome::IsNTPURL(remote_ntp_url, NULL));
941 EXPECT_FALSE(chrome::IsNTPURL(search_url_with_search_terms, NULL));
942 EXPECT_FALSE(chrome::IsNTPURL(search_url_without_search_terms, NULL));
945 TEST_F(SearchTest, GetSearchURLs) {
946 std::vector<GURL> search_urls = GetSearchURLs(profile());
947 EXPECT_EQ(2U, search_urls.size());
948 EXPECT_EQ("http://foo.com/alt#quux=", search_urls[0].spec());
949 EXPECT_EQ("http://foo.com/url?bar=", search_urls[1].spec());
952 } // namespace chrome