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/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" 32#include "url/gurl.h" 33 34namespace chrome { 35 36class EmbeddedSearchFieldTrialTest : public testing::Test { 37 protected: 38 virtual void SetUp() { 39 field_trial_list_.reset(new base::FieldTrialList( 40 new metrics::SHA1EntropyProvider("42"))); 41 base::StatisticsRecorder::Initialize(); 42 } 43 44 private: 45 scoped_ptr<base::FieldTrialList> field_trial_list_; 46}; 47 48TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoEmptyAndValid) { 49 FieldTrialFlags flags; 50 51 EXPECT_TRUE(GetFieldTrialInfo(&flags)); 52 EXPECT_EQ(0ul, flags.size()); 53 54 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 55 "Group77")); 56 EXPECT_TRUE(GetFieldTrialInfo(&flags)); 57 EXPECT_EQ(0ul, flags.size()); 58} 59 60TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoInvalidNumber) { 61 FieldTrialFlags flags; 62 63 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 64 "Group77.2")); 65 EXPECT_TRUE(GetFieldTrialInfo(&flags)); 66 EXPECT_EQ(0ul, flags.size()); 67} 68 69TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoInvalidName) { 70 FieldTrialFlags flags; 71 72 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 73 "Invalid77")); 74 EXPECT_TRUE(GetFieldTrialInfo(&flags)); 75 EXPECT_EQ(0ul, flags.size()); 76} 77 78TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoValidGroup) { 79 FieldTrialFlags flags; 80 81 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 82 "Group77")); 83 EXPECT_TRUE(GetFieldTrialInfo(&flags)); 84 EXPECT_EQ(0ul, flags.size()); 85} 86 87TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoValidFlag) { 88 FieldTrialFlags flags; 89 90 EXPECT_EQ(9999ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags)); 91 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 92 "Group77 foo:6")); 93 EXPECT_TRUE(GetFieldTrialInfo(&flags)); 94 EXPECT_EQ(1ul, flags.size()); 95 EXPECT_EQ(6ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags)); 96} 97 98TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoNewName) { 99 FieldTrialFlags flags; 100 101 EXPECT_EQ(9999ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags)); 102 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 103 "Group77 foo:6")); 104 EXPECT_TRUE(GetFieldTrialInfo(&flags)); 105 EXPECT_EQ(1ul, flags.size()); 106 EXPECT_EQ(6ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags)); 107} 108 109TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoNewNameOverridesOld) { 110 FieldTrialFlags flags; 111 112 EXPECT_EQ(9999ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags)); 113 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 114 "Group77 foo:6")); 115 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended", 116 "Group78 foo:5")); 117 EXPECT_TRUE(GetFieldTrialInfo(&flags)); 118 EXPECT_EQ(1ul, flags.size()); 119 EXPECT_EQ(6ul, GetUInt64ValueForFlagWithDefault("foo", 9999, flags)); 120} 121 122TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoLotsOfFlags) { 123 FieldTrialFlags flags; 124 125 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 126 "EmbeddedSearch", "Group77 bar:1 baz:7 cat:dogs")); 127 EXPECT_TRUE(GetFieldTrialInfo(&flags)); 128 EXPECT_EQ(3ul, flags.size()); 129 EXPECT_EQ(true, GetBoolValueForFlagWithDefault("bar", false, flags)); 130 EXPECT_EQ(7ul, GetUInt64ValueForFlagWithDefault("baz", 0, flags)); 131 EXPECT_EQ("dogs", 132 GetStringValueForFlagWithDefault("cat", std::string(), flags)); 133 EXPECT_EQ("default", 134 GetStringValueForFlagWithDefault("moose", "default", flags)); 135} 136 137TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoDisabled) { 138 FieldTrialFlags flags; 139 140 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 141 "EmbeddedSearch", "Group77 bar:1 baz:7 cat:dogs DISABLED")); 142 EXPECT_FALSE(GetFieldTrialInfo(&flags)); 143 EXPECT_EQ(0ul, flags.size()); 144} 145 146TEST_F(EmbeddedSearchFieldTrialTest, GetFieldTrialInfoControlFlags) { 147 FieldTrialFlags flags; 148 149 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 150 "EmbeddedSearch", "Control77 bar:1 baz:7 cat:dogs")); 151 EXPECT_TRUE(GetFieldTrialInfo(&flags)); 152 EXPECT_EQ(3ul, flags.size()); 153} 154 155class SearchTest : public BrowserWithTestWindowTest { 156 protected: 157 virtual void SetUp() OVERRIDE { 158 BrowserWithTestWindowTest::SetUp(); 159 field_trial_list_.reset(new base::FieldTrialList( 160 new metrics::SHA1EntropyProvider("42"))); 161 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse( 162 profile(), &TemplateURLServiceFactory::BuildInstanceFor); 163 TemplateURLService* template_url_service = 164 TemplateURLServiceFactory::GetForProfile(profile()); 165 ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service); 166 SetSearchProvider(true, false); 167 } 168 169 void SetSearchProvider(bool set_ntp_url, bool insecure_ntp_url) { 170 TemplateURLService* template_url_service = 171 TemplateURLServiceFactory::GetForProfile(profile()); 172 TemplateURLData data; 173 data.SetURL("http://foo.com/url?bar={searchTerms}"); 174 data.instant_url = "http://foo.com/instant?" 175 "{google:omniboxStartMarginParameter}{google:forceInstantResults}" 176 "foo=foo#foo=foo&strk"; 177 if (set_ntp_url) { 178 data.new_tab_url = (insecure_ntp_url ? "http" : "https") + 179 std::string("://foo.com/newtab?strk"); 180 } 181 data.alternate_urls.push_back("http://foo.com/alt#quux={searchTerms}"); 182 data.search_terms_replacement_key = "strk"; 183 184 TemplateURL* template_url = new TemplateURL(profile(), data); 185 // Takes ownership of |template_url|. 186 template_url_service->Add(template_url); 187 template_url_service->SetDefaultSearchProvider(template_url); 188 } 189 190 // Build an Instant URL with or without a valid search terms replacement key 191 // as per |has_search_term_replacement_key|. Set that URL as the instant URL 192 // for the default search provider. 193 void SetDefaultInstantTemplateUrl(bool has_search_term_replacement_key) { 194 TemplateURLService* template_url_service = 195 TemplateURLServiceFactory::GetForProfile(profile()); 196 197 static const char kInstantURLWithStrk[] = 198 "http://foo.com/instant?foo=foo#foo=foo&strk"; 199 static const char kInstantURLNoStrk[] = 200 "http://foo.com/instant?foo=foo#foo=foo"; 201 202 TemplateURLData data; 203 data.SetURL("http://foo.com/url?bar={searchTerms}"); 204 data.instant_url = (has_search_term_replacement_key ? 205 kInstantURLWithStrk : kInstantURLNoStrk); 206 data.search_terms_replacement_key = "strk"; 207 208 TemplateURL* template_url = new TemplateURL(profile(), data); 209 // Takes ownership of |template_url|. 210 template_url_service->Add(template_url); 211 template_url_service->SetDefaultSearchProvider(template_url); 212 } 213 214 bool InInstantProcess(const content::WebContents* contents) { 215 InstantService* instant_service = 216 InstantServiceFactory::GetForProfile(profile()); 217 return instant_service->IsInstantProcess( 218 contents->GetRenderProcessHost()->GetID()); 219 } 220 221 scoped_ptr<base::FieldTrialList> field_trial_list_; 222}; 223 224struct SearchTestCase { 225 const char* url; 226 bool expected_result; 227 const char* comment; 228}; 229 230TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedEnabled) { 231 EnableQueryExtractionForTesting(); 232 233 const SearchTestCase kTestCases[] = { 234 {chrome::kChromeSearchLocalNtpUrl, true, ""}, 235 {"https://foo.com/instant?strk", true, ""}, 236 {"https://foo.com/instant#strk", true, ""}, 237 {"https://foo.com/instant?strk=0", true, ""}, 238 {"https://foo.com/url?strk", true, ""}, 239 {"https://foo.com/alt?strk", true, ""}, 240 {"http://foo.com/instant", false, "Non-HTTPS"}, 241 {"http://foo.com/instant?strk", false, "Non-HTTPS"}, 242 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"}, 243 {"https://foo.com/instant", false, "No search terms replacement"}, 244 {"https://foo.com/?strk", false, "Non-exact path"}, 245 }; 246 247 for (size_t i = 0; i < arraysize(kTestCases); ++i) { 248 const SearchTestCase& test = kTestCases[i]; 249 EXPECT_EQ(test.expected_result, 250 ShouldAssignURLToInstantRenderer(GURL(test.url), profile())) 251 << test.url << " " << test.comment; 252 } 253} 254 255TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedEnabledNotOnSRP) { 256 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 257 "EmbeddedSearch", "Group1 espv:2 suppress_on_srp:1")); 258 259 const SearchTestCase kTestCases[] = { 260 {chrome::kChromeSearchLocalNtpUrl, true, ""}, 261 {"https://foo.com/instant?strk", true, ""}, 262 {"https://foo.com/instant#strk", true, ""}, 263 {"https://foo.com/instant?strk=0", true, ""}, 264 {"https://foo.com/url?strk", false, "Disabled on SRP"}, 265 {"https://foo.com/alt?strk", false, "Disabled ON SRP"}, 266 {"http://foo.com/instant", false, "Non-HTTPS"}, 267 {"http://foo.com/instant?strk", false, "Non-HTTPS"}, 268 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"}, 269 {"https://foo.com/instant", false, "No search terms replacement"}, 270 {"https://foo.com/?strk", false, "Non-exact path"}, 271 }; 272 273 for (size_t i = 0; i < arraysize(kTestCases); ++i) { 274 const SearchTestCase& test = kTestCases[i]; 275 EXPECT_EQ(test.expected_result, 276 ShouldAssignURLToInstantRenderer(GURL(test.url), profile())) 277 << test.url << " " << test.comment; 278 } 279} 280 281TEST_F(SearchTest, ShouldUseProcessPerSiteForInstantURL) { 282 EnableQueryExtractionForTesting(); 283 284 const SearchTestCase kTestCases[] = { 285 {"chrome-search://local-ntp", true, "Local NTP"}, 286 {"chrome-search://online-ntp", true, "Online NTP"}, 287 {"invalid-scheme://local-ntp", false, "Invalid Local NTP URL"}, 288 {"invalid-scheme://online-ntp", false, "Invalid Online NTP URL"}, 289 {"chrome-search://foo.com", false, "Search result page"}, 290 {"https://foo.com/instant?strk", false, ""}, 291 {"https://foo.com/instant#strk", false, ""}, 292 {"https://foo.com/instant?strk=0", false, ""}, 293 {"https://foo.com/url?strk", false, ""}, 294 {"https://foo.com/alt?strk", false, ""}, 295 {"http://foo.com/instant", false, "Non-HTTPS"}, 296 {"http://foo.com/instant?strk", false, "Non-HTTPS"}, 297 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"}, 298 {"https://foo.com/instant", false, "No search terms replacement"}, 299 {"https://foo.com/?strk", false, "Non-exact path"}, 300 }; 301 302 for (size_t i = 0; i < arraysize(kTestCases); ++i) { 303 const SearchTestCase& test = kTestCases[i]; 304 EXPECT_EQ(test.expected_result, 305 ShouldUseProcessPerSiteForInstantURL(GURL(test.url), profile())) 306 << test.url << " " << test.comment; 307 } 308} 309 310// Each test case represents a navigation to |start_url| followed by a 311// navigation to |end_url|. We will check whether each navigation lands in an 312// Instant process, and also whether the navigation from start to end re-uses 313// the same SiteInstance (and hence the same RenderViewHost, etc.). 314const struct ProcessIsolationTestCase { 315 const char* description; 316 const char* start_url; 317 bool start_in_instant_process; 318 const char* end_url; 319 bool end_in_instant_process; 320 bool same_site_instance; 321} kProcessIsolationTestCases[] = { 322 {"Local NTP -> SRP", 323 "chrome-search://local-ntp", true, 324 "https://foo.com/url?strk", true, false }, 325 {"Local NTP -> Regular", 326 "chrome-search://local-ntp", true, 327 "https://foo.com/other", false, false }, 328 {"Remote NTP -> SRP", 329 "https://foo.com/instant?strk", true, 330 "https://foo.com/url?strk", true, false }, 331 {"Remote NTP -> Regular", 332 "https://foo.com/instant?strk", true, 333 "https://foo.com/other", false, false }, 334 {"SRP -> SRP", 335 "https://foo.com/url?strk", true, 336 "https://foo.com/url?strk", true, true }, 337 {"SRP -> Regular", 338 "https://foo.com/url?strk", true, 339 "https://foo.com/other", false, false }, 340 {"Regular -> SRP", 341 "https://foo.com/other", false, 342 "https://foo.com/url?strk", true, false }, 343}; 344 345TEST_F(SearchTest, ProcessIsolation) { 346 EnableQueryExtractionForTesting(); 347 348 for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) { 349 const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i]; 350 AddTab(browser(), GURL("chrome://blank")); 351 const content::WebContents* contents = 352 browser()->tab_strip_model()->GetActiveWebContents(); 353 354 // Navigate to start URL. 355 NavigateAndCommitActiveTab(GURL(test.start_url)); 356 EXPECT_EQ(test.start_in_instant_process, InInstantProcess(contents)) 357 << test.description; 358 359 // Save state. 360 const scoped_refptr<content::SiteInstance> start_site_instance = 361 contents->GetSiteInstance(); 362 const content::RenderProcessHost* start_rph = 363 contents->GetRenderProcessHost(); 364 const content::RenderViewHost* start_rvh = 365 contents->GetRenderViewHost(); 366 367 // Navigate to end URL. 368 NavigateAndCommitActiveTab(GURL(test.end_url)); 369 EXPECT_EQ(test.end_in_instant_process, InInstantProcess(contents)) 370 << test.description; 371 372 EXPECT_EQ(test.same_site_instance, 373 start_site_instance == contents->GetSiteInstance()) 374 << test.description; 375 EXPECT_EQ(test.same_site_instance, 376 start_rvh == contents->GetRenderViewHost()) 377 << test.description; 378 EXPECT_EQ(test.same_site_instance, 379 start_rph == contents->GetRenderProcessHost()) 380 << test.description; 381 } 382} 383 384TEST_F(SearchTest, ProcessIsolation_RendererInitiated) { 385 EnableQueryExtractionForTesting(); 386 387 for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) { 388 const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i]; 389 AddTab(browser(), GURL("chrome://blank")); 390 content::WebContents* contents = 391 browser()->tab_strip_model()->GetActiveWebContents(); 392 393 // Navigate to start URL. 394 NavigateAndCommitActiveTab(GURL(test.start_url)); 395 EXPECT_EQ(test.start_in_instant_process, InInstantProcess(contents)) 396 << test.description; 397 398 // Save state. 399 const scoped_refptr<content::SiteInstance> start_site_instance = 400 contents->GetSiteInstance(); 401 const content::RenderProcessHost* start_rph = 402 contents->GetRenderProcessHost(); 403 const content::RenderViewHost* start_rvh = 404 contents->GetRenderViewHost(); 405 406 // Navigate to end URL via a renderer-initiated navigation. 407 content::NavigationController* controller = &contents->GetController(); 408 content::NavigationController::LoadURLParams load_params( 409 GURL(test.end_url)); 410 load_params.is_renderer_initiated = true; 411 load_params.transition_type = content::PAGE_TRANSITION_LINK; 412 413 controller->LoadURLWithParams(load_params); 414 CommitPendingLoad(controller); 415 EXPECT_EQ(test.end_in_instant_process, InInstantProcess(contents)) 416 << test.description; 417 418 EXPECT_EQ(test.same_site_instance, 419 start_site_instance == contents->GetSiteInstance()) 420 << test.description; 421 EXPECT_EQ(test.same_site_instance, 422 start_rvh == contents->GetRenderViewHost()) 423 << test.description; 424 EXPECT_EQ(test.same_site_instance, 425 start_rph == contents->GetRenderProcessHost()) 426 << test.description; 427 } 428} 429 430const SearchTestCase kInstantNTPTestCases[] = { 431 {"https://foo.com/instant?strk", true, "Valid Instant URL"}, 432 {"https://foo.com/instant#strk", true, "Valid Instant URL"}, 433 {"https://foo.com/url?strk", true, "Valid search URL"}, 434 {"https://foo.com/url#strk", true, "Valid search URL"}, 435 {"https://foo.com/alt?strk", true, "Valid alternative URL"}, 436 {"https://foo.com/alt#strk", true, "Valid alternative URL"}, 437 {"https://foo.com/url?strk&bar=", true, "No query terms"}, 438 {"https://foo.com/url?strk&q=abc", true, "No query terms key"}, 439 {"https://foo.com/url?strk#bar=abc", true, "Query terms key in ref"}, 440 {"https://foo.com/url?strk&bar=abc", false, "Has query terms"}, 441 {"http://foo.com/instant?strk=1", false, "Insecure URL"}, 442 {"https://foo.com/instant", false, "No search term replacement"}, 443 {"chrome://blank/", false, "Chrome scheme"}, 444 {"chrome-search://foo", false, "Chrome-search scheme"}, 445 {chrome::kChromeSearchLocalNtpUrl, true, "Local new tab page"}, 446 {"https://bar.com/instant?strk=1", false, "Random non-search page"}, 447}; 448 449TEST_F(SearchTest, InstantNTPExtendedEnabled) { 450 EnableQueryExtractionForTesting(); 451 // TODO(samarth): update test cases to use cacheable NTP URLs and remove this. 452 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 453 "InstantExtended", "Group1 use_cacheable_ntp:0")); 454 AddTab(browser(), GURL("chrome://blank")); 455 for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) { 456 const SearchTestCase& test = kInstantNTPTestCases[i]; 457 NavigateAndCommitActiveTab(GURL(test.url)); 458 const content::WebContents* contents = 459 browser()->tab_strip_model()->GetWebContentsAt(0); 460 EXPECT_EQ(test.expected_result, IsInstantNTP(contents)) 461 << test.url << " " << test.comment; 462 } 463} 464 465TEST_F(SearchTest, InstantNTPCustomNavigationEntry) { 466 EnableQueryExtractionForTesting(); 467 // TODO(samarth): update test cases to use cacheable NTP URLs and remove this. 468 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 469 "InstantExtended", "Group1 use_cacheable_ntp:0")); 470 AddTab(browser(), GURL("chrome://blank")); 471 for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) { 472 const SearchTestCase& test = kInstantNTPTestCases[i]; 473 NavigateAndCommitActiveTab(GURL(test.url)); 474 content::WebContents* contents = 475 browser()->tab_strip_model()->GetWebContentsAt(0); 476 content::NavigationController& controller = contents->GetController(); 477 controller.SetTransientEntry( 478 controller.CreateNavigationEntry(GURL("chrome://blank"), 479 content::Referrer(), 480 content::PAGE_TRANSITION_LINK, 481 false, 482 std::string(), 483 contents->GetBrowserContext())); 484 // The active entry is chrome://blank and not an NTP. 485 EXPECT_FALSE(IsInstantNTP(contents)); 486 EXPECT_EQ(test.expected_result, 487 NavEntryIsInstantNTP(contents, 488 controller.GetLastCommittedEntry())) 489 << test.url << " " << test.comment; 490 } 491} 492 493TEST_F(SearchTest, InstantCacheableNTPNavigationEntry) { 494 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 495 "EmbeddedSearch", "Group1 use_cacheable_ntp:1")); 496 497 AddTab(browser(), GURL("chrome://blank")); 498 content::WebContents* contents = 499 browser()->tab_strip_model()->GetWebContentsAt(0); 500 content::NavigationController& controller = contents->GetController(); 501 // Local NTP. 502 NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl)); 503 EXPECT_TRUE(NavEntryIsInstantNTP(contents, 504 controller.GetLastCommittedEntry())); 505 // Instant page is not cacheable NTP. 506 NavigateAndCommitActiveTab(GetInstantURL(profile(), kDisableStartMargin, 507 false)); 508 EXPECT_FALSE(NavEntryIsInstantNTP(contents, 509 controller.GetLastCommittedEntry())); 510 // Test Cacheable NTP 511 NavigateAndCommitActiveTab(chrome::GetNewTabPageURL(profile())); 512 EXPECT_TRUE(NavEntryIsInstantNTP(contents, 513 controller.GetLastCommittedEntry())); 514} 515 516TEST_F(SearchTest, InstantCacheableNTPNavigationEntryNewProfile) { 517 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 518 "EmbeddedSearch", "Group1 use_cacheable_ntp:1")); 519 SetSearchProvider(false, false); 520 AddTab(browser(), GURL(chrome::kChromeUINewTabURL)); 521 content::WebContents* contents = 522 browser()->tab_strip_model()->GetWebContentsAt(0); 523 content::NavigationController& controller = contents->GetController(); 524 // Test virtual url chrome://newtab for first NTP of a new profile 525 EXPECT_TRUE(NavEntryIsInstantNTP(contents, 526 controller.GetLastCommittedEntry())); 527 // The new_tab_url gets set after the first NTP is visible. 528 SetSearchProvider(true, false); 529 EXPECT_TRUE(NavEntryIsInstantNTP(contents, 530 controller.GetLastCommittedEntry())); 531} 532 533TEST_F(SearchTest, UseLocalNTPInIncognito) { 534 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 535 "EmbeddedSearch", "Group1 use_cacheable_ntp:1")); 536 EXPECT_EQ(GURL(), chrome::GetNewTabPageURL( 537 profile()->GetOffTheRecordProfile())); 538} 539 540TEST_F(SearchTest, UseLocalNTPIfNTPURLIsInsecure) { 541 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 542 "EmbeddedSearch", "Group1 use_cacheable_ntp:1")); 543 // Set an insecure new tab page URL and verify that it's ignored. 544 SetSearchProvider(true, true); 545 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), 546 chrome::GetNewTabPageURL(profile())); 547} 548 549TEST_F(SearchTest, UseLocalNTPIfNTPURLIsNotSet) { 550 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 551 "EmbeddedSearch", "Group1 use_cacheable_ntp:1")); 552 // Set an insecure new tab page URL and verify that it's ignored. 553 SetSearchProvider(false, true); 554 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), 555 chrome::GetNewTabPageURL(profile())); 556} 557 558TEST_F(SearchTest, UseLocalNTPIfNTPURLIsBlockedForSupervisedUser) { 559 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 560 "EmbeddedSearch", "Group1 use_cacheable_ntp:1")); 561 562 // Block access to foo.com in the URL filter. 563 ManagedUserService* managed_user_service = 564 ManagedUserServiceFactory::GetForProfile(profile()); 565 ManagedModeURLFilter* url_filter = 566 managed_user_service->GetURLFilterForUIThread(); 567 std::map<std::string, bool> hosts; 568 hosts["foo.com"] = false; 569 url_filter->SetManualHosts(&hosts); 570 571 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), 572 chrome::GetNewTabPageURL(profile())); 573 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false)); 574} 575 576TEST_F(SearchTest, GetInstantURL) { 577 // No Instant URL because "strk" is missing. 578 SetDefaultInstantTemplateUrl(false); 579 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false)); 580 581 // Set an Instant URL with a valid search terms replacement key. 582 SetDefaultInstantTemplateUrl(true); 583 584 // Now there should be a valid Instant URL. Note the HTTPS "upgrade". 585 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"), 586 GetInstantURL(profile(), kDisableStartMargin, false)); 587 588 // Enable suggest. No difference. 589 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true); 590 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"), 591 GetInstantURL(profile(), kDisableStartMargin, false)); 592 593 // Disable suggest. No Instant URL. 594 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false); 595 EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false)); 596} 597 598TEST_F(SearchTest, StartMarginCGI) { 599 // No margin. 600 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true); 601 602 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"), 603 GetInstantURL(profile(), kDisableStartMargin, false)); 604 605 // With start margin. 606 EXPECT_EQ(GURL("https://foo.com/instant?es_sm=10&foo=foo#foo=foo&strk"), 607 GetInstantURL(profile(), 10, false)); 608} 609 610TEST_F(SearchTest, InstantSearchEnabledCGI) { 611 // Disable Instant Search. 612 // Make sure {google:forceInstantResults} is not set in the Instant URL. 613 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"), 614 GetInstantURL(profile(), kDisableStartMargin, false)); 615 616 // Enable Instant Search. 617 // Make sure {google:forceInstantResults} is set in the Instant URL. 618 EXPECT_EQ(GURL("https://foo.com/instant?ion=1&foo=foo#foo=foo&strk"), 619 GetInstantURL(profile(), kDisableStartMargin, true)); 620} 621 622TEST_F(SearchTest, CommandLineOverrides) { 623 GURL local_instant_url(GetLocalInstantURL(profile())); 624 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url); 625 626 TemplateURLService* template_url_service = 627 TemplateURLServiceFactory::GetForProfile(profile()); 628 TemplateURLData data; 629 data.SetURL("{google:baseURL}search?q={searchTerms}"); 630 data.instant_url = "{google:baseURL}webhp?strk"; 631 data.search_terms_replacement_key = "strk"; 632 TemplateURL* template_url = new TemplateURL(profile(), data); 633 // Takes ownership of |template_url|. 634 template_url_service->Add(template_url); 635 template_url_service->SetDefaultSearchProvider(template_url); 636 637 // By default, Instant Extended forces the instant URL to be HTTPS, so even if 638 // we set a Google base URL that is HTTP, we should get an HTTPS URL. 639 UIThreadSearchTermsData::SetGoogleBaseURL("http://www.foo.com/"); 640 GURL instant_url(GetInstantURL(profile(), kDisableStartMargin, false)); 641 ASSERT_TRUE(instant_url.is_valid()); 642 EXPECT_EQ("https://www.foo.com/webhp?strk", instant_url.spec()); 643 644 // However, if the Google base URL is specified on the command line, the 645 // instant URL should just use it, even if it's HTTP. 646 UIThreadSearchTermsData::SetGoogleBaseURL(std::string()); 647 CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL, 648 "http://www.bar.com/"); 649 instant_url = GetInstantURL(profile(), kDisableStartMargin, false); 650 ASSERT_TRUE(instant_url.is_valid()); 651 EXPECT_EQ("http://www.bar.com/webhp?strk", instant_url.spec()); 652 653 // Similarly, setting a Google base URL on the command line should allow you 654 // to get the Google version of the local NTP, even though search provider's 655 // URL doesn't contain "google". 656 local_instant_url = GetLocalInstantURL(profile()); 657 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url); 658 659 // If we specify extra search query params, they should be inserted into the 660 // query portion of the instant URL. 661 CommandLine::ForCurrentProcess()->AppendSwitchASCII( 662 switches::kExtraSearchQueryParams, "a=b"); 663 instant_url = GetInstantURL(profile(), kDisableStartMargin, false); 664 ASSERT_TRUE(instant_url.is_valid()); 665 EXPECT_EQ("http://www.bar.com/webhp?a=b&strk", instant_url.spec()); 666} 667 668TEST_F(SearchTest, ShouldShowInstantNTP_Default) { 669 EXPECT_FALSE(ShouldShowInstantNTP()); 670} 671 672TEST_F(SearchTest, ShouldShowInstantNTP_DisabledViaFinch) { 673 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 674 "EmbeddedSearch", "Group1 show_ntp:0")); 675 EXPECT_FALSE(ShouldShowInstantNTP()); 676} 677 678TEST_F(SearchTest, ShouldShowInstantNTP_DisabledByUseCacheableNTPFinchFlag) { 679 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 680 "EmbeddedSearch", "Group1 use_cacheable_ntp:1")); 681 EXPECT_FALSE(ShouldShowInstantNTP()); 682} 683 684TEST_F(SearchTest, ShouldUseCacheableNTP_Default) { 685 EXPECT_TRUE(ShouldUseCacheableNTP()); 686} 687 688TEST_F(SearchTest, ShouldUseCacheableNTP_EnabledViaFinch) { 689 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 690 "EmbeddedSearch", "Group1 use_cacheable_ntp:1")); 691 EXPECT_TRUE(ShouldUseCacheableNTP()); 692} 693 694TEST_F(SearchTest, ShouldPrefetchSearchResults_Default) { 695 EXPECT_FALSE(ShouldPrefetchSearchResults()); 696} 697 698TEST_F(SearchTest, ShouldPrefetchSearchResults_InstantExtendedAPIEnabled) { 699 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 700 "EmbeddedSearch", 701 "Group1 espv:2 use_cacheable_ntp:1 prefetch_results:1")); 702 EXPECT_TRUE(ShouldPrefetchSearchResults()); 703#if defined(OS_IOS) || defined(OS_ANDROID) 704 EXPECT_EQ(1ul, EmbeddedSearchPageVersion()); 705#else 706 EXPECT_EQ(2ul, EmbeddedSearchPageVersion()); 707#endif 708} 709 710TEST_F(SearchTest, ShouldPrefetchSearchResults_DisabledViaFinch) { 711 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 712 "EmbeddedSearch", 713 "Group1 use_cacheable_ntp:1 espv:89 prefetch_results:0")); 714 EXPECT_FALSE(ShouldPrefetchSearchResults()); 715 EXPECT_EQ(89ul, EmbeddedSearchPageVersion()); 716} 717 718TEST_F(SearchTest, ShouldPrefetchSearchResults_EnabledViaFinch) { 719 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 720 "EmbeddedSearch", 721 "Group1 espv:80 use_cacheable_ntp:1 prefetch_results:1")); 722 EXPECT_TRUE(ShouldPrefetchSearchResults()); 723 EXPECT_EQ(80ul, EmbeddedSearchPageVersion()); 724} 725 726TEST_F(SearchTest, IsNTPURL) { 727 GURL invalid_url; 728 GURL ntp_url(chrome::kChromeUINewTabURL); 729 GURL local_ntp_url(GetLocalInstantURL(profile())); 730 731 EXPECT_FALSE(chrome::IsNTPURL(invalid_url, profile())); 732 // No margin. 733 EnableQueryExtractionForTesting(); 734 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true); 735 GURL remote_ntp_url(GetInstantURL(profile(), kDisableStartMargin, false)); 736 GURL search_url_with_search_terms("https://foo.com/url?strk&bar=abc"); 737 GURL search_url_without_search_terms("https://foo.com/url?strk&bar"); 738 739 EXPECT_FALSE(chrome::IsNTPURL(ntp_url, profile())); 740 EXPECT_TRUE(chrome::IsNTPURL(local_ntp_url, profile())); 741 EXPECT_TRUE(chrome::IsNTPURL(remote_ntp_url, profile())); 742 EXPECT_FALSE(chrome::IsNTPURL(search_url_with_search_terms, profile())); 743 EXPECT_TRUE(chrome::IsNTPURL(search_url_without_search_terms, profile())); 744 745 EXPECT_FALSE(chrome::IsNTPURL(ntp_url, NULL)); 746 EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, NULL)); 747 EXPECT_FALSE(chrome::IsNTPURL(remote_ntp_url, NULL)); 748 EXPECT_FALSE(chrome::IsNTPURL(search_url_with_search_terms, NULL)); 749 EXPECT_FALSE(chrome::IsNTPURL(search_url_without_search_terms, NULL)); 750} 751 752TEST_F(SearchTest, GetSearchURLs) { 753 std::vector<GURL> search_urls = GetSearchURLs(profile()); 754 EXPECT_EQ(2U, search_urls.size()); 755 EXPECT_EQ("http://foo.com/alt#quux=", search_urls[0].spec()); 756 EXPECT_EQ("http://foo.com/url?bar=", search_urls[1].spec()); 757} 758 759TEST_F(SearchTest, GetSearchResultPrefetchBaseURL) { 760 // "prefetch_results" flag is disabled. 761 EXPECT_EQ(GURL(), GetSearchResultPrefetchBaseURL(profile())); 762 763 // "prefetch_results" flag is enabled via field trials. 764 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 765 "EmbeddedSearch", 766 "Group1 espv:80 use_cacheable_ntp:1 prefetch_results:1")); 767 EXPECT_TRUE(ShouldPrefetchSearchResults()); 768 769 EXPECT_EQ(GURL("https://foo.com/instant?ion=1&foo=foo#foo=foo&strk"), 770 GetSearchResultPrefetchBaseURL(profile())); 771} 772 773typedef SearchTest IsQueryExtractionEnabledTest; 774 775TEST_F(IsQueryExtractionEnabledTest, NotSet) { 776 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 777 "EmbeddedSearch", "Group1 espv:2")); 778 EXPECT_TRUE(IsInstantExtendedAPIEnabled()); 779 EXPECT_FALSE(IsQueryExtractionEnabled()); 780 EXPECT_EQ(2ul, EmbeddedSearchPageVersion()); 781} 782 783TEST_F(IsQueryExtractionEnabledTest, EnabledViaFinch) { 784 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 785 "EmbeddedSearch", "Group1 espv:2 query_extraction:1")); 786 EXPECT_TRUE(IsInstantExtendedAPIEnabled()); 787 EXPECT_TRUE(IsQueryExtractionEnabled()); 788 EXPECT_EQ(2ul, EmbeddedSearchPageVersion()); 789} 790 791TEST_F(IsQueryExtractionEnabledTest, DisabledViaFinch) { 792 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 793 "EmbeddedSearch", "Group1 espv:2 query_extraction:0")); 794 EXPECT_TRUE(IsInstantExtendedAPIEnabled()); 795 EXPECT_FALSE(IsQueryExtractionEnabled()); 796 EXPECT_EQ(2ul, EmbeddedSearchPageVersion()); 797} 798 799TEST_F(IsQueryExtractionEnabledTest, EnabledViaCommandLine) { 800 EnableQueryExtractionForTesting(); 801 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 802 "EmbeddedSearch", "Group1 espv:2 query_extraction:0")); 803 EXPECT_TRUE(IsInstantExtendedAPIEnabled()); 804 EXPECT_TRUE(IsQueryExtractionEnabled()); 805 EXPECT_EQ(2ul, EmbeddedSearchPageVersion()); 806} 807 808typedef SearchTest ShouldHideTopVerbatimTest; 809 810TEST_F(ShouldHideTopVerbatimTest, DoNotHideByDefault) { 811 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 812 "Control")); 813 EXPECT_FALSE(ShouldHideTopVerbatimMatch()); 814} 815 816TEST_F(ShouldHideTopVerbatimTest, DoNotHideInInstantExtended) { 817 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 818 "Group1")); 819 EXPECT_FALSE(ShouldHideTopVerbatimMatch()); 820} 821 822TEST_F(ShouldHideTopVerbatimTest, EnableByFlagInInstantExtended) { 823 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 824 "Group1 hide_verbatim:1")); 825 EXPECT_TRUE(ShouldHideTopVerbatimMatch()); 826} 827 828TEST_F(ShouldHideTopVerbatimTest, EnableByFlagOutsideInstantExtended) { 829 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 830 "EmbeddedSearch", "Controll1 hide_verbatim:1")); 831 EXPECT_TRUE(ShouldHideTopVerbatimMatch()); 832} 833 834TEST_F(ShouldHideTopVerbatimTest, DisableByFlag) { 835 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch", 836 "Group1 hide_verbatim:0")); 837 EXPECT_FALSE(ShouldHideTopVerbatimMatch()); 838} 839 840typedef SearchTest DisplaySearchButtonTest; 841 842TEST_F(DisplaySearchButtonTest, NotSet) { 843 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 844 "EmbeddedSearch", "Group1 espv:2")); 845 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions()); 846} 847 848TEST_F(DisplaySearchButtonTest, Never) { 849 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 850 "EmbeddedSearch", "Group1 espv:2 display_search_button:0")); 851 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions()); 852} 853 854TEST_F(DisplaySearchButtonTest, CommandLineNever) { 855 CommandLine::ForCurrentProcess()->AppendSwitch( 856 switches::kDisableSearchButtonInOmnibox); 857 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions()); 858 859 // Command-line disable should override Finch. 860 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 861 "EmbeddedSearch", "Group1 espv:2 display_search_button:1")); 862 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions()); 863} 864 865TEST_F(DisplaySearchButtonTest, ForSearchTermReplacement) { 866 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 867 "EmbeddedSearch", "Group1 espv:2 display_search_button:1")); 868 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_FOR_STR, GetDisplaySearchButtonConditions()); 869} 870 871TEST_F(DisplaySearchButtonTest, CommandLineForSearchTermReplacement) { 872 CommandLine::ForCurrentProcess()->AppendSwitch( 873 switches::kEnableSearchButtonInOmniboxForStr); 874 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_FOR_STR, GetDisplaySearchButtonConditions()); 875} 876 877TEST_F(DisplaySearchButtonTest, ForSearchTermReplacementOrInputInProgress) { 878 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 879 "EmbeddedSearch", "Group1 espv:2 display_search_button:2")); 880 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_FOR_STR_OR_IIP, 881 GetDisplaySearchButtonConditions()); 882} 883 884TEST_F(DisplaySearchButtonTest, 885 CommandLineForSearchTermReplacementOrInputInProgress) { 886 CommandLine::ForCurrentProcess()->AppendSwitch( 887 switches::kEnableSearchButtonInOmniboxForStrOrIip); 888 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_FOR_STR_OR_IIP, 889 GetDisplaySearchButtonConditions()); 890} 891 892TEST_F(DisplaySearchButtonTest, Always) { 893 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 894 "EmbeddedSearch", "Group1 espv:2 display_search_button:3")); 895 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_ALWAYS, GetDisplaySearchButtonConditions()); 896} 897 898TEST_F(DisplaySearchButtonTest, CommandLineAlways) { 899 CommandLine::ForCurrentProcess()->AppendSwitch( 900 switches::kEnableSearchButtonInOmniboxAlways); 901 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_ALWAYS, GetDisplaySearchButtonConditions()); 902} 903 904TEST_F(DisplaySearchButtonTest, InvalidValue) { 905 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 906 "EmbeddedSearch", "Group1 espv:2 display_search_button:4")); 907 EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions()); 908} 909 910typedef SearchTest OriginChipTest; 911 912TEST_F(OriginChipTest, NotSet) { 913 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 914 "EmbeddedSearch", "Group1 espv:2")); 915 EXPECT_FALSE(ShouldDisplayOriginChip()); 916} 917 918TEST_F(OriginChipTest, NoOriginChip) { 919 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 920 "EmbeddedSearch", "Group1 espv:2 origin_chip:0")); 921 EXPECT_FALSE(ShouldDisplayOriginChip()); 922} 923 924TEST_F(OriginChipTest, CommandLineNoOriginChip) { 925 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kDisableOriginChip); 926 EXPECT_FALSE(ShouldDisplayOriginChip()); 927 928 // Command-line disable should override Finch. 929 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 930 "EmbeddedSearch", "Group1 espv:2 origin_chip:1")); 931 EXPECT_FALSE(ShouldDisplayOriginChip()); 932} 933 934TEST_F(OriginChipTest, OriginChip) { 935 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial( 936 "EmbeddedSearch", "Group1 espv:2 origin_chip:1")); 937 EXPECT_TRUE(ShouldDisplayOriginChip()); 938} 939 940TEST_F(OriginChipTest, CommandLineOriginChip) { 941 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kEnableOriginChip); 942 EXPECT_TRUE(ShouldDisplayOriginChip()); 943} 944 945} // namespace chrome 946