search_unittest.cc revision 2385ea399aae016c0806a4f9ef3c9cfe3d2a39df
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. 4 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/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/search_terms_data.h" 15#include "chrome/browser/search_engines/template_url_service.h" 16#include "chrome/browser/search_engines/template_url_service_factory.h" 17#include "chrome/browser/ui/tabs/tab_strip_model.h" 18#include "chrome/common/chrome_switches.h" 19#include "chrome/common/metrics/entropy_provider.h" 20#include "chrome/common/pref_names.h" 21#include "chrome/common/url_constants.h" 22#include "chrome/test/base/browser_with_test_window_test.h" 23#include "chrome/test/base/ui_test_utils.h" 24#include "content/public/browser/render_process_host.h" 25#include "content/public/browser/render_view_host.h" 26#include "content/public/browser/site_instance.h" 27#include "content/public/browser/web_contents.h" 28#include "content/public/common/renderer_preferences.h" 29 30namespace chrome { 31 32TEST(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoEmptyAndValid) { 33 FieldTrialFlags flags; 34 uint64 group_number = 0; 35 36 EXPECT_TRUE(GetFieldTrialInfo(std::string(), &flags, &group_number)); 37 EXPECT_EQ(0ul, group_number); 38 EXPECT_EQ(0ul, flags.size()); 39 40 EXPECT_TRUE(GetFieldTrialInfo("Group77", &flags, &group_number)); 41 EXPECT_EQ(77ul, group_number); 42 EXPECT_EQ(0ul, flags.size()); 43} 44 45TEST(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoInvalidThenValid) { 46 FieldTrialFlags flags; 47 uint64 group_number = 0; 48 49 EXPECT_FALSE(GetFieldTrialInfo("Group77.2", &flags, &group_number)); 50 EXPECT_EQ(0ul, group_number); 51 EXPECT_EQ(0ul, flags.size()); 52 53 EXPECT_TRUE(GetFieldTrialInfo("Invalid77", &flags, &group_number)); 54 EXPECT_EQ(0ul, group_number); 55 EXPECT_EQ(0ul, flags.size()); 56 57 EXPECT_TRUE(GetFieldTrialInfo("Group77 ", &flags, &group_number)); 58 EXPECT_EQ(77ul, group_number); 59 EXPECT_EQ(0ul, flags.size()); 60} 61 62TEST(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoValidFlag) { 63 FieldTrialFlags flags; 64 uint64 group_number = 0; 65 66 EXPECT_EQ(9999ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags)); 67 EXPECT_TRUE(GetFieldTrialInfo("Group77 foo:6", &flags, &group_number)); 68 EXPECT_EQ(77ul, group_number); 69 EXPECT_EQ(1ul, flags.size()); 70 EXPECT_EQ(6ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags)); 71} 72 73TEST(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoLotsOfFlags) { 74 FieldTrialFlags flags; 75 uint64 group_number = 0; 76 77 EXPECT_TRUE(GetFieldTrialInfo( 78 "Group77 bar:1 baz:7 cat:dogs", &flags, &group_number)); 79 EXPECT_EQ(77ul, group_number); 80 EXPECT_EQ(3ul, flags.size()); 81 EXPECT_EQ(true, GetBoolValueForFlagWithDefault("bar", false, flags)); 82 EXPECT_EQ(7ul, GetUInt64ValueForFlagWithDefault("baz", 0, flags)); 83 EXPECT_EQ("dogs", 84 GetStringValueForFlagWithDefault("cat", std::string(), flags)); 85 EXPECT_EQ("default", 86 GetStringValueForFlagWithDefault("moose", "default", flags)); 87} 88 89TEST(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoDisabled) { 90 FieldTrialFlags flags; 91 uint64 group_number = 0; 92 93 EXPECT_FALSE(GetFieldTrialInfo( 94 "Group77 bar:1 baz:7 cat:dogs DISABLED", &flags, &group_number)); 95 EXPECT_EQ(0ul, group_number); 96 EXPECT_EQ(0ul, flags.size()); 97} 98 99TEST(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoControlFlags) { 100 FieldTrialFlags flags; 101 uint64 group_number = 0; 102 103 EXPECT_TRUE(GetFieldTrialInfo( 104 "Control77 bar:1 baz:7 cat:dogs", &flags, &group_number)); 105 EXPECT_EQ(0ul, group_number); 106 EXPECT_EQ(3ul, flags.size()); 107} 108 109class InstantExtendedAPIEnabledTest : public testing::Test { 110 public: 111 InstantExtendedAPIEnabledTest() : histogram_(NULL) { 112 } 113 protected: 114 virtual void SetUp() { 115 field_trial_list_.reset(new base::FieldTrialList( 116 new metrics::SHA1EntropyProvider("42"))); 117 base::StatisticsRecorder::Initialize(); 118 ResetInstantExtendedOptInStateGateForTest(); 119 previous_metrics_count_.resize(INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT, 0); 120 base::HistogramBase* histogram = GetHistogram(); 121 if (histogram) { 122 scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples()); 123 if (samples.get()) { 124 for (int state = INSTANT_EXTENDED_NOT_SET; 125 state < INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT; ++state) { 126 previous_metrics_count_[state] = samples->GetCount(state); 127 } 128 } 129 } 130 } 131 132 virtual CommandLine* GetCommandLine() const { 133 return CommandLine::ForCurrentProcess(); 134 } 135 136 void ValidateMetrics(base::HistogramBase::Sample value) { 137 base::HistogramBase* histogram = GetHistogram(); 138 if (histogram) { 139 scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples()); 140 if (samples.get()) { 141 for (int state = INSTANT_EXTENDED_NOT_SET; 142 state < INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT; ++state) { 143 if (state == value) { 144 EXPECT_EQ(previous_metrics_count_[state] + 1, 145 samples->GetCount(state)); 146 } else { 147 EXPECT_EQ(previous_metrics_count_[state], samples->GetCount(state)); 148 } 149 } 150 } 151 } 152 } 153 154 private: 155 base::HistogramBase* GetHistogram() { 156 if (!histogram_) { 157 histogram_ = base::StatisticsRecorder::FindHistogram( 158 "InstantExtended.OptInState"); 159 } 160 return histogram_; 161 } 162 base::HistogramBase* histogram_; 163 scoped_ptr<base::FieldTrialList> field_trial_list_; 164 std::vector<int> previous_metrics_count_; 165}; 166 167TEST_F(InstantExtendedAPIEnabledTest, EnabledViaCommandLineFlag) { 168 GetCommandLine()->AppendSwitch(switches::kEnableInstantExtendedAPI); 169 EXPECT_TRUE(IsInstantExtendedAPIEnabled()); 170#if defined(OS_IOS) || defined(OS_ANDROID) 171 EXPECT_EQ(1ul, EmbeddedSearchPageVersion()); 172#else 173 EXPECT_EQ(2ul, EmbeddedSearchPageVersion()); 174#endif 175 ValidateMetrics(INSTANT_EXTENDED_OPT_IN); 176} 177 178TEST_F(InstantExtendedAPIEnabledTest, EnabledViaFinchFlag) { 179 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended", 180 "Group1 espv:42")); 181 EXPECT_TRUE(IsInstantExtendedAPIEnabled()); 182 EXPECT_EQ(42ul, EmbeddedSearchPageVersion()); 183 ValidateMetrics(INSTANT_EXTENDED_NOT_SET); 184} 185 186TEST_F(InstantExtendedAPIEnabledTest, DisabledViaCommandLineFlag) { 187 GetCommandLine()->AppendSwitch(switches::kDisableInstantExtendedAPI); 188 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended", 189 "Group1 espv:2")); 190 EXPECT_FALSE(IsInstantExtendedAPIEnabled()); 191 EXPECT_EQ(0ul, EmbeddedSearchPageVersion()); 192 ValidateMetrics(INSTANT_EXTENDED_OPT_OUT); 193} 194 195typedef InstantExtendedAPIEnabledTest ShouldHideTopVerbatimTest; 196 197TEST_F(ShouldHideTopVerbatimTest, DoNotHideByDefault) { 198 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 199 "InstantExtended", "Control")); 200 EXPECT_FALSE(ShouldHideTopVerbatimMatch()); 201} 202 203TEST_F(ShouldHideTopVerbatimTest, DoNotHideInInstantExtended) { 204 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 205 "InstantExtended", "Group1")); 206 EXPECT_FALSE(ShouldHideTopVerbatimMatch()); 207} 208 209TEST_F(ShouldHideTopVerbatimTest, EnableByFlagInInstantExtended) { 210 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 211 "InstantExtended", "Group1 hide_verbatim:1")); 212 EXPECT_TRUE(ShouldHideTopVerbatimMatch()); 213} 214 215TEST_F(ShouldHideTopVerbatimTest, EnableByFlagOutsideInstantExtended) { 216 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 217 "InstantExtended", "Controll1 hide_verbatim:1")); 218 EXPECT_TRUE(ShouldHideTopVerbatimMatch()); 219} 220 221TEST_F(ShouldHideTopVerbatimTest, DisableByFlag) { 222 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 223 "InstantExtended", "Group1 hide_verbatim:0")); 224 EXPECT_FALSE(ShouldHideTopVerbatimMatch()); 225} 226 227class SearchTest : public BrowserWithTestWindowTest { 228 protected: 229 virtual void SetUp() OVERRIDE { 230 BrowserWithTestWindowTest::SetUp(); 231 field_trial_list_.reset(new base::FieldTrialList( 232 new metrics::SHA1EntropyProvider("42"))); 233 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( 234 profile(), &TemplateURLServiceFactory::BuildInstanceFor); 235 TemplateURLService* template_url_service = 236 TemplateURLServiceFactory::GetForProfile(profile()); 237 ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service); 238 SetSearchProvider(); 239 } 240 241 void SetSearchProvider() { 242 TemplateURLService* template_url_service = 243 TemplateURLServiceFactory::GetForProfile(profile()); 244 TemplateURLData data; 245 data.SetURL("http://foo.com/url?bar={searchTerms}"); 246 data.instant_url = "http://foo.com/instant?" 247 "{google:omniboxStartMarginParameter}foo=foo#foo=foo&strk"; 248 data.alternate_urls.push_back("http://foo.com/alt#quux={searchTerms}"); 249 data.search_terms_replacement_key = "strk"; 250 251 TemplateURL* template_url = new TemplateURL(profile(), data); 252 // Takes ownership of |template_url|. 253 template_url_service->Add(template_url); 254 template_url_service->SetDefaultSearchProvider(template_url); 255 } 256 257 // Build an Instant URL with or without a valid search terms replacement key 258 // as per |has_search_term_replacement_key|. Set that URL as the instant URL 259 // for the default search provider. 260 void SetDefaultInstantTemplateUrl(bool has_search_term_replacement_key) { 261 TemplateURLService* template_url_service = 262 TemplateURLServiceFactory::GetForProfile(profile()); 263 264 static const char kInstantURLWithStrk[] = 265 "http://foo.com/instant?foo=foo#foo=foo&strk"; 266 static const char kInstantURLNoStrk[] = 267 "http://foo.com/instant?foo=foo#foo=foo"; 268 269 TemplateURLData data; 270 data.SetURL("http://foo.com/url?bar={searchTerms}"); 271 data.instant_url = (has_search_term_replacement_key ? 272 kInstantURLWithStrk : kInstantURLNoStrk); 273 data.search_terms_replacement_key = "strk"; 274 275 TemplateURL* template_url = new TemplateURL(profile(), data); 276 // Takes ownership of |template_url|. 277 template_url_service->Add(template_url); 278 template_url_service->SetDefaultSearchProvider(template_url); 279 } 280 281 bool InInstantProcess(const content::WebContents* contents) { 282 InstantService* instant_service = 283 InstantServiceFactory::GetForProfile(profile()); 284 return instant_service->IsInstantProcess( 285 contents->GetRenderProcessHost()->GetID()); 286 } 287 288 scoped_ptr<base::FieldTrialList> field_trial_list_; 289}; 290 291struct SearchTestCase { 292 const char* url; 293 bool expected_result; 294 const char* comment; 295}; 296 297TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedDisabled) { 298 DisableInstantExtendedAPIForTesting(); 299 300 const SearchTestCase kTestCases[] = { 301 {"chrome-search://foo/bar", false, ""}, 302 {"http://foo.com/instant", false, ""}, 303 {"http://foo.com/instant?foo=bar", false, ""}, 304 {"https://foo.com/instant", false, ""}, 305 {"https://foo.com/instant#foo=bar", false, ""}, 306 {"HtTpS://fOo.CoM/instant", false, ""}, 307 {"http://foo.com:80/instant", false, ""}, 308 {"invalid URL", false, "Invalid URL"}, 309 {"unknown://scheme/path", false, "Unknown scheme"}, 310 {"ftp://foo.com/instant", false, "Non-HTTP scheme"}, 311 {"http://sub.foo.com/instant", false, "Non-exact host"}, 312 {"http://foo.com:26/instant", false, "Non-default port"}, 313 {"http://foo.com/instant/bar", false, "Non-exact path"}, 314 {"http://foo.com/Instant", false, "Case sensitive path"}, 315 {"http://foo.com/", false, "Non-exact path"}, 316 {"https://foo.com/", false, "Non-exact path"}, 317 {"https://foo.com/url?strk", false, "Non-extended mode"}, 318 {"https://foo.com/alt?strk", false, "Non-extended mode"}, 319 }; 320 321 for (size_t i = 0; i < arraysize(kTestCases); ++i) { 322 const SearchTestCase& test = kTestCases[i]; 323 EXPECT_EQ(test.expected_result, 324 ShouldAssignURLToInstantRenderer(GURL(test.url), profile())) 325 << test.url << " " << test.comment; 326 } 327} 328 329TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedEnabled) { 330 EnableInstantExtendedAPIForTesting(); 331 332 const SearchTestCase kTestCases[] = { 333 {chrome::kChromeSearchLocalNtpUrl, true, ""}, 334 {"https://foo.com/instant?strk", true, ""}, 335 {"https://foo.com/instant#strk", true, ""}, 336 {"https://foo.com/instant?strk=0", true, ""}, 337 {"https://foo.com/url?strk", true, ""}, 338 {"https://foo.com/alt?strk", true, ""}, 339 {"http://foo.com/instant", false, "Non-HTTPS"}, 340 {"http://foo.com/instant?strk", false, "Non-HTTPS"}, 341 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"}, 342 {"https://foo.com/instant", false, "No search terms replacement"}, 343 {"https://foo.com/?strk", false, "Non-exact path"}, 344 }; 345 346 for (size_t i = 0; i < arraysize(kTestCases); ++i) { 347 const SearchTestCase& test = kTestCases[i]; 348 EXPECT_EQ(test.expected_result, 349 ShouldAssignURLToInstantRenderer(GURL(test.url), profile())) 350 << test.url << " " << test.comment; 351 } 352} 353 354TEST_F(SearchTest, ShouldUseProcessPerSiteForInstantURL) { 355 EnableInstantExtendedAPIForTesting(); 356 357 const SearchTestCase kTestCases[] = { 358 {"chrome-search://local-ntp", true, "Local NTP"}, 359 {"chrome-search://online-ntp", true, "Online NTP"}, 360 {"invalid-scheme://local-ntp", false, "Invalid Local NTP URL"}, 361 {"invalid-scheme://online-ntp", false, "Invalid Online NTP URL"}, 362 {"chrome-search://foo.com", false, "Search result page"}, 363 {"https://foo.com/instant?strk", false, ""}, 364 {"https://foo.com/instant#strk", false, ""}, 365 {"https://foo.com/instant?strk=0", false, ""}, 366 {"https://foo.com/url?strk", false, ""}, 367 {"https://foo.com/alt?strk", false, ""}, 368 {"http://foo.com/instant", false, "Non-HTTPS"}, 369 {"http://foo.com/instant?strk", false, "Non-HTTPS"}, 370 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"}, 371 {"https://foo.com/instant", false, "No search terms replacement"}, 372 {"https://foo.com/?strk", false, "Non-exact path"}, 373 }; 374 375 for (size_t i = 0; i < arraysize(kTestCases); ++i) { 376 const SearchTestCase& test = kTestCases[i]; 377 EXPECT_EQ(test.expected_result, 378 ShouldUseProcessPerSiteForInstantURL(GURL(test.url), profile())) 379 << test.url << " " << test.comment; 380 } 381} 382 383// Each test case represents a navigation to |start_url| followed by a 384// navigation to |end_url|. We will check whether each navigation lands in an 385// Instant process, and also whether the navigation from start to end re-uses 386// the same SiteInstance (and hence the same RenderViewHost, etc.). 387const struct ProcessIsolationTestCase { 388 const char* description; 389 const char* start_url; 390 bool start_in_instant_process; 391 const char* end_url; 392 bool end_in_instant_process; 393 bool same_site_instance; 394} kProcessIsolationTestCases[] = { 395 {"Local NTP -> SRP", 396 "chrome-search://local-ntp", true, 397 "https://foo.com/url?strk", true, false }, 398 {"Local NTP -> Regular", 399 "chrome-search://local-ntp", true, 400 "https://foo.com/other", false, false }, 401 {"Remote NTP -> SRP", 402 "https://foo.com/instant?strk", true, 403 "https://foo.com/url?strk", true, false }, 404 {"Remote NTP -> Regular", 405 "https://foo.com/instant?strk", true, 406 "https://foo.com/other", false, false }, 407 {"SRP -> SRP", 408 "https://foo.com/url?strk", true, 409 "https://foo.com/url?strk", true, true }, 410 {"SRP -> Regular", 411 "https://foo.com/url?strk", true, 412 "https://foo.com/other", false, false }, 413 {"Regular -> SRP", 414 "https://foo.com/other", false, 415 "https://foo.com/url?strk", true, false }, 416}; 417 418TEST_F(SearchTest, ProcessIsolation) { 419 EnableInstantExtendedAPIForTesting(); 420 421 for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) { 422 const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i]; 423 AddTab(browser(), GURL("chrome://blank")); 424 const content::WebContents* contents = 425 browser()->tab_strip_model()->GetActiveWebContents(); 426 427 // Navigate to start URL. 428 NavigateAndCommitActiveTab(GURL(test.start_url)); 429 EXPECT_EQ(test.start_in_instant_process, InInstantProcess(contents)) 430 << test.description; 431 432 // Save state. 433 const scoped_refptr<content::SiteInstance> start_site_instance = 434 contents->GetSiteInstance(); 435 const content::RenderProcessHost* start_rph = 436 contents->GetRenderProcessHost(); 437 const content::RenderViewHost* start_rvh = 438 contents->GetRenderViewHost(); 439 440 // Navigate to end URL. 441 NavigateAndCommitActiveTab(GURL(test.end_url)); 442 EXPECT_EQ(test.end_in_instant_process, InInstantProcess(contents)) 443 << test.description; 444 445 EXPECT_EQ(test.same_site_instance, 446 start_site_instance == contents->GetSiteInstance()) 447 << test.description; 448 EXPECT_EQ(test.same_site_instance, 449 start_rvh == contents->GetRenderViewHost()) 450 << test.description; 451 EXPECT_EQ(test.same_site_instance, 452 start_rph == contents->GetRenderProcessHost()) 453 << test.description; 454 } 455} 456 457TEST_F(SearchTest, ProcessIsolation_RendererInitiated) { 458 EnableInstantExtendedAPIForTesting(); 459 460 for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) { 461 const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i]; 462 AddTab(browser(), GURL("chrome://blank")); 463 content::WebContents* contents = 464 browser()->tab_strip_model()->GetActiveWebContents(); 465 466 // Navigate to start URL. 467 NavigateAndCommitActiveTab(GURL(test.start_url)); 468 EXPECT_EQ(test.start_in_instant_process, InInstantProcess(contents)) 469 << test.description; 470 471 // Save state. 472 const scoped_refptr<content::SiteInstance> start_site_instance = 473 contents->GetSiteInstance(); 474 const content::RenderProcessHost* start_rph = 475 contents->GetRenderProcessHost(); 476 const content::RenderViewHost* start_rvh = 477 contents->GetRenderViewHost(); 478 479 // Navigate to end URL via a renderer-initiated navigation. 480 content::NavigationController* controller = &contents->GetController(); 481 content::NavigationController::LoadURLParams load_params( 482 GURL(test.end_url)); 483 load_params.is_renderer_initiated = true; 484 load_params.transition_type = content::PAGE_TRANSITION_LINK; 485 486 controller->LoadURLWithParams(load_params); 487 CommitPendingLoad(controller); 488 EXPECT_EQ(test.end_in_instant_process, InInstantProcess(contents)) 489 << test.description; 490 491 EXPECT_EQ(test.same_site_instance, 492 start_site_instance == contents->GetSiteInstance()) 493 << test.description; 494 EXPECT_EQ(test.same_site_instance, 495 start_rvh == contents->GetRenderViewHost()) 496 << test.description; 497 EXPECT_EQ(test.same_site_instance, 498 start_rph == contents->GetRenderProcessHost()) 499 << test.description; 500 } 501} 502 503const SearchTestCase kInstantNTPTestCases[] = { 504 {"https://foo.com/instant?strk", true, "Valid Instant URL"}, 505 {"https://foo.com/instant#strk", true, "Valid Instant URL"}, 506 {"https://foo.com/url?strk", true, "Valid search URL"}, 507 {"https://foo.com/url#strk", true, "Valid search URL"}, 508 {"https://foo.com/alt?strk", true, "Valid alternative URL"}, 509 {"https://foo.com/alt#strk", true, "Valid alternative URL"}, 510 {"https://foo.com/url?strk&bar=", true, "No query terms"}, 511 {"https://foo.com/url?strk&q=abc", true, "No query terms key"}, 512 {"https://foo.com/url?strk#bar=abc", true, "Query terms key in ref"}, 513 {"https://foo.com/url?strk&bar=abc", false, "Has query terms"}, 514 {"http://foo.com/instant?strk=1", false, "Insecure URL"}, 515 {"https://foo.com/instant", false, "No search term replacement"}, 516 {"chrome://blank/", false, "Chrome scheme"}, 517 {"chrome-search://foo", false, "Chrome-search scheme"}, 518 {chrome::kChromeSearchLocalNtpUrl, true, "Local new tab page"}, 519 {"https://bar.com/instant?strk=1", false, "Random non-search page"}, 520}; 521 522TEST_F(SearchTest, InstantNTPExtendedEnabled) { 523 EnableInstantExtendedAPIForTesting(); 524 AddTab(browser(), GURL("chrome://blank")); 525 for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) { 526 const SearchTestCase& test = kInstantNTPTestCases[i]; 527 NavigateAndCommitActiveTab(GURL(test.url)); 528 const content::WebContents* contents = 529 browser()->tab_strip_model()->GetWebContentsAt(0); 530 EXPECT_EQ(test.expected_result, IsInstantNTP(contents)) 531 << test.url << " " << test.comment; 532 } 533} 534 535TEST_F(SearchTest, InstantNTPExtendedDisabled) { 536 AddTab(browser(), GURL("chrome://blank")); 537 for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) { 538 const SearchTestCase& test = kInstantNTPTestCases[i]; 539 NavigateAndCommitActiveTab(GURL(test.url)); 540 const content::WebContents* contents = 541 browser()->tab_strip_model()->GetWebContentsAt(0); 542 EXPECT_FALSE(IsInstantNTP(contents)) << test.url << " " << test.comment; 543 } 544} 545 546TEST_F(SearchTest, InstantNTPCustomNavigationEntry) { 547 EnableInstantExtendedAPIForTesting(); 548 AddTab(browser(), GURL("chrome://blank")); 549 for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) { 550 const SearchTestCase& test = kInstantNTPTestCases[i]; 551 NavigateAndCommitActiveTab(GURL(test.url)); 552 content::WebContents* contents = 553 browser()->tab_strip_model()->GetWebContentsAt(0); 554 content::NavigationController& controller = contents->GetController(); 555 controller.SetTransientEntry( 556 controller.CreateNavigationEntry(GURL("chrome://blank"), 557 content::Referrer(), 558 content::PAGE_TRANSITION_LINK, 559 false, 560 std::string(), 561 contents->GetBrowserContext())); 562 // The active entry is chrome://blank and not an NTP. 563 EXPECT_FALSE(IsInstantNTP(contents)); 564 EXPECT_EQ(test.expected_result, 565 NavEntryIsInstantNTP(contents, 566 controller.GetLastCommittedEntry())) 567 << test.url << " " << test.comment; 568 } 569} 570 571TEST_F(SearchTest, GetInstantURLExtendedEnabled) { 572 // Instant is disabled, so no Instant URL. 573 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin)); 574 575 // Enable Instant. Still no Instant URL because "strk" is missing. 576 EnableInstantExtendedAPIForTesting(); 577 SetDefaultInstantTemplateUrl(false); 578 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin)); 579 580 // Set an Instant URL with a valid search terms replacement key. 581 SetDefaultInstantTemplateUrl(true); 582 583 // Now there should be a valid Instant URL. Note the HTTPS "upgrade". 584 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"), 585 GetInstantURL(profile(), kDisableStartMargin)); 586 587 // Enable suggest. No difference. 588 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true); 589 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"), 590 GetInstantURL(profile(), kDisableStartMargin)); 591 592 // Disable suggest. No Instant URL. 593 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false); 594 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin)); 595} 596 597TEST_F(SearchTest, StartMarginCGI) { 598 // Instant is disabled, so no Instant URL. 599 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin)); 600 601 // Enable Instant. No margin. 602 EnableInstantExtendedAPIForTesting(); 603 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true); 604 605 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"), 606 GetInstantURL(profile(), kDisableStartMargin)); 607 608 // With start margin. 609 EXPECT_EQ(GURL("https://foo.com/instant?es_sm=10&foo=foo#foo=foo&strk"), 610 GetInstantURL(profile(), 10)); 611} 612 613TEST_F(SearchTest, CommandLineOverrides) { 614 EnableInstantExtendedAPIForTesting(); 615 616 GURL local_instant_url(GetLocalInstantURL(profile())); 617 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url); 618 619 TemplateURLService* template_url_service = 620 TemplateURLServiceFactory::GetForProfile(profile()); 621 TemplateURLData data; 622 data.SetURL("{google:baseURL}search?q={searchTerms}"); 623 data.instant_url = "{google:baseURL}webhp?strk"; 624 data.search_terms_replacement_key = "strk"; 625 TemplateURL* template_url = new TemplateURL(profile(), data); 626 // Takes ownership of |template_url|. 627 template_url_service->Add(template_url); 628 template_url_service->SetDefaultSearchProvider(template_url); 629 630 // By default, Instant Extended forces the instant URL to be HTTPS, so even if 631 // we set a Google base URL that is HTTP, we should get an HTTPS URL. 632 UIThreadSearchTermsData::SetGoogleBaseURL("http://www.foo.com/"); 633 GURL instant_url(GetInstantURL(profile(), kDisableStartMargin)); 634 ASSERT_TRUE(instant_url.is_valid()); 635 EXPECT_EQ("https://www.foo.com/webhp?strk", instant_url.spec()); 636 637 // However, if the Google base URL is specified on the command line, the 638 // instant URL should just use it, even if it's HTTP. 639 UIThreadSearchTermsData::SetGoogleBaseURL(std::string()); 640 CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL, 641 "http://www.bar.com/"); 642 instant_url = GetInstantURL(profile(), kDisableStartMargin); 643 ASSERT_TRUE(instant_url.is_valid()); 644 EXPECT_EQ("http://www.bar.com/webhp?strk", instant_url.spec()); 645 646 // Similarly, setting a Google base URL on the command line should allow you 647 // to get the Google version of the local NTP, even though search provider's 648 // URL doesn't contain "google". 649 local_instant_url = GetLocalInstantURL(profile()); 650 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url); 651 652 // If we specify extra search query params, they should be inserted into the 653 // query portion of the instant URL. 654 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 655 switches::kExtraSearchQueryParams, "a=b"); 656 instant_url = GetInstantURL(profile(), kDisableStartMargin); 657 ASSERT_TRUE(instant_url.is_valid()); 658 EXPECT_EQ("http://www.bar.com/webhp?a=b&strk", instant_url.spec()); 659} 660 661TEST_F(SearchTest, ShouldShowInstantNTP_Default) { 662 EnableInstantExtendedAPIForTesting(); 663 EXPECT_TRUE(ShouldShowInstantNTP()); 664} 665 666TEST_F(SearchTest, ShouldShowInstantNTP_DisabledViaFinch) { 667 EnableInstantExtendedAPIForTesting(); 668 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended", 669 "Group1 show_ntp:0")); 670 EXPECT_FALSE(ShouldShowInstantNTP()); 671} 672 673TEST_F(SearchTest, ShouldShowInstantNTP_DisabledByInstantNewTabURLSwitch) { 674 EnableInstantExtendedAPIForTesting(); 675 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 676 switches::kInstantNewTabURL, "http://example.com/newtab"); 677 EXPECT_FALSE(ShouldShowInstantNTP()); 678} 679 680TEST_F(SearchTest, IsNTPURL) { 681 GURL invalid_url; 682 GURL ntp_url(chrome::kChromeUINewTabURL); 683 GURL local_ntp_url(GetLocalInstantURL(profile())); 684 685 EXPECT_FALSE(chrome::IsNTPURL(invalid_url, profile())); 686 EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, profile())); 687 688 EXPECT_TRUE(chrome::IsNTPURL(ntp_url, NULL)); 689 EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, NULL)); 690 691 // Enable Instant. No margin. 692 EnableInstantExtendedAPIForTesting(); 693 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true); 694 GURL remote_ntp_url(GetInstantURL(profile(), kDisableStartMargin)); 695 696 EXPECT_FALSE(chrome::IsNTPURL(ntp_url, profile())); 697 EXPECT_TRUE(chrome::IsNTPURL(local_ntp_url, profile())); 698 EXPECT_TRUE(chrome::IsNTPURL(remote_ntp_url, profile())); 699 700 EXPECT_FALSE(chrome::IsNTPURL(ntp_url, NULL)); 701 EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, NULL)); 702 EXPECT_FALSE(chrome::IsNTPURL(remote_ntp_url, NULL)); 703} 704 705} // namespace chrome 706