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