search_unittest.cc revision f2477e01787aa58f445919b809d89e252beef54f
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, UseLocalNTPInIncognito) {
517  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
518      "EmbeddedSearch", "Group1 use_cacheable_ntp:1"));
519  EXPECT_EQ(GURL(), chrome::GetNewTabPageURL(
520      profile()->GetOffTheRecordProfile()));
521}
522
523TEST_F(SearchTest, UseLocalNTPIfNTPURLIsInsecure) {
524  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
525      "EmbeddedSearch", "Group1 use_cacheable_ntp:1"));
526  // Set an insecure new tab page URL and verify that it's ignored.
527  SetSearchProvider(true, true);
528  EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
529            chrome::GetNewTabPageURL(profile()));
530}
531
532TEST_F(SearchTest, UseLocalNTPIfNTPURLIsNotSet) {
533  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
534      "EmbeddedSearch", "Group1 use_cacheable_ntp:1"));
535  // Set an insecure new tab page URL and verify that it's ignored.
536  SetSearchProvider(false, true);
537  EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
538            chrome::GetNewTabPageURL(profile()));
539}
540
541TEST_F(SearchTest, UseLocalNTPIfNTPURLIsBlockedForSupervisedUser) {
542  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
543      "EmbeddedSearch", "Group1 use_cacheable_ntp:1"));
544
545  // Block access to foo.com in the URL filter.
546  ManagedUserService* managed_user_service =
547      ManagedUserServiceFactory::GetForProfile(profile());
548  ManagedModeURLFilter* url_filter =
549      managed_user_service->GetURLFilterForUIThread();
550  std::map<std::string, bool> hosts;
551  hosts["foo.com"] = false;
552  url_filter->SetManualHosts(&hosts);
553
554  EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl),
555            chrome::GetNewTabPageURL(profile()));
556  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false));
557}
558
559TEST_F(SearchTest, GetInstantURL) {
560  // No Instant URL because "strk" is missing.
561  SetDefaultInstantTemplateUrl(false);
562  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false));
563
564  // Set an Instant URL with a valid search terms replacement key.
565  SetDefaultInstantTemplateUrl(true);
566
567  // Now there should be a valid Instant URL. Note the HTTPS "upgrade".
568  EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
569            GetInstantURL(profile(), kDisableStartMargin, false));
570
571  // Enable suggest. No difference.
572  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
573  EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
574            GetInstantURL(profile(), kDisableStartMargin, false));
575
576  // Disable suggest. No Instant URL.
577  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
578  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin, false));
579}
580
581TEST_F(SearchTest, StartMarginCGI) {
582  // No margin.
583  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
584
585  EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
586            GetInstantURL(profile(), kDisableStartMargin, false));
587
588  // With start margin.
589  EXPECT_EQ(GURL("https://foo.com/instant?es_sm=10&foo=foo#foo=foo&strk"),
590            GetInstantURL(profile(), 10, false));
591}
592
593TEST_F(SearchTest, InstantSearchEnabledCGI) {
594  // Disable Instant Search.
595  // Make sure {google:forceInstantResults} is not set in the Instant URL.
596  EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
597            GetInstantURL(profile(), kDisableStartMargin, false));
598
599  // Enable Instant Search.
600  // Make sure {google:forceInstantResults} is set in the Instant URL.
601  EXPECT_EQ(GURL("https://foo.com/instant?ion=1&foo=foo#foo=foo&strk"),
602            GetInstantURL(profile(), kDisableStartMargin, true));
603}
604
605TEST_F(SearchTest, CommandLineOverrides) {
606  GURL local_instant_url(GetLocalInstantURL(profile()));
607  EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url);
608
609  TemplateURLService* template_url_service =
610      TemplateURLServiceFactory::GetForProfile(profile());
611  TemplateURLData data;
612  data.SetURL("{google:baseURL}search?q={searchTerms}");
613  data.instant_url = "{google:baseURL}webhp?strk";
614  data.search_terms_replacement_key = "strk";
615  TemplateURL* template_url = new TemplateURL(profile(), data);
616  // Takes ownership of |template_url|.
617  template_url_service->Add(template_url);
618  template_url_service->SetDefaultSearchProvider(template_url);
619
620  // By default, Instant Extended forces the instant URL to be HTTPS, so even if
621  // we set a Google base URL that is HTTP, we should get an HTTPS URL.
622  UIThreadSearchTermsData::SetGoogleBaseURL("http://www.foo.com/");
623  GURL instant_url(GetInstantURL(profile(), kDisableStartMargin, false));
624  ASSERT_TRUE(instant_url.is_valid());
625  EXPECT_EQ("https://www.foo.com/webhp?strk", instant_url.spec());
626
627  // However, if the Google base URL is specified on the command line, the
628  // instant URL should just use it, even if it's HTTP.
629  UIThreadSearchTermsData::SetGoogleBaseURL(std::string());
630  CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
631                                                      "http://www.bar.com/");
632  instant_url = GetInstantURL(profile(), kDisableStartMargin, false);
633  ASSERT_TRUE(instant_url.is_valid());
634  EXPECT_EQ("http://www.bar.com/webhp?strk", instant_url.spec());
635
636  // Similarly, setting a Google base URL on the command line should allow you
637  // to get the Google version of the local NTP, even though search provider's
638  // URL doesn't contain "google".
639  local_instant_url = GetLocalInstantURL(profile());
640  EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), local_instant_url);
641
642  // If we specify extra search query params, they should be inserted into the
643  // query portion of the instant URL.
644  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
645      switches::kExtraSearchQueryParams, "a=b");
646  instant_url = GetInstantURL(profile(), kDisableStartMargin, false);
647  ASSERT_TRUE(instant_url.is_valid());
648  EXPECT_EQ("http://www.bar.com/webhp?a=b&strk", instant_url.spec());
649}
650
651TEST_F(SearchTest, ShouldShowInstantNTP_Default) {
652  EXPECT_FALSE(ShouldShowInstantNTP());
653}
654
655TEST_F(SearchTest, ShouldShowInstantNTP_DisabledViaFinch) {
656  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
657      "EmbeddedSearch", "Group1 show_ntp:0"));
658  EXPECT_FALSE(ShouldShowInstantNTP());
659}
660
661TEST_F(SearchTest, ShouldShowInstantNTP_DisabledByUseCacheableNTPFinchFlag) {
662  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
663      "EmbeddedSearch", "Group1 use_cacheable_ntp:1"));
664  EXPECT_FALSE(ShouldShowInstantNTP());
665}
666
667TEST_F(SearchTest, ShouldUseCacheableNTP_Default) {
668  EXPECT_TRUE(ShouldUseCacheableNTP());
669}
670
671TEST_F(SearchTest, ShouldUseCacheableNTP_EnabledViaFinch) {
672  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
673      "EmbeddedSearch", "Group1 use_cacheable_ntp:1"));
674  EXPECT_TRUE(ShouldUseCacheableNTP());
675}
676
677TEST_F(SearchTest, ShouldPrefetchSearchResults_Default) {
678  EXPECT_FALSE(ShouldPrefetchSearchResults());
679}
680
681TEST_F(SearchTest, ShouldPrefetchSearchResults_InstantExtendedAPIEnabled) {
682  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
683      "EmbeddedSearch",
684      "Group1 espv:2 use_cacheable_ntp:1 prefetch_results:1"));
685  EXPECT_TRUE(ShouldPrefetchSearchResults());
686#if defined(OS_IOS) || defined(OS_ANDROID)
687  EXPECT_EQ(1ul, EmbeddedSearchPageVersion());
688#else
689  EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
690#endif
691}
692
693TEST_F(SearchTest, ShouldPrefetchSearchResults_DisabledViaFinch) {
694  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
695      "EmbeddedSearch",
696      "Group1 use_cacheable_ntp:1 espv:89 prefetch_results:0"));
697  EXPECT_FALSE(ShouldPrefetchSearchResults());
698  EXPECT_EQ(89ul, EmbeddedSearchPageVersion());
699}
700
701TEST_F(SearchTest, ShouldPrefetchSearchResults_EnabledViaFinch) {
702  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
703      "EmbeddedSearch",
704      "Group1 espv:80 use_cacheable_ntp:1 prefetch_results:1"));
705  EXPECT_TRUE(ShouldPrefetchSearchResults());
706  EXPECT_EQ(80ul, EmbeddedSearchPageVersion());
707}
708
709TEST_F(SearchTest, IsNTPURL) {
710  GURL invalid_url;
711  GURL ntp_url(chrome::kChromeUINewTabURL);
712  GURL local_ntp_url(GetLocalInstantURL(profile()));
713
714  EXPECT_FALSE(chrome::IsNTPURL(invalid_url, profile()));
715  // No margin.
716  EnableQueryExtractionForTesting();
717  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
718  GURL remote_ntp_url(GetInstantURL(profile(), kDisableStartMargin, false));
719  GURL search_url_with_search_terms("https://foo.com/url?strk&bar=abc");
720  GURL search_url_without_search_terms("https://foo.com/url?strk&bar");
721
722  EXPECT_FALSE(chrome::IsNTPURL(ntp_url, profile()));
723  EXPECT_TRUE(chrome::IsNTPURL(local_ntp_url, profile()));
724  EXPECT_TRUE(chrome::IsNTPURL(remote_ntp_url, profile()));
725  EXPECT_FALSE(chrome::IsNTPURL(search_url_with_search_terms, profile()));
726  EXPECT_TRUE(chrome::IsNTPURL(search_url_without_search_terms, profile()));
727
728  EXPECT_FALSE(chrome::IsNTPURL(ntp_url, NULL));
729  EXPECT_FALSE(chrome::IsNTPURL(local_ntp_url, NULL));
730  EXPECT_FALSE(chrome::IsNTPURL(remote_ntp_url, NULL));
731  EXPECT_FALSE(chrome::IsNTPURL(search_url_with_search_terms, NULL));
732  EXPECT_FALSE(chrome::IsNTPURL(search_url_without_search_terms, NULL));
733}
734
735TEST_F(SearchTest, GetSearchURLs) {
736  std::vector<GURL> search_urls = GetSearchURLs(profile());
737  EXPECT_EQ(2U, search_urls.size());
738  EXPECT_EQ("http://foo.com/alt#quux=", search_urls[0].spec());
739  EXPECT_EQ("http://foo.com/url?bar=", search_urls[1].spec());
740}
741
742TEST_F(SearchTest, GetSearchResultPrefetchBaseURL) {
743  // "prefetch_results" flag is disabled.
744  EXPECT_EQ(GURL(), GetSearchResultPrefetchBaseURL(profile()));
745
746  // "prefetch_results" flag is enabled via field trials.
747  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
748      "EmbeddedSearch",
749      "Group1 espv:80 use_cacheable_ntp:1 prefetch_results:1"));
750  EXPECT_TRUE(ShouldPrefetchSearchResults());
751
752  EXPECT_EQ(GURL("https://foo.com/instant?ion=1&foo=foo#foo=foo&strk"),
753            GetSearchResultPrefetchBaseURL(profile()));
754}
755
756typedef SearchTest IsQueryExtractionEnabledTest;
757
758TEST_F(IsQueryExtractionEnabledTest, NotSet) {
759  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
760      "EmbeddedSearch", "Group1 espv:2"));
761  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
762  EXPECT_FALSE(IsQueryExtractionEnabled());
763  EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
764}
765
766TEST_F(IsQueryExtractionEnabledTest, EnabledViaFinch) {
767  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
768      "EmbeddedSearch", "Group1 espv:2 query_extraction:1"));
769  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
770  EXPECT_TRUE(IsQueryExtractionEnabled());
771  EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
772}
773
774TEST_F(IsQueryExtractionEnabledTest, DisabledViaFinch) {
775  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
776      "EmbeddedSearch", "Group1 espv:2 query_extraction:0"));
777  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
778  EXPECT_FALSE(IsQueryExtractionEnabled());
779  EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
780}
781
782TEST_F(IsQueryExtractionEnabledTest, EnabledViaCommandLine) {
783  EnableQueryExtractionForTesting();
784  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
785      "EmbeddedSearch", "Group1 espv:2 query_extraction:0"));
786  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
787  EXPECT_TRUE(IsQueryExtractionEnabled());
788  EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
789}
790
791typedef SearchTest ShouldHideTopVerbatimTest;
792
793TEST_F(ShouldHideTopVerbatimTest, DoNotHideByDefault) {
794  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
795                                                     "Control"));
796  EXPECT_FALSE(ShouldHideTopVerbatimMatch());
797}
798
799TEST_F(ShouldHideTopVerbatimTest, DoNotHideInInstantExtended) {
800  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
801                                                     "Group1"));
802  EXPECT_FALSE(ShouldHideTopVerbatimMatch());
803}
804
805TEST_F(ShouldHideTopVerbatimTest, EnableByFlagInInstantExtended) {
806  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
807                                                     "Group1 hide_verbatim:1"));
808  EXPECT_TRUE(ShouldHideTopVerbatimMatch());
809}
810
811TEST_F(ShouldHideTopVerbatimTest, EnableByFlagOutsideInstantExtended) {
812  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
813      "EmbeddedSearch", "Controll1 hide_verbatim:1"));
814  EXPECT_TRUE(ShouldHideTopVerbatimMatch());
815}
816
817TEST_F(ShouldHideTopVerbatimTest, DisableByFlag) {
818  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
819                                                     "Group1 hide_verbatim:0"));
820  EXPECT_FALSE(ShouldHideTopVerbatimMatch());
821}
822
823typedef SearchTest DisplaySearchButtonTest;
824
825TEST_F(DisplaySearchButtonTest, NotSet) {
826  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
827      "EmbeddedSearch", "Group1 espv:2"));
828  EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions());
829}
830
831TEST_F(DisplaySearchButtonTest, Never) {
832  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
833      "EmbeddedSearch", "Group1 espv:2 display_search_button:0"));
834  EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions());
835}
836
837TEST_F(DisplaySearchButtonTest, ForSearchTermReplacement) {
838  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
839      "EmbeddedSearch", "Group1 espv:2 display_search_button:1"));
840  EXPECT_EQ(DISPLAY_SEARCH_BUTTON_FOR_STR, GetDisplaySearchButtonConditions());
841}
842
843TEST_F(DisplaySearchButtonTest, ForSearchTermReplacementOrInputInProgress) {
844  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
845      "EmbeddedSearch", "Group1 espv:2 display_search_button:2"));
846  EXPECT_EQ(DISPLAY_SEARCH_BUTTON_FOR_STR_OR_IIP,
847            GetDisplaySearchButtonConditions());
848}
849
850TEST_F(DisplaySearchButtonTest, Always) {
851  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
852      "EmbeddedSearch", "Group1 espv:2 display_search_button:3"));
853  EXPECT_EQ(DISPLAY_SEARCH_BUTTON_ALWAYS, GetDisplaySearchButtonConditions());
854}
855
856TEST_F(DisplaySearchButtonTest, InvalidValue) {
857  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
858      "EmbeddedSearch", "Group1 espv:2 display_search_button:4"));
859  EXPECT_EQ(DISPLAY_SEARCH_BUTTON_NEVER, GetDisplaySearchButtonConditions());
860}
861
862typedef SearchTest OriginChipTest;
863
864TEST_F(OriginChipTest, NotSet) {
865  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
866      "EmbeddedSearch", "Group1 espv:2"));
867  EXPECT_FALSE(ShouldDisplayOriginChip());
868}
869
870TEST_F(OriginChipTest, NoOriginChip) {
871  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
872      "EmbeddedSearch", "Group1 espv:2 origin_chip:0"));
873  EXPECT_FALSE(ShouldDisplayOriginChip());
874}
875
876TEST_F(OriginChipTest, OriginChip) {
877  ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
878      "EmbeddedSearch", "Group1 espv:2 origin_chip:1"));
879  EXPECT_TRUE(ShouldDisplayOriginChip());
880}
881
882}  // namespace chrome
883