Home | History | Annotate | Download | only in search
      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 
     30 namespace chrome {
     31 
     32 TEST(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 
     45 TEST(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 
     62 TEST(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 
     73 TEST(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 
     89 TEST(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 
     99 TEST(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 
    109 class 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 
    167 TEST_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 
    178 TEST_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 
    186 TEST_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 
    195 typedef InstantExtendedAPIEnabledTest ShouldHideTopVerbatimTest;
    196 
    197 TEST_F(ShouldHideTopVerbatimTest, DoNotHideByDefault) {
    198   ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
    199       "InstantExtended", "Control"));
    200   EXPECT_FALSE(ShouldHideTopVerbatimMatch());
    201 }
    202 
    203 TEST_F(ShouldHideTopVerbatimTest, DoNotHideInInstantExtended) {
    204   ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
    205       "InstantExtended", "Group1"));
    206   EXPECT_FALSE(ShouldHideTopVerbatimMatch());
    207 }
    208 
    209 TEST_F(ShouldHideTopVerbatimTest, EnableByFlagInInstantExtended) {
    210   ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
    211       "InstantExtended", "Group1 hide_verbatim:1"));
    212   EXPECT_TRUE(ShouldHideTopVerbatimMatch());
    213 }
    214 
    215 TEST_F(ShouldHideTopVerbatimTest, EnableByFlagOutsideInstantExtended) {
    216   ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
    217       "InstantExtended", "Controll1 hide_verbatim:1"));
    218   EXPECT_TRUE(ShouldHideTopVerbatimMatch());
    219 }
    220 
    221 TEST_F(ShouldHideTopVerbatimTest, DisableByFlag) {
    222   ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
    223       "InstantExtended", "Group1 hide_verbatim:0"));
    224   EXPECT_FALSE(ShouldHideTopVerbatimMatch());
    225 }
    226 
    227 typedef InstantExtendedAPIEnabledTest ShouldSuppressInstantExtendedOnSRPTest;
    228 
    229 TEST_F(ShouldSuppressInstantExtendedOnSRPTest, NotSet) {
    230   ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
    231       "InstantExtended", "Group1 espv:2"));
    232   EXPECT_FALSE(ShouldSuppressInstantExtendedOnSRP());
    233   EXPECT_TRUE(IsInstantExtendedAPIEnabled());
    234   EXPECT_TRUE(IsQueryExtractionEnabled());
    235   EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
    236 }
    237 
    238 TEST_F(ShouldSuppressInstantExtendedOnSRPTest, NotSuppressOnSRP) {
    239   ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
    240       "InstantExtended", "Group1 espv:2 suppress_on_srp:0"));
    241   EXPECT_FALSE(ShouldSuppressInstantExtendedOnSRP());
    242   EXPECT_TRUE(IsInstantExtendedAPIEnabled());
    243   EXPECT_TRUE(IsQueryExtractionEnabled());
    244   EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
    245 }
    246 
    247 TEST_F(ShouldSuppressInstantExtendedOnSRPTest, SuppressOnSRP) {
    248   ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
    249       "InstantExtended", "Group1 espv:2 suppress_on_srp:1"));
    250   EXPECT_TRUE(ShouldSuppressInstantExtendedOnSRP());
    251   EXPECT_TRUE(IsInstantExtendedAPIEnabled());
    252   EXPECT_FALSE(IsQueryExtractionEnabled());
    253   EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
    254 }
    255 
    256 class SearchTest : public BrowserWithTestWindowTest {
    257  protected:
    258   virtual void SetUp() OVERRIDE {
    259     BrowserWithTestWindowTest::SetUp();
    260     field_trial_list_.reset(new base::FieldTrialList(
    261         new metrics::SHA1EntropyProvider("42")));
    262     TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
    263         profile(), &TemplateURLServiceFactory::BuildInstanceFor);
    264     TemplateURLService* template_url_service =
    265         TemplateURLServiceFactory::GetForProfile(profile());
    266     ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
    267     SetSearchProvider();
    268   }
    269 
    270   void SetSearchProvider() {
    271     TemplateURLService* template_url_service =
    272         TemplateURLServiceFactory::GetForProfile(profile());
    273     TemplateURLData data;
    274     data.SetURL("http://foo.com/url?bar={searchTerms}");
    275     data.instant_url = "http://foo.com/instant?"
    276         "{google:omniboxStartMarginParameter}foo=foo#foo=foo&strk";
    277     data.alternate_urls.push_back("http://foo.com/alt#quux={searchTerms}");
    278     data.search_terms_replacement_key = "strk";
    279 
    280     TemplateURL* template_url = new TemplateURL(profile(), data);
    281     // Takes ownership of |template_url|.
    282     template_url_service->Add(template_url);
    283     template_url_service->SetDefaultSearchProvider(template_url);
    284   }
    285 
    286   // Build an Instant URL with or without a valid search terms replacement key
    287   // as per |has_search_term_replacement_key|. Set that URL as the instant URL
    288   // for the default search provider.
    289   void SetDefaultInstantTemplateUrl(bool has_search_term_replacement_key) {
    290     TemplateURLService* template_url_service =
    291         TemplateURLServiceFactory::GetForProfile(profile());
    292 
    293     static const char kInstantURLWithStrk[] =
    294         "http://foo.com/instant?foo=foo#foo=foo&strk";
    295     static const char kInstantURLNoStrk[] =
    296         "http://foo.com/instant?foo=foo#foo=foo";
    297 
    298     TemplateURLData data;
    299     data.SetURL("http://foo.com/url?bar={searchTerms}");
    300     data.instant_url = (has_search_term_replacement_key ?
    301         kInstantURLWithStrk : kInstantURLNoStrk);
    302     data.search_terms_replacement_key = "strk";
    303 
    304     TemplateURL* template_url = new TemplateURL(profile(), data);
    305     // Takes ownership of |template_url|.
    306     template_url_service->Add(template_url);
    307     template_url_service->SetDefaultSearchProvider(template_url);
    308   }
    309 
    310   bool InInstantProcess(const content::WebContents* contents) {
    311     InstantService* instant_service =
    312         InstantServiceFactory::GetForProfile(profile());
    313     return instant_service->IsInstantProcess(
    314         contents->GetRenderProcessHost()->GetID());
    315   }
    316 
    317   scoped_ptr<base::FieldTrialList> field_trial_list_;
    318 };
    319 
    320 struct SearchTestCase {
    321   const char* url;
    322   bool expected_result;
    323   const char* comment;
    324 };
    325 
    326 TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedDisabled) {
    327   DisableInstantExtendedAPIForTesting();
    328 
    329   const SearchTestCase kTestCases[] = {
    330     {"chrome-search://foo/bar",                 false,  ""},
    331     {"http://foo.com/instant",                  false,  ""},
    332     {"http://foo.com/instant?foo=bar",          false,  ""},
    333     {"https://foo.com/instant",                 false,  ""},
    334     {"https://foo.com/instant#foo=bar",         false,  ""},
    335     {"HtTpS://fOo.CoM/instant",                 false,  ""},
    336     {"http://foo.com:80/instant",               false,  ""},
    337     {"invalid URL",                             false, "Invalid URL"},
    338     {"unknown://scheme/path",                   false, "Unknown scheme"},
    339     {"ftp://foo.com/instant",                   false, "Non-HTTP scheme"},
    340     {"http://sub.foo.com/instant",              false, "Non-exact host"},
    341     {"http://foo.com:26/instant",               false, "Non-default port"},
    342     {"http://foo.com/instant/bar",              false, "Non-exact path"},
    343     {"http://foo.com/Instant",                  false, "Case sensitive path"},
    344     {"http://foo.com/",                         false, "Non-exact path"},
    345     {"https://foo.com/",                        false, "Non-exact path"},
    346     {"https://foo.com/url?strk",                false, "Non-extended mode"},
    347     {"https://foo.com/alt?strk",                false, "Non-extended mode"},
    348   };
    349 
    350   for (size_t i = 0; i < arraysize(kTestCases); ++i) {
    351     const SearchTestCase& test = kTestCases[i];
    352     EXPECT_EQ(test.expected_result,
    353               ShouldAssignURLToInstantRenderer(GURL(test.url), profile()))
    354         << test.url << " " << test.comment;
    355   }
    356 }
    357 
    358 TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedEnabled) {
    359   EnableInstantExtendedAPIForTesting();
    360 
    361   const SearchTestCase kTestCases[] = {
    362     {chrome::kChromeSearchLocalNtpUrl, true,  ""},
    363     {"https://foo.com/instant?strk",   true,  ""},
    364     {"https://foo.com/instant#strk",   true,  ""},
    365     {"https://foo.com/instant?strk=0", true,  ""},
    366     {"https://foo.com/url?strk",       true,  ""},
    367     {"https://foo.com/alt?strk",       true,  ""},
    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               ShouldAssignURLToInstantRenderer(GURL(test.url), profile()))
    379         << test.url << " " << test.comment;
    380   }
    381 }
    382 
    383 TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedEnabledNotOnSRP) {
    384   ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
    385       "InstantExtended", "Group1 espv:2 suppress_on_srp:1"));
    386 
    387   const SearchTestCase kTestCases[] = {
    388     {chrome::kChromeSearchLocalNtpUrl, true,  ""},
    389     {"https://foo.com/instant?strk",   true,  ""},
    390     {"https://foo.com/instant#strk",   true,  ""},
    391     {"https://foo.com/instant?strk=0", true,  ""},
    392     {"https://foo.com/url?strk",       false, "Disabled on SRP"},
    393     {"https://foo.com/alt?strk",       false, "Disabled ON SRP"},
    394     {"http://foo.com/instant",         false, "Non-HTTPS"},
    395     {"http://foo.com/instant?strk",    false, "Non-HTTPS"},
    396     {"http://foo.com/instant?strk=1",  false, "Non-HTTPS"},
    397     {"https://foo.com/instant",        false, "No search terms replacement"},
    398     {"https://foo.com/?strk",          false, "Non-exact path"},
    399   };
    400 
    401   for (size_t i = 0; i < arraysize(kTestCases); ++i) {
    402     const SearchTestCase& test = kTestCases[i];
    403     EXPECT_EQ(test.expected_result,
    404               ShouldAssignURLToInstantRenderer(GURL(test.url), profile()))
    405         << test.url << " " << test.comment;
    406   }
    407 }
    408 
    409 TEST_F(SearchTest, ShouldUseProcessPerSiteForInstantURL) {
    410   EnableInstantExtendedAPIForTesting();
    411 
    412   const SearchTestCase kTestCases[] = {
    413     {"chrome-search://local-ntp",      true,  "Local NTP"},
    414     {"chrome-search://online-ntp",     true,  "Online NTP"},
    415     {"invalid-scheme://local-ntp",     false, "Invalid Local NTP URL"},
    416     {"invalid-scheme://online-ntp",    false, "Invalid Online NTP URL"},
    417     {"chrome-search://foo.com",        false, "Search result page"},
    418     {"https://foo.com/instant?strk",   false,  ""},
    419     {"https://foo.com/instant#strk",   false,  ""},
    420     {"https://foo.com/instant?strk=0", false,  ""},
    421     {"https://foo.com/url?strk",       false,  ""},
    422     {"https://foo.com/alt?strk",       false,  ""},
    423     {"http://foo.com/instant",         false,  "Non-HTTPS"},
    424     {"http://foo.com/instant?strk",    false,  "Non-HTTPS"},
    425     {"http://foo.com/instant?strk=1",  false,  "Non-HTTPS"},
    426     {"https://foo.com/instant",        false,  "No search terms replacement"},
    427     {"https://foo.com/?strk",          false,  "Non-exact path"},
    428   };
    429 
    430   for (size_t i = 0; i < arraysize(kTestCases); ++i) {
    431     const SearchTestCase& test = kTestCases[i];
    432     EXPECT_EQ(test.expected_result,
    433               ShouldUseProcessPerSiteForInstantURL(GURL(test.url), profile()))
    434         << test.url << " " << test.comment;
    435   }
    436 }
    437 
    438 // Each test case represents a navigation to |start_url| followed by a
    439 // navigation to |end_url|. We will check whether each navigation lands in an
    440 // Instant process, and also whether the navigation from start to end re-uses
    441 // the same SiteInstance (and hence the same RenderViewHost, etc.).
    442 const struct ProcessIsolationTestCase {
    443   const char* description;
    444   const char* start_url;
    445   bool start_in_instant_process;
    446   const char* end_url;
    447   bool end_in_instant_process;
    448   bool same_site_instance;
    449 } kProcessIsolationTestCases[] = {
    450   {"Local NTP -> SRP",
    451    "chrome-search://local-ntp",       true,
    452    "https://foo.com/url?strk",        true,   false },
    453   {"Local NTP -> Regular",
    454    "chrome-search://local-ntp",       true,
    455    "https://foo.com/other",           false,  false },
    456   {"Remote NTP -> SRP",
    457    "https://foo.com/instant?strk",    true,
    458    "https://foo.com/url?strk",        true,   false },
    459   {"Remote NTP -> Regular",
    460    "https://foo.com/instant?strk",    true,
    461    "https://foo.com/other",           false,  false },
    462   {"SRP -> SRP",
    463    "https://foo.com/url?strk",        true,
    464    "https://foo.com/url?strk",        true,   true  },
    465   {"SRP -> Regular",
    466    "https://foo.com/url?strk",        true,
    467    "https://foo.com/other",           false,  false },
    468   {"Regular -> SRP",
    469    "https://foo.com/other",           false,
    470    "https://foo.com/url?strk",        true,   false },
    471 };
    472 
    473 TEST_F(SearchTest, ProcessIsolation) {
    474   EnableInstantExtendedAPIForTesting();
    475 
    476   for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) {
    477     const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i];
    478     AddTab(browser(), GURL("chrome://blank"));
    479     const content::WebContents* contents =
    480         browser()->tab_strip_model()->GetActiveWebContents();
    481 
    482     // Navigate to start URL.
    483     NavigateAndCommitActiveTab(GURL(test.start_url));
    484     EXPECT_EQ(test.start_in_instant_process, InInstantProcess(contents))
    485         << test.description;
    486 
    487     // Save state.
    488     const scoped_refptr<content::SiteInstance> start_site_instance =
    489         contents->GetSiteInstance();
    490     const content::RenderProcessHost* start_rph =
    491         contents->GetRenderProcessHost();
    492     const content::RenderViewHost* start_rvh =
    493         contents->GetRenderViewHost();
    494 
    495     // Navigate to end URL.
    496     NavigateAndCommitActiveTab(GURL(test.end_url));
    497     EXPECT_EQ(test.end_in_instant_process, InInstantProcess(contents))
    498         << test.description;
    499 
    500     EXPECT_EQ(test.same_site_instance,
    501               start_site_instance == contents->GetSiteInstance())
    502         << test.description;
    503     EXPECT_EQ(test.same_site_instance,
    504               start_rvh == contents->GetRenderViewHost())
    505         << test.description;
    506     EXPECT_EQ(test.same_site_instance,
    507               start_rph == contents->GetRenderProcessHost())
    508         << test.description;
    509   }
    510 }
    511 
    512 TEST_F(SearchTest, ProcessIsolation_RendererInitiated) {
    513   EnableInstantExtendedAPIForTesting();
    514 
    515   for (size_t i = 0; i < arraysize(kProcessIsolationTestCases); ++i) {
    516     const ProcessIsolationTestCase& test = kProcessIsolationTestCases[i];
    517     AddTab(browser(), GURL("chrome://blank"));
    518     content::WebContents* contents =
    519         browser()->tab_strip_model()->GetActiveWebContents();
    520 
    521     // Navigate to start URL.
    522     NavigateAndCommitActiveTab(GURL(test.start_url));
    523     EXPECT_EQ(test.start_in_instant_process, InInstantProcess(contents))
    524         << test.description;
    525 
    526     // Save state.
    527     const scoped_refptr<content::SiteInstance> start_site_instance =
    528         contents->GetSiteInstance();
    529     const content::RenderProcessHost* start_rph =
    530         contents->GetRenderProcessHost();
    531     const content::RenderViewHost* start_rvh =
    532         contents->GetRenderViewHost();
    533 
    534     // Navigate to end URL via a renderer-initiated navigation.
    535     content::NavigationController* controller = &contents->GetController();
    536     content::NavigationController::LoadURLParams load_params(
    537         GURL(test.end_url));
    538     load_params.is_renderer_initiated = true;
    539     load_params.transition_type = content::PAGE_TRANSITION_LINK;
    540 
    541     controller->LoadURLWithParams(load_params);
    542     CommitPendingLoad(controller);
    543     EXPECT_EQ(test.end_in_instant_process, InInstantProcess(contents))
    544         << test.description;
    545 
    546     EXPECT_EQ(test.same_site_instance,
    547               start_site_instance == contents->GetSiteInstance())
    548         << test.description;
    549     EXPECT_EQ(test.same_site_instance,
    550               start_rvh == contents->GetRenderViewHost())
    551         << test.description;
    552     EXPECT_EQ(test.same_site_instance,
    553               start_rph == contents->GetRenderProcessHost())
    554         << test.description;
    555   }
    556 }
    557 
    558 const SearchTestCase kInstantNTPTestCases[] = {
    559   {"https://foo.com/instant?strk",         true,  "Valid Instant URL"},
    560   {"https://foo.com/instant#strk",         true,  "Valid Instant URL"},
    561   {"https://foo.com/url?strk",             true,  "Valid search URL"},
    562   {"https://foo.com/url#strk",             true,  "Valid search URL"},
    563   {"https://foo.com/alt?strk",             true,  "Valid alternative URL"},
    564   {"https://foo.com/alt#strk",             true,  "Valid alternative URL"},
    565   {"https://foo.com/url?strk&bar=",        true,  "No query terms"},
    566   {"https://foo.com/url?strk&q=abc",       true,  "No query terms key"},
    567   {"https://foo.com/url?strk#bar=abc",     true,  "Query terms key in ref"},
    568   {"https://foo.com/url?strk&bar=abc",     false, "Has query terms"},
    569   {"http://foo.com/instant?strk=1",        false, "Insecure URL"},
    570   {"https://foo.com/instant",              false, "No search term replacement"},
    571   {"chrome://blank/",                      false, "Chrome scheme"},
    572   {"chrome-search://foo",                  false, "Chrome-search scheme"},
    573   {chrome::kChromeSearchLocalNtpUrl,       true,  "Local new tab page"},
    574   {"https://bar.com/instant?strk=1",       false, "Random non-search page"},
    575 };
    576 
    577 TEST_F(SearchTest, InstantNTPExtendedEnabled) {
    578   EnableInstantExtendedAPIForTesting();
    579   AddTab(browser(), GURL("chrome://blank"));
    580   for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
    581     const SearchTestCase& test = kInstantNTPTestCases[i];
    582     NavigateAndCommitActiveTab(GURL(test.url));
    583     const content::WebContents* contents =
    584         browser()->tab_strip_model()->GetWebContentsAt(0);
    585     EXPECT_EQ(test.expected_result, IsInstantNTP(contents))
    586         << test.url << " " << test.comment;
    587   }
    588 }
    589 
    590 TEST_F(SearchTest, InstantNTPExtendedDisabled) {
    591   AddTab(browser(), GURL("chrome://blank"));
    592   for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
    593     const SearchTestCase& test = kInstantNTPTestCases[i];
    594     NavigateAndCommitActiveTab(GURL(test.url));
    595     const content::WebContents* contents =
    596         browser()->tab_strip_model()->GetWebContentsAt(0);
    597     EXPECT_FALSE(IsInstantNTP(contents)) << test.url << " " << test.comment;
    598   }
    599 }
    600 
    601 TEST_F(SearchTest, InstantNTPCustomNavigationEntry) {
    602   EnableInstantExtendedAPIForTesting();
    603   AddTab(browser(), GURL("chrome://blank"));
    604   for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
    605     const SearchTestCase& test = kInstantNTPTestCases[i];
    606     NavigateAndCommitActiveTab(GURL(test.url));
    607     content::WebContents* contents =
    608         browser()->tab_strip_model()->GetWebContentsAt(0);
    609     content::NavigationController& controller = contents->GetController();
    610     controller.SetTransientEntry(
    611         controller.CreateNavigationEntry(GURL("chrome://blank"),
    612                                          content::Referrer(),
    613                                          content::PAGE_TRANSITION_LINK,
    614                                          false,
    615                                          std::string(),
    616                                          contents->GetBrowserContext()));
    617     // The active entry is chrome://blank and not an NTP.
    618     EXPECT_FALSE(IsInstantNTP(contents));
    619     EXPECT_EQ(test.expected_result,
    620               NavEntryIsInstantNTP(contents,
    621                                    controller.GetLastCommittedEntry()))
    622         << test.url << " " << test.comment;
    623   }
    624 }
    625 
    626 TEST_F(SearchTest, GetInstantURLExtendedEnabled) {
    627   // Instant is disabled, so no Instant URL.
    628   EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
    629 
    630   // Enable Instant. Still no Instant URL because "strk" is missing.
    631   EnableInstantExtendedAPIForTesting();
    632   SetDefaultInstantTemplateUrl(false);
    633   EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
    634 
    635   // Set an Instant URL with a valid search terms replacement key.
    636   SetDefaultInstantTemplateUrl(true);
    637 
    638   // Now there should be a valid Instant URL. Note the HTTPS "upgrade".
    639   EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
    640             GetInstantURL(profile(), kDisableStartMargin));
    641 
    642   // Enable suggest. No difference.
    643   profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
    644   EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
    645             GetInstantURL(profile(), kDisableStartMargin));
    646 
    647   // Disable suggest. No Instant URL.
    648   profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
    649   EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
    650 }
    651 
    652 TEST_F(SearchTest, StartMarginCGI) {
    653   // Instant is disabled, so no Instant URL.
    654   EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
    655 
    656   // Enable Instant. No margin.
    657   EnableInstantExtendedAPIForTesting();
    658   profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
    659 
    660   EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
    661             GetInstantURL(profile(), kDisableStartMargin));
    662 
    663   // With start margin.
    664   EXPECT_EQ(GURL("https://foo.com/instant?es_sm=10&foo=foo#foo=foo&strk"),
    665             GetInstantURL(profile(), 10));
    666 }
    667 
    668 TEST_F(SearchTest, CommandLineOverrides) {
    669   EnableInstantExtendedAPIForTesting();
    670 
    671   GURL local_instant_url(GetLocalInstantURL(profile()));
    672   EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url);
    673 
    674   TemplateURLService* template_url_service =
    675       TemplateURLServiceFactory::GetForProfile(profile());
    676   TemplateURLData data;
    677   data.SetURL("{google:baseURL}search?q={searchTerms}");
    678   data.instant_url = "{google:baseURL}webhp?strk";
    679   data.search_terms_replacement_key = "strk";
    680   TemplateURL* template_url = new TemplateURL(profile(), data);
    681   // Takes ownership of |template_url|.
    682   template_url_service->Add(template_url);
    683   template_url_service->SetDefaultSearchProvider(template_url);
    684 
    685   // By default, Instant Extended forces the instant URL to be HTTPS, so even if
    686   // we set a Google base URL that is HTTP, we should get an HTTPS URL.
    687   UIThreadSearchTermsData::SetGoogleBaseURL("http://www.foo.com/");
    688   GURL instant_url(GetInstantURL(profile(), kDisableStartMargin));
    689   ASSERT_TRUE(instant_url.is_valid());
    690   EXPECT_EQ("https://www.foo.com/webhp?strk", instant_url.spec());
    691 
    692   // However, if the Google base URL is specified on the command line, the
    693   // instant URL should just use it, even if it's HTTP.
    694   UIThreadSearchTermsData::SetGoogleBaseURL(std::string());
    695   CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
    696                                                       "http://www.bar.com/");
    697   instant_url = GetInstantURL(profile(), kDisableStartMargin);
    698   ASSERT_TRUE(instant_url.is_valid());
    699   EXPECT_EQ("http://www.bar.com/webhp?strk", instant_url.spec());
    700 
    701   // Similarly, setting a Google base URL on the command line should allow you
    702   // to get the Google version of the local NTP, even though search provider's
    703   // URL doesn't contain "google".
    704   local_instant_url = GetLocalInstantURL(profile());
    705   EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url);
    706 
    707   // If we specify extra search query params, they should be inserted into the
    708   // query portion of the instant URL.
    709   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    710       switches::kExtraSearchQueryParams, "a=b");
    711   instant_url = GetInstantURL(profile(), kDisableStartMargin);
    712   ASSERT_TRUE(instant_url.is_valid());
    713   EXPECT_EQ("http://www.bar.com/webhp?a=b&strk", instant_url.spec());
    714 }
    715 
    716 TEST_F(SearchTest, ShouldShowInstantNTP_Default) {
    717   EnableInstantExtendedAPIForTesting();
    718   EXPECT_TRUE(ShouldShowInstantNTP());
    719 }
    720 
    721 TEST_F(SearchTest, ShouldShowInstantNTP_DisabledViaFinch) {
    722   EnableInstantExtendedAPIForTesting();
    723   ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("InstantExtended",
    724                                                      "Group1 show_ntp:0"));
    725   EXPECT_FALSE(ShouldShowInstantNTP());
    726 }
    727 
    728 TEST_F(SearchTest, ShouldShowInstantNTP_DisabledByInstantNewTabURLSwitch) {
    729   EnableInstantExtendedAPIForTesting();
    730   CommandLine::ForCurrentProcess()->AppendSwitchASCII(
    731       switches::kInstantNewTabURL, "http://example.com/newtab");
    732   EXPECT_FALSE(ShouldShowInstantNTP());
    733 }
    734 
    735 TEST_F(SearchTest, IsNTPURL) {
    736   GURL invalid_url;
    737   GURL ntp_url(chrome::kChromeUINewTabURL);
    738   GURL local_ntp_url(GetLocalInstantURL(profile()));
    739 
    740   EXPECT_FALSE(chrome::IsNTPURL(invalid_url, profile()));
    741   EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, profile()));
    742 
    743   EXPECT_TRUE(chrome::IsNTPURL(ntp_url, NULL));
    744   EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, NULL));
    745 
    746   // Enable Instant. No margin.
    747   EnableInstantExtendedAPIForTesting();
    748   profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
    749   GURL remote_ntp_url(GetInstantURL(profile(), kDisableStartMargin));
    750   GURL search_url_with_search_terms("https://foo.com/url?strk&bar=abc");
    751   GURL search_url_without_search_terms("https://foo.com/url?strk&bar");
    752 
    753   EXPECT_FALSE(chrome::IsNTPURL(ntp_url, profile()));
    754   EXPECT_TRUE(chrome::IsNTPURL(local_ntp_url, profile()));
    755   EXPECT_TRUE(chrome::IsNTPURL(remote_ntp_url, profile()));
    756   EXPECT_FALSE(chrome::IsNTPURL(search_url_with_search_terms, profile()));
    757   EXPECT_TRUE(chrome::IsNTPURL(search_url_without_search_terms, profile()));
    758 
    759   EXPECT_FALSE(chrome::IsNTPURL(ntp_url, NULL));
    760   EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, NULL));
    761   EXPECT_FALSE(chrome::IsNTPURL(remote_ntp_url, NULL));
    762   EXPECT_FALSE(chrome::IsNTPURL(search_url_with_search_terms, NULL));
    763   EXPECT_FALSE(chrome::IsNTPURL(search_url_without_search_terms, NULL));
    764 }
    765 
    766 }  // namespace chrome
    767