search_unittest.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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/search.h"
12#include "chrome/browser/search_engines/template_url_service.h"
13#include "chrome/browser/search_engines/template_url_service_factory.h"
14#include "chrome/browser/ui/tabs/tab_strip_model.h"
15#include "chrome/common/chrome_switches.h"
16#include "chrome/common/metrics/entropy_provider.h"
17#include "chrome/common/pref_names.h"
18#include "chrome/common/url_constants.h"
19#include "chrome/test/base/browser_with_test_window_test.h"
20#include "chrome/test/base/ui_test_utils.h"
21#include "content/public/browser/web_contents.h"
22
23namespace chrome {
24
25TEST(EmbeddedSearchFieldTrialTest, GetFieldTrialInfo) {
26  FieldTrialFlags flags;
27  uint64 group_number = 0;
28  const uint64 ZERO = 0;
29
30  EXPECT_FALSE(GetFieldTrialInfo(std::string(), &flags, &group_number));
31  EXPECT_EQ(ZERO, group_number);
32  EXPECT_EQ(ZERO, flags.size());
33
34  EXPECT_TRUE(GetFieldTrialInfo("Group77", &flags, &group_number));
35  EXPECT_EQ(uint64(77), group_number);
36  EXPECT_EQ(ZERO, flags.size());
37
38  group_number = 0;
39  EXPECT_FALSE(GetFieldTrialInfo("Group77.2", &flags, &group_number));
40  EXPECT_EQ(ZERO, group_number);
41  EXPECT_EQ(ZERO, flags.size());
42
43  EXPECT_FALSE(GetFieldTrialInfo("Invalid77", &flags, &group_number));
44  EXPECT_EQ(ZERO, group_number);
45  EXPECT_EQ(ZERO, flags.size());
46
47  EXPECT_FALSE(GetFieldTrialInfo("Invalid77", &flags, NULL));
48  EXPECT_EQ(ZERO, flags.size());
49
50  EXPECT_TRUE(GetFieldTrialInfo("Group77 ", &flags, &group_number));
51  EXPECT_EQ(uint64(77), group_number);
52  EXPECT_EQ(ZERO, flags.size());
53
54  group_number = 0;
55  flags.clear();
56  EXPECT_EQ(uint64(9999), GetUInt64ValueForFlagWithDefault("foo", 9999, flags));
57  EXPECT_TRUE(GetFieldTrialInfo("Group77 foo:6", &flags, &group_number));
58  EXPECT_EQ(uint64(77), group_number);
59  EXPECT_EQ(uint64(1), flags.size());
60  EXPECT_EQ(uint64(6), GetUInt64ValueForFlagWithDefault("foo", 9999, flags));
61
62  group_number = 0;
63  flags.clear();
64  EXPECT_TRUE(GetFieldTrialInfo(
65      "Group77 bar:1 baz:7 cat:dogs", &flags, &group_number));
66  EXPECT_EQ(uint64(77), group_number);
67  EXPECT_EQ(uint64(3), flags.size());
68  EXPECT_EQ(true, GetBoolValueForFlagWithDefault("bar", false, flags));
69  EXPECT_EQ(uint64(7), GetUInt64ValueForFlagWithDefault("baz", 0, flags));
70  EXPECT_EQ("dogs",
71            GetStringValueForFlagWithDefault("cat", std::string(), flags));
72  EXPECT_EQ("default",
73            GetStringValueForFlagWithDefault("moose", "default", flags));
74
75  group_number = 0;
76  flags.clear();
77  EXPECT_FALSE(GetFieldTrialInfo(
78      "Group77 bar:1 baz:7 cat:dogs DISABLED", &flags, &group_number));
79  EXPECT_EQ(ZERO, group_number);
80  EXPECT_EQ(ZERO, flags.size());
81}
82
83class InstantExtendedAPIEnabledTest : public testing::Test {
84 public:
85  InstantExtendedAPIEnabledTest() : histogram_(NULL) {
86  }
87 protected:
88  virtual void SetUp() {
89    field_trial_list_.reset(new base::FieldTrialList(
90        new metrics::SHA1EntropyProvider("42")));
91    base::StatisticsRecorder::Initialize();
92    ResetInstantExtendedOptInStateGateForTest();
93    previous_metrics_count_.resize(INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT, 0);
94    base::HistogramBase* histogram = GetHistogram();
95    if (histogram) {
96      scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
97      if (samples.get()) {
98        for (int state = INSTANT_EXTENDED_NOT_SET;
99             state < INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT; ++state) {
100          previous_metrics_count_[state] = samples->GetCount(state);
101        }
102      }
103    }
104  }
105
106  virtual CommandLine* GetCommandLine() const {
107    return CommandLine::ForCurrentProcess();
108  }
109
110  void ValidateMetrics(base::HistogramBase::Sample value) {
111    base::HistogramBase* histogram = GetHistogram();
112    if (histogram) {
113      scoped_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
114      if (samples.get()) {
115        for (int state = INSTANT_EXTENDED_NOT_SET;
116             state < INSTANT_EXTENDED_OPT_IN_STATE_ENUM_COUNT; ++state) {
117          if (state == value) {
118            EXPECT_EQ(previous_metrics_count_[state] + 1,
119                      samples->GetCount(state));
120          } else {
121            EXPECT_EQ(previous_metrics_count_[state], samples->GetCount(state));
122          }
123        }
124      }
125    }
126  }
127
128 private:
129  base::HistogramBase* GetHistogram() {
130    if (!histogram_) {
131      histogram_ = base::StatisticsRecorder::FindHistogram(
132          "InstantExtended.OptInState");
133    }
134    return histogram_;
135  }
136  base::HistogramBase* histogram_;
137  scoped_ptr<base::FieldTrialList> field_trial_list_;
138  std::vector<int> previous_metrics_count_;
139};
140
141TEST_F(InstantExtendedAPIEnabledTest, EnabledViaCommandLineFlag) {
142  GetCommandLine()->AppendSwitch(switches::kEnableInstantExtendedAPI);
143  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
144  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
145#if defined(OS_IOS) || defined(OS_ANDROID)
146  EXPECT_EQ(1ul, EmbeddedSearchPageVersion());
147#else
148  EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
149#endif
150  ValidateMetrics(INSTANT_EXTENDED_OPT_IN);
151}
152
153TEST_F(InstantExtendedAPIEnabledTest, EnabledViaFinchFlag) {
154  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
155      "InstantExtended/Group1 espv:42/"));
156  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
157  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
158  EXPECT_EQ(42ul, EmbeddedSearchPageVersion());
159  ValidateMetrics(INSTANT_EXTENDED_NOT_SET);
160}
161
162TEST_F(InstantExtendedAPIEnabledTest, DisabledViaCommandLineFlag) {
163  GetCommandLine()->AppendSwitch(switches::kDisableInstantExtendedAPI);
164  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
165      "InstantExtended/Group1 espv:2/"));
166  EXPECT_FALSE(IsInstantExtendedAPIEnabled());
167  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
168  EXPECT_EQ(0ul, EmbeddedSearchPageVersion());
169  ValidateMetrics(INSTANT_EXTENDED_OPT_OUT);
170}
171
172TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyEnabledViaCommandLineFlag) {
173  GetCommandLine()->AppendSwitch(switches::kEnableLocalOnlyInstantExtendedAPI);
174  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
175  EXPECT_TRUE(IsLocalOnlyInstantExtendedAPIEnabled());
176  EXPECT_EQ(0ul, EmbeddedSearchPageVersion());
177  ValidateMetrics(INSTANT_EXTENDED_OPT_IN_LOCAL);
178}
179
180TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyEnabledViaFinch) {
181  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
182      "InstantExtended/Group1 local_only:1/"));
183  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
184  EXPECT_TRUE(IsLocalOnlyInstantExtendedAPIEnabled());
185  EXPECT_EQ(0ul, EmbeddedSearchPageVersion());
186  ValidateMetrics(INSTANT_EXTENDED_NOT_SET);
187}
188
189TEST_F(InstantExtendedAPIEnabledTest, BothLocalAndRegularOptOutCommandLine) {
190  GetCommandLine()->AppendSwitch(switches::kDisableLocalOnlyInstantExtendedAPI);
191  GetCommandLine()->AppendSwitch(switches::kDisableInstantExtendedAPI);
192  EXPECT_FALSE(IsInstantExtendedAPIEnabled());
193  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
194  ValidateMetrics(INSTANT_EXTENDED_OPT_OUT_BOTH);
195}
196
197TEST_F(InstantExtendedAPIEnabledTest, BothLocalAndRegularOptInCommandLine) {
198  GetCommandLine()->AppendSwitch(switches::kEnableLocalOnlyInstantExtendedAPI);
199  GetCommandLine()->AppendSwitch(switches::kEnableInstantExtendedAPI);
200  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
201  EXPECT_TRUE(IsLocalOnlyInstantExtendedAPIEnabled());
202  ValidateMetrics(INSTANT_EXTENDED_OPT_IN_LOCAL);
203}
204
205TEST_F(InstantExtendedAPIEnabledTest,
206       LocalOnlyCommandLineTrumpedByCommandLine) {
207  GetCommandLine()->AppendSwitch(switches::kEnableLocalOnlyInstantExtendedAPI);
208  GetCommandLine()->AppendSwitch(switches::kDisableInstantExtendedAPI);
209  EXPECT_FALSE(IsInstantExtendedAPIEnabled());
210  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
211  EXPECT_EQ(0ul, EmbeddedSearchPageVersion());
212  ValidateMetrics(INSTANT_EXTENDED_OPT_OUT);
213}
214
215TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyCommandLineTrumpsFinch) {
216  GetCommandLine()->AppendSwitch(switches::kEnableLocalOnlyInstantExtendedAPI);
217  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
218      "InstantExtended/Group1 espv:2/"));
219  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
220  EXPECT_TRUE(IsLocalOnlyInstantExtendedAPIEnabled());
221  EXPECT_EQ(0ul, EmbeddedSearchPageVersion());
222  ValidateMetrics(INSTANT_EXTENDED_OPT_IN_LOCAL);
223}
224
225TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyFinchTrumpedByCommandLine) {
226  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
227      "InstantExtended/Group1 local_only:1/"));
228  GetCommandLine()->AppendSwitch(switches::kDisableInstantExtendedAPI);
229  EXPECT_FALSE(IsInstantExtendedAPIEnabled());
230  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
231  EXPECT_EQ(0ul, EmbeddedSearchPageVersion());
232  ValidateMetrics(INSTANT_EXTENDED_OPT_OUT);
233}
234
235TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyFinchTrumpsFinch) {
236  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
237      "InstantExtended/Group1 espv:1 local_only:1/"));
238  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
239  EXPECT_TRUE(IsLocalOnlyInstantExtendedAPIEnabled());
240  EXPECT_EQ(0ul, EmbeddedSearchPageVersion());
241  ValidateMetrics(INSTANT_EXTENDED_NOT_SET);
242}
243
244TEST_F(InstantExtendedAPIEnabledTest, LocalOnlyDisabledViaCommandLineFlag) {
245  GetCommandLine()->AppendSwitch(switches::kDisableLocalOnlyInstantExtendedAPI);
246  ASSERT_TRUE(base::FieldTrialList::CreateTrialsFromString(
247      "InstantExtended/Group1 espv:2/"));
248  EXPECT_TRUE(IsInstantExtendedAPIEnabled());
249  EXPECT_FALSE(IsLocalOnlyInstantExtendedAPIEnabled());
250  EXPECT_EQ(2ul, EmbeddedSearchPageVersion());
251  ValidateMetrics(INSTANT_EXTENDED_OPT_OUT_LOCAL);
252}
253
254class SearchTest : public BrowserWithTestWindowTest {
255 protected:
256  virtual void SetUp() OVERRIDE {
257    BrowserWithTestWindowTest::SetUp();
258    TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
259        profile(), &TemplateURLServiceFactory::BuildInstanceFor);
260    TemplateURLService* template_url_service =
261        TemplateURLServiceFactory::GetForProfile(profile());
262    ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
263    SetSearchProvider(false);
264  }
265
266  void SetSearchProvider(bool is_google) {
267    TemplateURLService* template_url_service =
268        TemplateURLServiceFactory::GetForProfile(profile());
269    TemplateURLData data;
270    if (is_google) {
271      data.SetURL("http://www.google.com/");
272      data.instant_url = "http://www.google.com/";
273    } else {
274      data.SetURL("http://foo.com/url?bar={searchTerms}");
275      data.instant_url = "http://foo.com/instant?"
276          "{google:omniboxStartMarginParameter}foo=foo#foo=foo";
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};
311
312struct SearchTestCase {
313  const char* url;
314  bool expected_result;
315  const char* comment;
316};
317
318TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedDisabled) {
319  const SearchTestCase kTestCases[] = {
320    {"chrome-search://foo/bar",                 true,  ""},
321    {"http://foo.com/instant",                  true,  ""},
322    {"http://foo.com/instant?foo=bar",          true,  ""},
323    {"https://foo.com/instant",                 true,  ""},
324    {"https://foo.com/instant#foo=bar",         true,  ""},
325    {"HtTpS://fOo.CoM/instant",                 true,  ""},
326    {"http://foo.com:80/instant",               true,  ""},
327    {"invalid URL",                             false, "Invalid URL"},
328    {"unknown://scheme/path",                   false, "Unknown scheme"},
329    {"ftp://foo.com/instant",                   false, "Non-HTTP scheme"},
330    {"http://sub.foo.com/instant",              false, "Non-exact host"},
331    {"http://foo.com:26/instant",               false, "Non-default port"},
332    {"http://foo.com/instant/bar",              false, "Non-exact path"},
333    {"http://foo.com/Instant",                  false, "Case sensitive path"},
334    {"http://foo.com/",                         false, "Non-exact path"},
335    {"https://foo.com/",                        false, "Non-exact path"},
336    {"https://foo.com/url?strk",                false, "Non-extended mode"},
337    {"https://foo.com/alt?strk",                false, "Non-extended mode"},
338  };
339
340  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
341    const SearchTestCase& test = kTestCases[i];
342    EXPECT_EQ(test.expected_result,
343              ShouldAssignURLToInstantRenderer(GURL(test.url), profile()))
344        << test.url << " " << test.comment;
345  }
346}
347
348TEST_F(SearchTest, ShouldAssignURLToInstantRendererExtendedEnabled) {
349  EnableInstantExtendedAPIForTesting();
350
351  const SearchTestCase kTestCases[] = {
352    {chrome::kChromeSearchLocalNtpUrl, true,  ""},
353    {chrome::kChromeSearchLocalGoogleNtpUrl, true,  ""},
354    {"https://foo.com/instant?strk",   true,  ""},
355    {"https://foo.com/instant#strk",   true,  ""},
356    {"https://foo.com/instant?strk=0", true,  ""},
357    {"https://foo.com/url?strk",       true,  ""},
358    {"https://foo.com/alt?strk",       true,  ""},
359    {"http://foo.com/instant",         false, "Non-HTTPS"},
360    {"http://foo.com/instant?strk",    false, "Non-HTTPS"},
361    {"http://foo.com/instant?strk=1",  false, "Non-HTTPS"},
362    {"https://foo.com/instant",        false, "No search terms replacement"},
363    {"https://foo.com/?strk",          false, "Non-exact path"},
364  };
365
366  for (size_t i = 0; i < arraysize(kTestCases); ++i) {
367    const SearchTestCase& test = kTestCases[i];
368    EXPECT_EQ(test.expected_result,
369              ShouldAssignURLToInstantRenderer(GURL(test.url), profile()))
370        << test.url << " " << test.comment;
371  }
372}
373
374TEST_F(SearchTest, CoerceCommandLineURLToTemplateURL) {
375  TemplateURL* template_url =
376      TemplateURLServiceFactory::GetForProfile(profile())->
377          GetDefaultSearchProvider();
378  EXPECT_EQ(
379      GURL("https://foo.com/dev?bar=bar#bar=bar"),
380      CoerceCommandLineURLToTemplateURL(
381          GURL("http://myserver.com:9000/dev?bar=bar#bar=bar"),
382          template_url->instant_url_ref(), kDisableStartMargin));
383}
384
385const SearchTestCase kInstantNTPTestCases[] = {
386  {"https://foo.com/instant?strk",         true,  "Valid Instant URL"},
387  {"https://foo.com/instant#strk",         true,  "Valid Instant URL"},
388  {"https://foo.com/url?strk",             true,  "Valid search URL"},
389  {"https://foo.com/url#strk",             true,  "Valid search URL"},
390  {"https://foo.com/alt?strk",             true,  "Valid alternative URL"},
391  {"https://foo.com/alt#strk",             true,  "Valid alternative URL"},
392  {"https://foo.com/url?strk&bar=",        true,  "No query terms"},
393  {"https://foo.com/url?strk&q=abc",       true,  "No query terms key"},
394  {"https://foo.com/url?strk#bar=abc",     true,  "Query terms key in ref"},
395  {"https://foo.com/url?strk&bar=abc",     false, "Has query terms"},
396  {"http://foo.com/instant?strk=1",        false, "Insecure URL"},
397  {"https://foo.com/instant",              false, "No search term replacement"},
398  {"chrome://blank/",                      false, "Chrome scheme"},
399  {"chrome-search://foo",                   false, "Chrome-search scheme"},
400  {chrome::kChromeSearchLocalNtpUrl,       true,  "Local new tab page"},
401  {chrome::kChromeSearchLocalGoogleNtpUrl, true,  "Local new tab page"},
402  {"https://bar.com/instant?strk=1",       false, "Random non-search page"},
403};
404
405TEST_F(SearchTest, InstantNTPExtendedEnabled) {
406  EnableInstantExtendedAPIForTesting();
407  AddTab(browser(), GURL("chrome://blank"));
408  for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
409    const SearchTestCase& test = kInstantNTPTestCases[i];
410    NavigateAndCommitActiveTab(GURL(test.url));
411    SetSearchProvider(test.url == chrome::kChromeSearchLocalGoogleNtpUrl);
412    const content::WebContents* contents =
413        browser()->tab_strip_model()->GetWebContentsAt(0);
414    EXPECT_EQ(test.expected_result, IsInstantNTP(contents))
415        << test.url << " " << test.comment;
416  }
417}
418
419TEST_F(SearchTest, InstantNTPExtendedDisabled) {
420  AddTab(browser(), GURL("chrome://blank"));
421  for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
422    const SearchTestCase& test = kInstantNTPTestCases[i];
423    NavigateAndCommitActiveTab(GURL(test.url));
424    const content::WebContents* contents =
425        browser()->tab_strip_model()->GetWebContentsAt(0);
426    EXPECT_FALSE(IsInstantNTP(contents)) << test.url << " " << test.comment;
427  }
428}
429
430TEST_F(SearchTest, InstantNTPCustomNavigationEntry) {
431  EnableInstantExtendedAPIForTesting();
432  AddTab(browser(), GURL("chrome://blank"));
433  for (size_t i = 0; i < arraysize(kInstantNTPTestCases); ++i) {
434    const SearchTestCase& test = kInstantNTPTestCases[i];
435    NavigateAndCommitActiveTab(GURL(test.url));
436    SetSearchProvider(test.url == chrome::kChromeSearchLocalGoogleNtpUrl);
437    content::WebContents* contents =
438        browser()->tab_strip_model()->GetWebContentsAt(0);
439    content::NavigationController& controller = contents->GetController();
440    controller.SetTransientEntry(
441        controller.CreateNavigationEntry(GURL("chrome://blank"),
442                                         content::Referrer(),
443                                         content::PAGE_TRANSITION_LINK,
444                                         false,
445                                         std::string(),
446                                         contents->GetBrowserContext()));
447    // The active entry is chrome://blank and not an NTP.
448    EXPECT_FALSE(IsInstantNTP(contents));
449    EXPECT_EQ(test.expected_result,
450              NavEntryIsInstantNTP(contents,
451                                   controller.GetLastCommittedEntry()))
452        << test.url << " " << test.comment;
453  }
454}
455
456TEST_F(SearchTest, GetInstantURLExtendedDisabled) {
457  // Instant is disabled, so no Instant URL.
458  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
459
460  // Enable Instant.
461  profile()->GetPrefs()->SetBoolean(prefs::kInstantEnabled, true);
462  EXPECT_EQ(GURL("http://foo.com/instant?foo=foo#foo=foo"),
463            GetInstantURL(profile(), kDisableStartMargin));
464
465  // Override the Instant URL on the commandline.
466  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
467      switches::kInstantURL,
468      "http://myserver.com:9000/dev?bar=bar#bar=bar");
469  EXPECT_EQ(GURL("http://myserver.com:9000/dev?bar=bar#bar=bar"),
470            GetInstantURL(profile(), kDisableStartMargin));
471}
472
473TEST_F(SearchTest, GetInstantURLExtendedEnabled) {
474  EnableInstantExtendedAPIForTesting();
475
476  // Instant is disabled, so no Instant URL.
477  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
478
479  // Enable Instant. Still no Instant URL because "strk" is missing.
480  profile()->GetPrefs()->SetBoolean(prefs::kInstantExtendedEnabled, true);
481  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
482
483  // Set an Instant URL with a valid search terms replacement key.
484  SetDefaultInstantTemplateUrl(true);
485
486  // Now there should be a valid Instant URL. Note the HTTPS "upgrade".
487  EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
488            GetInstantURL(profile(), kDisableStartMargin));
489
490  // Enable suggest. No difference.
491  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
492  EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
493            GetInstantURL(profile(), kDisableStartMargin));
494
495  // Disable Instant. No difference, because suggest is still enabled.
496  profile()->GetPrefs()->SetBoolean(prefs::kInstantExtendedEnabled, false);
497  EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
498            GetInstantURL(profile(), kDisableStartMargin));
499
500  // Override the Instant URL on the commandline. Oops, forgot "strk".
501  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
502      switches::kInstantURL,
503      "http://myserver.com:9000/dev?bar=bar#bar=bar");
504  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
505
506  // Override with "strk". For fun, put it in the query, instead of the ref.
507  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
508      switches::kInstantURL,
509      "http://myserver.com:9000/dev?bar=bar&strk#bar=bar");
510  EXPECT_EQ(GURL("http://myserver.com:9000/dev?bar=bar&strk#bar=bar"),
511            GetInstantURL(profile(), kDisableStartMargin));
512
513  // Disable suggest. No Instant URL.
514  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
515  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
516}
517
518TEST_F(SearchTest, StartMarginCGI) {
519  // Instant is disabled, so no Instant URL.
520  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
521
522  // Enable Instant.  No margin.
523  profile()->GetPrefs()->SetBoolean(prefs::kInstantEnabled, true);
524  EXPECT_EQ(GURL("http://foo.com/instant?foo=foo#foo=foo"),
525            GetInstantURL(profile(), kDisableStartMargin));
526
527  // With start margin.
528  EXPECT_EQ(GURL("http://foo.com/instant?es_sm=10&foo=foo#foo=foo"),
529            GetInstantURL(profile(), 10));
530}
531
532TEST_F(SearchTest, DefaultSearchProviderSupportsInstant) {
533  EnableInstantExtendedAPIForTesting();
534
535  // Enable Instant. Still no Instant URL because "strk" is missing.
536  profile()->GetPrefs()->SetBoolean(prefs::kInstantExtendedEnabled, true);
537
538  // No default search provider support yet.
539  EXPECT_FALSE(DefaultSearchProviderSupportsInstant(profile()));
540
541  // Set an Instant URL with a valid search terms replacement key.
542  SetDefaultInstantTemplateUrl(true);
543
544  // Default search provider should now support instant.
545  EXPECT_TRUE(DefaultSearchProviderSupportsInstant(profile()));
546  // Enable suggest. No difference.
547  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
548  EXPECT_TRUE(DefaultSearchProviderSupportsInstant(profile()));
549
550  // Disable Instant. No difference.
551  profile()->GetPrefs()->SetBoolean(prefs::kInstantExtendedEnabled, false);
552  EXPECT_TRUE(DefaultSearchProviderSupportsInstant(profile()));
553
554  // Override the Instant URL on the commandline. Oops, forgot "strk".
555  CommandLine::ForCurrentProcess()->AppendSwitchASCII(
556      switches::kInstantURL,
557      "http://myserver.com:9000/dev?bar=bar#bar=bar");
558  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
559
560  // Check that command line overrides don't affect the default search provider.
561  EXPECT_TRUE(DefaultSearchProviderSupportsInstant(profile()));
562
563  // Disable suggest. No Instant URL.
564  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
565  EXPECT_EQ(GURL(), GetInstantURL(profile(), kDisableStartMargin));
566  // Even with suggest disabled, the default search provider still supports
567  // instant.
568  EXPECT_TRUE(DefaultSearchProviderSupportsInstant(profile()));
569
570  // Set an Instant URL with no valid search terms replacement key.
571  SetDefaultInstantTemplateUrl(false);
572
573  EXPECT_FALSE(DefaultSearchProviderSupportsInstant(profile()));
574}
575
576TEST_F(SearchTest, IsInstantCheckboxEnabledExtendedDisabled) {
577  // Enable suggest.
578  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
579
580  // Set an Instant URL with a valid search terms replacement key.
581  SetDefaultInstantTemplateUrl(true);
582
583  const char* pref_name = GetInstantPrefName();
584  profile()->GetPrefs()->SetBoolean(pref_name, true);
585
586  EXPECT_TRUE(IsInstantCheckboxEnabled(profile()));
587  EXPECT_TRUE(IsInstantCheckboxChecked(profile()));
588
589  // Set an Instant URL with no valid search terms replacement key.
590  SetDefaultInstantTemplateUrl(false);
591
592  // For non-extended instant, the checkbox should still be enabled and checked.
593  EXPECT_TRUE(IsInstantCheckboxEnabled(profile()));
594  EXPECT_TRUE(IsInstantCheckboxChecked(profile()));
595
596  // Disable suggest.
597  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
598
599  // With suggest off, the checkbox should now be disabled and unchecked.
600  EXPECT_FALSE(IsInstantCheckboxEnabled(profile()));
601  EXPECT_FALSE(IsInstantCheckboxChecked(profile()));
602}
603
604TEST_F(SearchTest, IsInstantCheckboxEnabledExtendedEnabled) {
605  // Enable instant extended.
606  EnableInstantExtendedAPIForTesting();
607
608  // Enable suggest.
609  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
610
611  // Set an Instant URL with a valid search terms replacement key.
612  SetDefaultInstantTemplateUrl(true);
613
614  const char* pref_name = GetInstantPrefName();
615  profile()->GetPrefs()->SetBoolean(pref_name, true);
616
617  EXPECT_TRUE(IsInstantCheckboxEnabled(profile()));
618  EXPECT_TRUE(IsInstantCheckboxChecked(profile()));
619
620  // Set an Instant URL with no valid search terms replacement key.
621  SetDefaultInstantTemplateUrl(false);
622
623  // For extended instant, the checkbox should now be disabled.
624  EXPECT_FALSE(IsInstantCheckboxEnabled(profile()));
625
626  // Disable suggest.
627  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, false);
628
629  EXPECT_FALSE(IsInstantCheckboxEnabled(profile()));
630  EXPECT_FALSE(IsInstantCheckboxChecked(profile()));
631
632  // Set an Instant URL with a search terms replacement key.
633  SetDefaultInstantTemplateUrl(true);
634
635  // Should still be disabled, since suggest is still off.
636  EXPECT_FALSE(IsInstantCheckboxEnabled(profile()));
637
638  profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled, true);
639
640  // Now that suggest is back on and the instant url is good, the checkbox
641  // should be enabled and checked again.
642  EXPECT_TRUE(IsInstantCheckboxEnabled(profile()));
643  EXPECT_TRUE(IsInstantCheckboxChecked(profile()));
644}
645
646
647}  // namespace chrome
648