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.
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/prefs/pref_service.h"
10 #include "base/strings/utf_string_conversions.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/template_url_service_factory.h"
15 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/common/url_constants.h"
20 #include "chrome/test/base/browser_with_test_window_test.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "components/google/core/browser/google_switches.h"
23 #include "components/search/search.h"
24 #include "components/search_engines/search_engines_switches.h"
25 #include "components/search_engines/template_url_service.h"
26 #include "components/variations/entropy_provider.h"
27 #include "content/public/browser/navigation_entry.h"
28 #include "content/public/browser/render_process_host.h"
29 #include "content/public/browser/render_view_host.h"
30 #include "content/public/browser/site_instance.h"
31 #include "content/public/browser/web_contents.h"
32 #include "content/public/common/renderer_preferences.h"
35 #if defined(ENABLE_SUPERVISED_USERS)
36 #include "chrome/browser/supervised_user/supervised_user_service.h"
37 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
38 #include "chrome/browser/supervised_user/supervised_user_url_filter.h"
43 class SearchTest
: public BrowserWithTestWindowTest
{
45 void SetUp() override
{
46 BrowserWithTestWindowTest::SetUp();
47 field_trial_list_
.reset(new base::FieldTrialList(
48 new metrics::SHA1EntropyProvider("42")));
49 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
50 profile(), &TemplateURLServiceFactory::BuildInstanceFor
);
51 TemplateURLService
* template_url_service
=
52 TemplateURLServiceFactory::GetForProfile(profile());
53 ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service
);
54 SetSearchProvider(true, false);
57 virtual void SetSearchProvider(bool set_ntp_url
, bool insecure_ntp_url
) {
58 TemplateURLService
* template_url_service
=
59 TemplateURLServiceFactory::GetForProfile(profile());
61 data
.SetShortName(base::ASCIIToUTF16("foo.com"));
62 data
.SetURL("http://foo.com/url?bar={searchTerms}");
63 data
.instant_url
= "http://foo.com/instant?"
64 "{google:forceInstantResults}foo=foo#foo=foo&strk";
66 data
.new_tab_url
= (insecure_ntp_url
? "http" : "https") +
67 std::string("://foo.com/newtab?strk");
69 data
.alternate_urls
.push_back("http://foo.com/alt#quux={searchTerms}");
70 data
.search_terms_replacement_key
= "strk";
72 TemplateURL
* template_url
= new TemplateURL(data
);
73 // Takes ownership of |template_url|.
74 template_url_service
->Add(template_url
);
75 template_url_service
->SetUserSelectedDefaultSearchProvider(template_url
);
78 // Build an Instant URL with or without a valid search terms replacement key
79 // as per |has_search_term_replacement_key|. Set that URL as the instant URL
80 // for the default search provider.
81 void SetDefaultInstantTemplateUrl(bool has_search_term_replacement_key
) {
82 TemplateURLService
* template_url_service
=
83 TemplateURLServiceFactory::GetForProfile(profile());
85 static const char kInstantURLWithStrk
[] =
86 "http://foo.com/instant?foo=foo#foo=foo&strk";
87 static const char kInstantURLNoStrk
[] =
88 "http://foo.com/instant?foo=foo#foo=foo";
91 data
.SetShortName(base::ASCIIToUTF16("foo.com"));
92 data
.SetURL("http://foo.com/url?bar={searchTerms}");
93 data
.instant_url
= (has_search_term_replacement_key
?
94 kInstantURLWithStrk
: kInstantURLNoStrk
);
95 data
.search_terms_replacement_key
= "strk";
97 TemplateURL
* template_url
= new TemplateURL(data
);
98 // Takes ownership of |template_url|.
99 template_url_service
->Add(template_url
);
100 template_url_service
->SetUserSelectedDefaultSearchProvider(template_url
);
103 bool InInstantProcess(const content::WebContents
* contents
) {
104 InstantService
* instant_service
=
105 InstantServiceFactory::GetForProfile(profile());
106 return instant_service
->IsInstantProcess(
107 contents
->GetRenderProcessHost()->GetID());
110 scoped_ptr
<base::FieldTrialList
> field_trial_list_
;
113 struct SearchTestCase
{
115 bool expected_result
;
119 TEST_F(SearchTest
, ShouldAssignURLToInstantRendererExtendedEnabled
) {
120 EnableQueryExtractionForTesting();
122 const SearchTestCase kTestCases
[] = {
123 {chrome::kChromeSearchLocalNtpUrl
, true, ""},
124 {"https://foo.com/instant?strk", true, ""},
125 {"https://foo.com/instant#strk", true, ""},
126 {"https://foo.com/instant?strk=0", true, ""},
127 {"https://foo.com/url?strk", true, ""},
128 {"https://foo.com/alt?strk", true, ""},
129 {"http://foo.com/instant", false, "Non-HTTPS"},
130 {"http://foo.com/instant?strk", false, "Non-HTTPS"},
131 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"},
132 {"https://foo.com/instant", false, "No search terms replacement"},
133 {"https://foo.com/?strk", false, "Non-exact path"},
136 for (size_t i
= 0; i
< arraysize(kTestCases
); ++i
) {
137 const SearchTestCase
& test
= kTestCases
[i
];
138 EXPECT_EQ(test
.expected_result
,
139 ShouldAssignURLToInstantRenderer(GURL(test
.url
), profile()))
140 << test
.url
<< " " << test
.comment
;
144 TEST_F(SearchTest
, ShouldAssignURLToInstantRendererExtendedEnabledNotOnSRP
) {
145 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
146 "EmbeddedSearch", "Group1 espv:2 suppress_on_srp:1"));
148 const SearchTestCase kTestCases
[] = {
149 {chrome::kChromeSearchLocalNtpUrl
, true, ""},
150 {"https://foo.com/instant?strk", true, ""},
151 {"https://foo.com/instant#strk", true, ""},
152 {"https://foo.com/instant?strk=0", true, ""},
153 {"https://foo.com/url?strk", false, "Disabled on SRP"},
154 {"https://foo.com/alt?strk", false, "Disabled ON SRP"},
155 {"http://foo.com/instant", false, "Non-HTTPS"},
156 {"http://foo.com/instant?strk", false, "Non-HTTPS"},
157 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"},
158 {"https://foo.com/instant", false, "No search terms replacement"},
159 {"https://foo.com/?strk", false, "Non-exact path"},
162 for (size_t i
= 0; i
< arraysize(kTestCases
); ++i
) {
163 const SearchTestCase
& test
= kTestCases
[i
];
164 EXPECT_EQ(test
.expected_result
,
165 ShouldAssignURLToInstantRenderer(GURL(test
.url
), profile()))
166 << test
.url
<< " " << test
.comment
;
170 TEST_F(SearchTest
, ShouldUseProcessPerSiteForInstantURL
) {
171 EnableQueryExtractionForTesting();
173 const SearchTestCase kTestCases
[] = {
174 {"chrome-search://local-ntp", true, "Local NTP"},
175 {"chrome-search://remote-ntp", true, "Remote NTP"},
176 {"invalid-scheme://local-ntp", false, "Invalid Local NTP URL"},
177 {"invalid-scheme://online-ntp", false, "Invalid Online NTP URL"},
178 {"chrome-search://foo.com", false, "Search result page"},
179 {"https://foo.com/instant?strk", false, ""},
180 {"https://foo.com/instant#strk", false, ""},
181 {"https://foo.com/instant?strk=0", false, ""},
182 {"https://foo.com/url?strk", false, ""},
183 {"https://foo.com/alt?strk", false, ""},
184 {"http://foo.com/instant", false, "Non-HTTPS"},
185 {"http://foo.com/instant?strk", false, "Non-HTTPS"},
186 {"http://foo.com/instant?strk=1", false, "Non-HTTPS"},
187 {"https://foo.com/instant", false, "No search terms replacement"},
188 {"https://foo.com/?strk", false, "Non-exact path"},
191 for (size_t i
= 0; i
< arraysize(kTestCases
); ++i
) {
192 const SearchTestCase
& test
= kTestCases
[i
];
193 EXPECT_EQ(test
.expected_result
,
194 ShouldUseProcessPerSiteForInstantURL(GURL(test
.url
), profile()))
195 << test
.url
<< " " << test
.comment
;
199 // Each test case represents a navigation to |start_url| followed by a
200 // navigation to |end_url|. We will check whether each navigation lands in an
201 // Instant process, and also whether the navigation from start to end re-uses
202 // the same SiteInstance (and hence the same RenderViewHost, etc.).
203 const struct ProcessIsolationTestCase
{
204 const char* description
;
205 const char* start_url
;
206 bool start_in_instant_process
;
208 bool end_in_instant_process
;
209 bool same_site_instance
;
210 } kProcessIsolationTestCases
[] = {
212 "chrome-search://local-ntp", true,
213 "https://foo.com/url?strk", true, false },
214 {"Local NTP -> Regular",
215 "chrome-search://local-ntp", true,
216 "https://foo.com/other", false, false },
217 {"Remote NTP -> SRP",
218 "https://foo.com/newtab?strk", true,
219 "https://foo.com/url?strk", true, false },
220 {"Remote NTP -> Regular",
221 "https://foo.com/newtab?strk", true,
222 "https://foo.com/other", false, false },
224 "https://foo.com/url?strk", true,
225 "https://foo.com/url?strk", true, true },
227 "https://foo.com/url?strk", true,
228 "https://foo.com/other", false, false },
230 "https://foo.com/other", false,
231 "https://foo.com/url?strk", true, false },
234 TEST_F(SearchTest
, ProcessIsolation
) {
235 EnableQueryExtractionForTesting();
237 for (size_t i
= 0; i
< arraysize(kProcessIsolationTestCases
); ++i
) {
238 const ProcessIsolationTestCase
& test
= kProcessIsolationTestCases
[i
];
239 AddTab(browser(), GURL("chrome://blank"));
240 const content::WebContents
* contents
=
241 browser()->tab_strip_model()->GetActiveWebContents();
243 // Navigate to start URL.
244 NavigateAndCommitActiveTab(GURL(test
.start_url
));
245 EXPECT_EQ(test
.start_in_instant_process
, InInstantProcess(contents
))
249 const scoped_refptr
<content::SiteInstance
> start_site_instance
=
250 contents
->GetSiteInstance();
251 const content::RenderProcessHost
* start_rph
=
252 contents
->GetRenderProcessHost();
253 const content::RenderViewHost
* start_rvh
=
254 contents
->GetRenderViewHost();
256 // Navigate to end URL.
257 NavigateAndCommitActiveTab(GURL(test
.end_url
));
258 EXPECT_EQ(test
.end_in_instant_process
, InInstantProcess(contents
))
261 EXPECT_EQ(test
.same_site_instance
,
262 start_site_instance
.get() == contents
->GetSiteInstance())
264 EXPECT_EQ(test
.same_site_instance
,
265 start_rvh
== contents
->GetRenderViewHost())
267 EXPECT_EQ(test
.same_site_instance
,
268 start_rph
== contents
->GetRenderProcessHost())
273 TEST_F(SearchTest
, ProcessIsolation_RendererInitiated
) {
274 EnableQueryExtractionForTesting();
276 for (size_t i
= 0; i
< arraysize(kProcessIsolationTestCases
); ++i
) {
277 const ProcessIsolationTestCase
& test
= kProcessIsolationTestCases
[i
];
278 AddTab(browser(), GURL("chrome://blank"));
279 content::WebContents
* contents
=
280 browser()->tab_strip_model()->GetActiveWebContents();
282 // Navigate to start URL.
283 NavigateAndCommitActiveTab(GURL(test
.start_url
));
284 EXPECT_EQ(test
.start_in_instant_process
, InInstantProcess(contents
))
288 const scoped_refptr
<content::SiteInstance
> start_site_instance
=
289 contents
->GetSiteInstance();
290 const content::RenderProcessHost
* start_rph
=
291 contents
->GetRenderProcessHost();
292 const content::RenderViewHost
* start_rvh
=
293 contents
->GetRenderViewHost();
295 // Navigate to end URL via a renderer-initiated navigation.
296 content::NavigationController
* controller
= &contents
->GetController();
297 content::NavigationController::LoadURLParams
load_params(
299 load_params
.is_renderer_initiated
= true;
300 load_params
.transition_type
= ui::PAGE_TRANSITION_LINK
;
302 controller
->LoadURLWithParams(load_params
);
303 CommitPendingLoad(controller
);
304 EXPECT_EQ(test
.end_in_instant_process
, InInstantProcess(contents
))
307 EXPECT_EQ(test
.same_site_instance
,
308 start_site_instance
.get() == contents
->GetSiteInstance())
310 EXPECT_EQ(test
.same_site_instance
,
311 start_rvh
== contents
->GetRenderViewHost())
313 EXPECT_EQ(test
.same_site_instance
,
314 start_rph
== contents
->GetRenderProcessHost())
319 const SearchTestCase kInstantNTPTestCases
[] = {
320 {"https://foo.com/instant?strk", false, "Valid Instant URL"},
321 {"https://foo.com/instant#strk", false, "Valid Instant URL"},
322 {"https://foo.com/url?strk", false, "Valid search URL"},
323 {"https://foo.com/url#strk", false, "Valid search URL"},
324 {"https://foo.com/alt?strk", false, "Valid alternative URL"},
325 {"https://foo.com/alt#strk", false, "Valid alternative URL"},
326 {"https://foo.com/url?strk&bar=", false, "No query terms"},
327 {"https://foo.com/url?strk&q=abc", false, "No query terms key"},
328 {"https://foo.com/url?strk#bar=abc", false, "Query terms key in ref"},
329 {"https://foo.com/url?strk&bar=abc", false, "Has query terms"},
330 {"http://foo.com/instant?strk=1", false, "Insecure URL"},
331 {"https://foo.com/instant", false, "No search term replacement"},
332 {"chrome://blank/", false, "Chrome scheme"},
333 {"chrome-search://foo", false, "Chrome-search scheme"},
334 {"https://bar.com/instant?strk=1", false, "Random non-search page"},
335 {chrome::kChromeSearchLocalNtpUrl
, true, "Local new tab page"},
336 {"https://foo.com/newtab?strk", true, "New tab URL"},
337 {"http://foo.com/newtab?strk", false, "Insecure New tab URL"},
340 TEST_F(SearchTest
, InstantNTPExtendedEnabled
) {
341 EnableQueryExtractionForTesting();
342 AddTab(browser(), GURL("chrome://blank"));
343 for (size_t i
= 0; i
< arraysize(kInstantNTPTestCases
); ++i
) {
344 const SearchTestCase
& test
= kInstantNTPTestCases
[i
];
345 NavigateAndCommitActiveTab(GURL(test
.url
));
346 const content::WebContents
* contents
=
347 browser()->tab_strip_model()->GetWebContentsAt(0);
348 EXPECT_EQ(test
.expected_result
, IsInstantNTP(contents
))
349 << test
.url
<< " " << test
.comment
;
353 TEST_F(SearchTest
, InstantNTPCustomNavigationEntry
) {
354 EnableQueryExtractionForTesting();
355 AddTab(browser(), GURL("chrome://blank"));
356 for (size_t i
= 0; i
< arraysize(kInstantNTPTestCases
); ++i
) {
357 const SearchTestCase
& test
= kInstantNTPTestCases
[i
];
358 NavigateAndCommitActiveTab(GURL(test
.url
));
359 content::WebContents
* contents
=
360 browser()->tab_strip_model()->GetWebContentsAt(0);
361 content::NavigationController
& controller
= contents
->GetController();
362 controller
.SetTransientEntry(
363 controller
.CreateNavigationEntry(GURL("chrome://blank"),
365 ui::PAGE_TRANSITION_LINK
,
368 contents
->GetBrowserContext()));
369 // The active entry is chrome://blank and not an NTP.
370 EXPECT_FALSE(IsInstantNTP(contents
));
371 EXPECT_EQ(test
.expected_result
,
372 NavEntryIsInstantNTP(contents
,
373 controller
.GetLastCommittedEntry()))
374 << test
.url
<< " " << test
.comment
;
378 TEST_F(SearchTest
, InstantCacheableNTPNavigationEntry
) {
379 AddTab(browser(), GURL("chrome://blank"));
380 content::WebContents
* contents
=
381 browser()->tab_strip_model()->GetWebContentsAt(0);
382 content::NavigationController
& controller
= contents
->GetController();
384 NavigateAndCommitActiveTab(GURL(chrome::kChromeSearchLocalNtpUrl
));
385 EXPECT_TRUE(NavEntryIsInstantNTP(contents
,
386 controller
.GetLastCommittedEntry()));
387 // Instant page is not cacheable NTP.
388 NavigateAndCommitActiveTab(GetInstantURL(profile(), false));
389 EXPECT_FALSE(NavEntryIsInstantNTP(contents
,
390 controller
.GetLastCommittedEntry()));
391 // Test Cacheable NTP
392 NavigateAndCommitActiveTab(GetNewTabPageURL(profile()));
393 EXPECT_TRUE(NavEntryIsInstantNTP(contents
,
394 controller
.GetLastCommittedEntry()));
397 TEST_F(SearchTest
, InstantCacheableNTPNavigationEntryNewProfile
) {
398 SetSearchProvider(false, false);
399 AddTab(browser(), GURL(chrome::kChromeUINewTabURL
));
400 content::WebContents
* contents
=
401 browser()->tab_strip_model()->GetWebContentsAt(0);
402 content::NavigationController
& controller
= contents
->GetController();
403 // Test virtual url chrome://newtab for first NTP of a new profile
404 EXPECT_TRUE(NavEntryIsInstantNTP(contents
,
405 controller
.GetLastCommittedEntry()));
406 // The new_tab_url gets set after the first NTP is visible.
407 SetSearchProvider(true, false);
408 EXPECT_TRUE(NavEntryIsInstantNTP(contents
,
409 controller
.GetLastCommittedEntry()));
412 TEST_F(SearchTest
, NoRewriteInIncognito
) {
413 profile()->ForceIncognito(true);
414 EXPECT_EQ(GURL(), GetNewTabPageURL(profile()));
415 GURL
new_tab_url(chrome::kChromeUINewTabURL
);
416 EXPECT_FALSE(HandleNewTabURLRewrite(&new_tab_url
, profile()));
417 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL
), new_tab_url
);
420 TEST_F(SearchTest
, UseLocalNTPIfNTPURLIsInsecure
) {
421 // Set an insecure new tab page URL and verify that it's ignored.
422 SetSearchProvider(true, true);
423 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl
),
424 GetNewTabPageURL(profile()));
425 GURL
new_tab_url(chrome::kChromeUINewTabURL
);
426 EXPECT_TRUE(HandleNewTabURLRewrite(&new_tab_url
, profile()));
427 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl
), new_tab_url
);
430 TEST_F(SearchTest
, UseLocalNTPIfNTPURLIsNotSet
) {
431 // Set an insecure new tab page URL and verify that it's ignored.
432 SetSearchProvider(false, true);
433 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl
),
434 GetNewTabPageURL(profile()));
435 GURL
new_tab_url(chrome::kChromeUINewTabURL
);
436 EXPECT_TRUE(HandleNewTabURLRewrite(&new_tab_url
, profile()));
437 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl
), new_tab_url
);
440 #if defined(ENABLE_SUPERVISED_USERS)
441 TEST_F(SearchTest
, UseLocalNTPIfNTPURLIsBlockedForSupervisedUser
) {
442 // Block access to foo.com in the URL filter.
443 SupervisedUserService
* supervised_user_service
=
444 SupervisedUserServiceFactory::GetForProfile(profile());
445 SupervisedUserURLFilter
* url_filter
=
446 supervised_user_service
->GetURLFilterForUIThread();
447 std::map
<std::string
, bool> hosts
;
448 hosts
["foo.com"] = false;
449 url_filter
->SetManualHosts(&hosts
);
451 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl
),
452 GetNewTabPageURL(profile()));
453 GURL
new_tab_url(chrome::kChromeUINewTabURL
);
454 EXPECT_TRUE(HandleNewTabURLRewrite(&new_tab_url
, profile()));
455 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl
), new_tab_url
);
456 EXPECT_EQ(GURL(), GetInstantURL(profile(), false));
460 TEST_F(SearchTest
, GetInstantURL
) {
461 // No Instant URL because "strk" is missing.
462 SetDefaultInstantTemplateUrl(false);
463 EXPECT_EQ(GURL(), GetInstantURL(profile(), false));
465 // Set an Instant URL with a valid search terms replacement key.
466 SetDefaultInstantTemplateUrl(true);
468 // Now there should be a valid Instant URL. Note the HTTPS "upgrade".
469 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
470 GetInstantURL(profile(), false));
472 // Enable suggest. No difference.
473 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled
, true);
474 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
475 GetInstantURL(profile(), false));
477 // Disable suggest. No Instant URL.
478 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled
, false);
479 EXPECT_EQ(GURL(), GetInstantURL(profile(), false));
481 // Use alternate Instant search base URL.
482 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled
, true);
483 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
484 "EmbeddedSearch", "Group1 espv:8 use_alternate_instant_url:1"));
485 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo&qbp=1#foo=foo&strk"),
486 GetInstantURL(profile(), false));
489 TEST_F(SearchTest
, UseSearchPathForInstant
) {
490 // Use alternate Instant search base URL path.
491 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
493 "Group1 use_alternate_instant_url:1 use_search_path_for_instant:1"));
494 EXPECT_EQ(GURL("https://foo.com/search?foo=foo&qbp=1#foo=foo&strk"),
495 GetInstantURL(profile(), false));
498 TEST_F(SearchTest
, InstantSearchEnabledCGI
) {
499 // Disable Instant Search.
500 // Make sure {google:forceInstantResults} is not set in the Instant URL.
501 EXPECT_EQ(GURL("https://foo.com/instant?foo=foo#foo=foo&strk"),
502 GetInstantURL(profile(), false));
504 // Enable Instant Search.
505 // Make sure {google:forceInstantResults} is set in the Instant URL.
506 EXPECT_EQ(GURL("https://foo.com/instant?ion=1&foo=foo#foo=foo&strk"),
507 GetInstantURL(profile(), true));
510 TEST_F(SearchTest
, CommandLineOverrides
) {
511 GURL
local_instant_url(GetLocalInstantURL(profile()));
512 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl
), local_instant_url
);
514 TemplateURLService
* template_url_service
=
515 TemplateURLServiceFactory::GetForProfile(profile());
516 TemplateURLData data
;
517 data
.SetShortName(base::ASCIIToUTF16("Google"));
518 data
.SetURL("{google:baseURL}search?q={searchTerms}");
519 data
.instant_url
= "{google:baseURL}webhp?strk";
520 data
.search_terms_replacement_key
= "strk";
521 TemplateURL
* template_url
= new TemplateURL(data
);
522 // Takes ownership of |template_url|.
523 template_url_service
->Add(template_url
);
524 template_url_service
->SetUserSelectedDefaultSearchProvider(template_url
);
526 // By default, Instant Extended forces the instant URL to be HTTPS, so even if
527 // we set a Google base URL that is HTTP, we should get an HTTPS URL.
528 UIThreadSearchTermsData::SetGoogleBaseURL("http://www.foo.com/");
529 GURL
instant_url(GetInstantURL(profile(), false));
530 ASSERT_TRUE(instant_url
.is_valid());
531 EXPECT_EQ("https://www.foo.com/webhp?strk", instant_url
.spec());
533 // However, if the Google base URL is specified on the command line, the
534 // instant URL should just use it, even if it's HTTP.
535 UIThreadSearchTermsData::SetGoogleBaseURL(std::string());
536 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
537 switches::kGoogleBaseURL
, "http://www.bar.com/");
538 instant_url
= GetInstantURL(profile(), false);
539 ASSERT_TRUE(instant_url
.is_valid());
540 EXPECT_EQ("http://www.bar.com/webhp?strk", instant_url
.spec());
542 // Similarly, setting a Google base URL on the command line should allow you
543 // to get the Google version of the local NTP, even though search provider's
544 // URL doesn't contain "google".
545 local_instant_url
= GetLocalInstantURL(profile());
546 EXPECT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl
), local_instant_url
);
548 // If we specify extra search query params, they should be inserted into the
549 // query portion of the instant URL.
550 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
551 switches::kExtraSearchQueryParams
, "a=b");
552 instant_url
= GetInstantURL(profile(), false);
553 ASSERT_TRUE(instant_url
.is_valid());
554 EXPECT_EQ("http://www.bar.com/webhp?a=b&strk", instant_url
.spec());
557 TEST_F(SearchTest
, ShouldUseAltInstantURL_DisabledViaFieldTrial
) {
558 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
559 "EmbeddedSearch", "Group1 espv:8 use_alternate_instant_url:0"));
560 EXPECT_FALSE(ShouldUseAltInstantURL());
563 TEST_F(SearchTest
, ShouldUseAltInstantURL_EnabledViaFieldTrial
) {
564 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
565 "EmbeddedSearch", "Group1 espv:8 use_alternate_instant_url:1"));
566 EXPECT_TRUE(ShouldUseAltInstantURL());
569 TEST_F(SearchTest
, ShouldUseSearchPathForInstant_DisabledViaFieldTrial
) {
570 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
572 "Group1 use_alternate_instant_url:1 use_search_path_for_instant:0"));
573 EXPECT_FALSE(ShouldUseSearchPathForInstant());
576 TEST_F(SearchTest
, ShouldUseSearchPathForInstant_EnabledViaFieldTrial
) {
577 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
579 "Group1 use_alternate_instant_url:1 use_search_path_for_instant:1"));
580 EXPECT_TRUE(ShouldUseSearchPathForInstant());
584 ShouldPrerenderInstantUrlOnOmniboxFocus_DisabledViaFieldTrial
) {
585 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
587 "Group1 espv:89 prerender_instant_url_on_omnibox_focus:0"));
588 EXPECT_FALSE(ShouldPrerenderInstantUrlOnOmniboxFocus());
589 EXPECT_EQ(89ul, EmbeddedSearchPageVersion());
593 ShouldPrerenderInstantUrlOnOmniboxFocus_EnabledViaFieldTrial
) {
594 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
596 "Group1 espv:80 prerender_instant_url_on_omnibox_focus:1"));
597 EXPECT_TRUE(ShouldPrerenderInstantUrlOnOmniboxFocus());
598 EXPECT_EQ(80ul, EmbeddedSearchPageVersion());
603 TEST_F(SearchTest
, ShouldShowGoogleLocalNTP_Default
) {
604 EXPECT_TRUE(ShouldShowGoogleLocalNTP());
607 TEST_F(SearchTest
, ShouldShowGoogleLocalNTP_EnabledViaFinch
) {
608 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
609 "EmbeddedSearch", "Group1 espv:2 google_local_ntp:1"));
610 EXPECT_TRUE(ShouldShowGoogleLocalNTP());
613 TEST_F(SearchTest
, ShouldShowGoogleLocalNTP_DisabledViaFinch
) {
614 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
615 "EmbeddedSearch", "Group1 espv:2 google_local_ntp:0"));
616 EXPECT_FALSE(ShouldShowGoogleLocalNTP());
620 TEST_F(SearchTest
, IsNTPURL
) {
622 GURL
ntp_url(chrome::kChromeUINewTabURL
);
623 GURL
local_ntp_url(GetLocalInstantURL(profile()));
625 EXPECT_FALSE(IsNTPURL(invalid_url
, profile()));
627 EnableQueryExtractionForTesting();
628 profile()->GetPrefs()->SetBoolean(prefs::kSearchSuggestEnabled
, true);
629 GURL
remote_ntp_url(GetInstantURL(profile(), false));
630 GURL
search_url_with_search_terms("https://foo.com/url?strk&bar=abc");
631 GURL
search_url_without_search_terms("https://foo.com/url?strk&bar");
633 EXPECT_FALSE(IsNTPURL(ntp_url
, profile()));
634 EXPECT_TRUE(IsNTPURL(local_ntp_url
, profile()));
635 EXPECT_TRUE(IsNTPURL(remote_ntp_url
, profile()));
636 EXPECT_FALSE(IsNTPURL(search_url_with_search_terms
, profile()));
637 EXPECT_TRUE(IsNTPURL(search_url_without_search_terms
, profile()));
639 EXPECT_FALSE(IsNTPURL(ntp_url
, NULL
));
640 EXPECT_FALSE(IsNTPURL(local_ntp_url
, NULL
));
641 EXPECT_FALSE(IsNTPURL(remote_ntp_url
, NULL
));
642 EXPECT_FALSE(IsNTPURL(search_url_with_search_terms
, NULL
));
643 EXPECT_FALSE(IsNTPURL(search_url_without_search_terms
, NULL
));
646 TEST_F(SearchTest
, GetSearchURLs
) {
647 std::vector
<GURL
> search_urls
= GetSearchURLs(profile());
648 EXPECT_EQ(2U, search_urls
.size());
649 EXPECT_EQ("http://foo.com/alt#quux=", search_urls
[0].spec());
650 EXPECT_EQ("http://foo.com/url?bar=", search_urls
[1].spec());
653 TEST_F(SearchTest
, GetSearchResultPrefetchBaseURL
) {
655 EXPECT_FALSE(ShouldPrefetchSearchResults());
656 EXPECT_EQ(GURL(), GetSearchResultPrefetchBaseURL(profile()));
658 EXPECT_TRUE(ShouldPrefetchSearchResults());
659 EXPECT_EQ(GURL("https://foo.com/instant?ion=1&foo=foo#foo=foo&strk"),
660 GetSearchResultPrefetchBaseURL(profile()));
664 struct ExtractSearchTermsTestCase
{
666 const char* expected_result
;
670 TEST_F(SearchTest
, ExtractSearchTermsFromURL
) {
671 const ExtractSearchTermsTestCase kTestCases
[] = {
672 {chrome::kChromeSearchLocalNtpUrl
, "", "NTP url"},
673 {"https://foo.com/instant?strk", "", "Invalid search url"},
674 {"https://foo.com/instant#strk", "", "Invalid search url"},
675 {"https://foo.com/alt#quux=foo", "foo", "Valid search url"},
676 {"https://foo.com/alt#quux=foo&strk", "foo", "Valid search url"}
679 for (size_t i
= 0; i
< arraysize(kTestCases
); ++i
) {
680 const ExtractSearchTermsTestCase
& test
= kTestCases
[i
];
681 EXPECT_EQ(test
.expected_result
,
683 ExtractSearchTermsFromURL(profile(), GURL(test
.url
))))
684 << test
.url
<< " " << test
.comment
;
688 struct QueryExtractionAllowedTestCase
{
690 bool expected_result
;
694 TEST_F(SearchTest
, IsQueryExtractionAllowedForURL
) {
695 const QueryExtractionAllowedTestCase kTestCases
[] = {
696 {"http://foo.com/instant?strk", false, "HTTP URL"},
697 {"https://foo.com/instant?strk", true, "Valid URL"},
698 {"https://foo.com/instant?", false,
699 "No search terms replacement key"},
700 {"https://foo.com/alt#quux=foo", false,
701 "No search terms replacement key"},
702 {"https://foo.com/alt#quux=foo&strk", true, "Valid search url"}
705 for (size_t i
= 0; i
< arraysize(kTestCases
); ++i
) {
706 const QueryExtractionAllowedTestCase
& test
= kTestCases
[i
];
707 EXPECT_EQ(test
.expected_result
,
708 IsQueryExtractionAllowedForURL(profile(), GURL(test
.url
)))
709 << test
.url
<< " " << test
.comment
;
713 class SearchURLTest
: public SearchTest
{
715 void SetSearchProvider(bool set_ntp_url
, bool insecure_ntp_url
) override
{
716 TemplateURLService
* template_url_service
=
717 TemplateURLServiceFactory::GetForProfile(profile());
718 TemplateURLData data
;
719 data
.SetShortName(base::ASCIIToUTF16("Google"));
720 data
.SetURL("{google:baseURL}search?"
721 "{google:instantExtendedEnabledParameter}q={searchTerms}");
722 data
.search_terms_replacement_key
= "espv";
723 template_url_
= new TemplateURL(data
);
724 // |template_url_service| takes ownership of |template_url_|.
725 template_url_service
->Add(template_url_
);
726 template_url_service
->SetUserSelectedDefaultSearchProvider(template_url_
);
729 TemplateURL
* template_url_
;
732 TEST_F(SearchURLTest
, QueryExtractionEnabled
) {
733 UIThreadSearchTermsData::SetGoogleBaseURL("http://www.google.com/");
734 EnableQueryExtractionForTesting();
735 EXPECT_TRUE(IsQueryExtractionEnabled());
736 TemplateURLRef::SearchTermsArgs
search_terms_args(base::ASCIIToUTF16("foo"));
737 GURL
result(template_url_
->url_ref().ReplaceSearchTerms(
738 search_terms_args
, UIThreadSearchTermsData(profile())));
739 ASSERT_TRUE(result
.is_valid());
740 // Query extraction is enabled. Make sure
741 // {google:instantExtendedEnabledParameter} is set in the search URL.
742 EXPECT_EQ("http://www.google.com/search?espv=2&q=foo", result
.spec());
745 TEST_F(SearchURLTest
, QueryExtractionDisabled
) {
746 UIThreadSearchTermsData::SetGoogleBaseURL("http://www.google.com/");
747 EXPECT_FALSE(IsQueryExtractionEnabled());
748 TemplateURLRef::SearchTermsArgs
search_terms_args(base::ASCIIToUTF16("foo"));
749 GURL
result(template_url_
->url_ref().ReplaceSearchTerms(
750 search_terms_args
, UIThreadSearchTermsData(profile())));
751 ASSERT_TRUE(result
.is_valid());
752 // Query extraction is disabled. Make sure
753 // {google:instantExtendedEnabledParameter} is not set in the search URL.
754 EXPECT_EQ("http://www.google.com/search?q=foo", result
.spec());
757 } // namespace search