Move about://-related constants from //content to //url
[chromium-blink-merge.git] / chrome / browser / ui / search / instant_search_prerenderer_unittest.cc
blob344618c9a609cb0e99093ad220c0fb24086c9c6b
1 // Copyright 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 "chrome/browser/ui/search/instant_search_prerenderer.h"
7 #include "base/basictypes.h"
8 #include "base/compiler_specific.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/autocomplete/autocomplete_match.h"
14 #include "chrome/browser/prerender/prerender_contents.h"
15 #include "chrome/browser/prerender/prerender_handle.h"
16 #include "chrome/browser/prerender/prerender_manager.h"
17 #include "chrome/browser/prerender/prerender_manager_factory.h"
18 #include "chrome/browser/prerender/prerender_origin.h"
19 #include "chrome/browser/prerender/prerender_tab_helper.h"
20 #include "chrome/browser/prerender/prerender_tracker.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/search/instant_service.h"
23 #include "chrome/browser/search/instant_unittest_base.h"
24 #include "chrome/browser/search/search.h"
25 #include "chrome/browser/ui/search/search_tab_helper.h"
26 #include "chrome/browser/ui/tabs/tab_strip_model.h"
27 #include "chrome/common/render_messages.h"
28 #include "content/public/browser/navigation_controller.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/common/url_constants.h"
31 #include "content/public/test/mock_render_process_host.h"
32 #include "ipc/ipc_message.h"
33 #include "ipc/ipc_test_sink.h"
34 #include "ui/gfx/size.h"
36 using base::ASCIIToUTF16;
38 namespace {
40 using content::Referrer;
41 using prerender::Origin;
42 using prerender::PrerenderContents;
43 using prerender::PrerenderHandle;
44 using prerender::PrerenderManager;
45 using prerender::PrerenderManagerFactory;
46 using prerender::PrerenderTabHelper;
48 class DummyPrerenderContents : public PrerenderContents {
49 public:
50 DummyPrerenderContents(
51 PrerenderManager* prerender_manager,
52 Profile* profile,
53 const GURL& url,
54 const Referrer& referrer,
55 Origin origin,
56 bool call_did_finish_load,
57 const content::SessionStorageNamespaceMap& session_storage_namespace_map);
59 virtual void StartPrerendering(
60 int ALLOW_UNUSED creator_child_id,
61 const gfx::Size& ALLOW_UNUSED size,
62 content::SessionStorageNamespace* session_storage_namespace,
63 net::URLRequestContextGetter* request_context) OVERRIDE;
64 virtual bool GetChildId(int* child_id) const OVERRIDE;
65 virtual bool GetRouteId(int* route_id) const OVERRIDE;
67 private:
68 Profile* profile_;
69 const GURL url_;
70 bool call_did_finish_load_;
71 content::SessionStorageNamespaceMap session_storage_namespace_map_;
73 DISALLOW_COPY_AND_ASSIGN(DummyPrerenderContents);
76 class DummyPrerenderContentsFactory : public PrerenderContents::Factory {
77 public:
78 DummyPrerenderContentsFactory(
79 bool call_did_finish_load,
80 const content::SessionStorageNamespaceMap& session_storage_namespace_map)
81 : call_did_finish_load_(call_did_finish_load),
82 session_storage_namespace_map_(session_storage_namespace_map) {
85 virtual PrerenderContents* CreatePrerenderContents(
86 PrerenderManager* prerender_manager,
87 Profile* profile,
88 const GURL& url,
89 const Referrer& referrer,
90 Origin origin,
91 uint8 experiment_id) OVERRIDE;
93 private:
94 bool call_did_finish_load_;
95 content::SessionStorageNamespaceMap session_storage_namespace_map_;
97 DISALLOW_COPY_AND_ASSIGN(DummyPrerenderContentsFactory);
100 DummyPrerenderContents::DummyPrerenderContents(
101 PrerenderManager* prerender_manager,
102 Profile* profile,
103 const GURL& url,
104 const Referrer& referrer,
105 Origin origin,
106 bool call_did_finish_load,
107 const content::SessionStorageNamespaceMap& session_storage_namespace_map)
108 : PrerenderContents(prerender_manager, profile, url, referrer, origin,
109 PrerenderManager::kNoExperiment),
110 profile_(profile),
111 url_(url),
112 call_did_finish_load_(call_did_finish_load),
113 session_storage_namespace_map_(session_storage_namespace_map) {
116 void DummyPrerenderContents::StartPrerendering(
117 int ALLOW_UNUSED creator_child_id,
118 const gfx::Size& ALLOW_UNUSED size,
119 content::SessionStorageNamespace* session_storage_namespace,
120 net::URLRequestContextGetter* request_context) {
121 prerender_contents_.reset(content::WebContents::CreateWithSessionStorage(
122 content::WebContents::CreateParams(profile_),
123 session_storage_namespace_map_));
124 PrerenderTabHelper::CreateForWebContentsWithPasswordManager(
125 prerender_contents_.get(), NULL);
126 content::NavigationController::LoadURLParams params(url_);
127 prerender_contents_->GetController().LoadURLWithParams(params);
128 SearchTabHelper::CreateForWebContents(prerender_contents_.get());
130 prerendering_has_started_ = true;
131 DCHECK(session_storage_namespace);
132 session_storage_namespace_id_ = session_storage_namespace->id();
133 NotifyPrerenderStart();
135 if (call_did_finish_load_)
136 DidFinishLoad(1, url_, true, NULL);
139 bool DummyPrerenderContents::GetChildId(int* child_id) const {
140 *child_id = 1;
141 return true;
144 bool DummyPrerenderContents::GetRouteId(int* route_id) const {
145 *route_id = 1;
146 return true;
149 PrerenderContents* DummyPrerenderContentsFactory::CreatePrerenderContents(
150 PrerenderManager* prerender_manager,
151 Profile* profile,
152 const GURL& url,
153 const Referrer& referrer,
154 Origin origin,
155 uint8 experiment_id) {
156 return new DummyPrerenderContents(prerender_manager, profile, url, referrer,
157 origin, call_did_finish_load_,
158 session_storage_namespace_map_);
161 } // namespace
163 class InstantSearchPrerendererTest : public InstantUnitTestBase {
164 public:
165 InstantSearchPrerendererTest() {}
167 protected:
168 virtual void SetUp() OVERRIDE {
169 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
170 "EmbeddedSearch", "Group1 strk:20 prefetch_results:1"));
171 InstantUnitTestBase::SetUp();
174 void Init(bool prerender_search_results_base_page,
175 bool call_did_finish_load) {
176 AddTab(browser(), GURL(url::kAboutBlankURL));
178 content::SessionStorageNamespaceMap session_storage_namespace_map;
179 session_storage_namespace_map[std::string()] =
180 GetActiveWebContents()->GetController().
181 GetDefaultSessionStorageNamespace();
182 PrerenderManagerFactory::GetForProfile(browser()->profile())->
183 SetPrerenderContentsFactory(
184 new DummyPrerenderContentsFactory(call_did_finish_load,
185 session_storage_namespace_map));
186 PrerenderManagerFactory::GetForProfile(browser()->profile())->
187 OnCookieStoreLoaded();
188 if (prerender_search_results_base_page) {
189 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
190 prerenderer->Init(session_storage_namespace_map, gfx::Size(640, 480));
191 EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
195 InstantSearchPrerenderer* GetInstantSearchPrerenderer() {
196 return instant_service_->instant_search_prerenderer();
199 const GURL& GetPrerenderURL() {
200 return GetInstantSearchPrerenderer()->prerender_url_;
203 void SetLastQuery(const base::string16& query) {
204 GetInstantSearchPrerenderer()->last_instant_suggestion_ =
205 InstantSuggestion(query, std::string());
208 content::WebContents* prerender_contents() {
209 return GetInstantSearchPrerenderer()->prerender_contents();
212 bool MessageWasSent(uint32 id) {
213 content::MockRenderProcessHost* process =
214 static_cast<content::MockRenderProcessHost*>(
215 prerender_contents()->GetRenderViewHost()->GetProcess());
216 return process->sink().GetFirstMessageMatching(id) != NULL;
219 content::WebContents* GetActiveWebContents() const {
220 return browser()->tab_strip_model()->GetWebContentsAt(0);
223 PrerenderHandle* prerender_handle() {
224 return GetInstantSearchPrerenderer()->prerender_handle_.get();
227 void PrerenderSearchQuery(const base::string16& query) {
228 Init(true, true);
229 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
230 prerenderer->Prerender(InstantSuggestion(query, std::string()));
231 CommitPendingLoad(&prerender_contents()->GetController());
232 EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(), query));
233 EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
237 TEST_F(InstantSearchPrerendererTest, GetSearchTermsFromPrerenderedPage) {
238 Init(false, false);
239 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
240 GURL url(GetPrerenderURL());
241 EXPECT_EQ(GURL("https://www.google.com/instant?ion=1&foo=foo#foo=foo&strk"),
242 url);
243 EXPECT_EQ(base::UTF16ToASCII(prerenderer->get_last_query()),
244 base::UTF16ToASCII(
245 chrome::ExtractSearchTermsFromURL(profile(), url)));
247 // Assume the prerendered page prefetched search results for the query
248 // "flowers".
249 SetLastQuery(ASCIIToUTF16("flowers"));
250 EXPECT_EQ("flowers", base::UTF16ToASCII(prerenderer->get_last_query()));
251 EXPECT_EQ(base::UTF16ToASCII(prerenderer->get_last_query()),
252 base::UTF16ToASCII(
253 chrome::ExtractSearchTermsFromURL(profile(), url)));
256 TEST_F(InstantSearchPrerendererTest, PrefetchSearchResults) {
257 Init(true, true);
258 EXPECT_TRUE(prerender_handle()->IsFinishedLoading());
259 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
260 prerenderer->Prerender(
261 InstantSuggestion(ASCIIToUTF16("flowers"), std::string()));
262 EXPECT_EQ("flowers", base::UTF16ToASCII(prerenderer->get_last_query()));
263 EXPECT_TRUE(MessageWasSent(
264 ChromeViewMsg_SearchBoxSetSuggestionToPrefetch::ID));
267 TEST_F(InstantSearchPrerendererTest, DoNotPrefetchSearchResults) {
268 Init(true, false);
269 // Page hasn't finished loading yet.
270 EXPECT_FALSE(prerender_handle()->IsFinishedLoading());
271 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
272 prerenderer->Prerender(
273 InstantSuggestion(ASCIIToUTF16("flowers"), std::string()));
274 EXPECT_EQ("", base::UTF16ToASCII(prerenderer->get_last_query()));
275 EXPECT_FALSE(MessageWasSent(
276 ChromeViewMsg_SearchBoxSetSuggestionToPrefetch::ID));
279 TEST_F(InstantSearchPrerendererTest, CanCommitQuery) {
280 Init(true, true);
281 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
282 base::string16 query = ASCIIToUTF16("flowers");
283 prerenderer->Prerender(InstantSuggestion(query, std::string()));
284 EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(), query));
286 // Make sure InstantSearchPrerenderer::CanCommitQuery() returns false for
287 // invalid search queries.
288 EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
289 ASCIIToUTF16("joy")));
290 EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
291 base::string16()));
294 TEST_F(InstantSearchPrerendererTest, CommitQuery) {
295 base::string16 query = ASCIIToUTF16("flowers");
296 PrerenderSearchQuery(query);
297 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
298 prerenderer->Commit(query);
299 EXPECT_TRUE(MessageWasSent(ChromeViewMsg_SearchBoxSubmit::ID));
302 TEST_F(InstantSearchPrerendererTest, CancelPrerenderRequestOnTabChangeEvent) {
303 Init(true, true);
304 EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
306 // Add a new tab to deactivate the current tab.
307 AddTab(browser(), GURL(url::kAboutBlankURL));
308 EXPECT_EQ(2, browser()->tab_strip_model()->count());
310 // Make sure the pending prerender request is cancelled.
311 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
314 TEST_F(InstantSearchPrerendererTest, CancelPendingPrerenderRequest) {
315 Init(true, true);
316 EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
318 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
319 prerenderer->Cancel();
320 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
323 TEST_F(InstantSearchPrerendererTest, PrerenderingAllowed) {
324 Init(true, true);
325 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
326 content::WebContents* active_tab = GetActiveWebContents();
327 EXPECT_EQ(GURL(url::kAboutBlankURL), active_tab->GetURL());
329 // Allow prerendering only for search type AutocompleteMatch suggestions.
330 AutocompleteMatch search_type_match(NULL, 1100, false,
331 AutocompleteMatchType::SEARCH_SUGGEST);
332 EXPECT_TRUE(AutocompleteMatch::IsSearchType(search_type_match.type));
333 EXPECT_TRUE(prerenderer->IsAllowed(search_type_match, active_tab));
335 AutocompleteMatch url_type_match(NULL, 1100, true,
336 AutocompleteMatchType::URL_WHAT_YOU_TYPED);
337 EXPECT_FALSE(AutocompleteMatch::IsSearchType(url_type_match.type));
338 EXPECT_FALSE(prerenderer->IsAllowed(url_type_match, active_tab));
340 // Search results page supports Instant search. InstantSearchPrerenderer is
341 // used only when the underlying page doesn't support Instant.
342 NavigateAndCommitActiveTab(GURL("https://www.google.com/alt#quux=foo&strk"));
343 active_tab = GetActiveWebContents();
344 EXPECT_FALSE(chrome::ExtractSearchTermsFromURL(profile(),
345 active_tab->GetURL()).empty());
346 EXPECT_FALSE(chrome::ShouldPrefetchSearchResultsOnSRP());
347 EXPECT_FALSE(prerenderer->IsAllowed(search_type_match, active_tab));
350 TEST_F(InstantSearchPrerendererTest, UsePrerenderPage) {
351 PrerenderSearchQuery(ASCIIToUTF16("foo"));
353 // Open a search results page. A prerendered page exists for |url|. Make sure
354 // the browser swaps the current tab contents with the prerendered contents.
355 GURL url("https://www.google.com/alt#quux=foo&strk");
356 browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
357 content::PAGE_TRANSITION_TYPED,
358 false));
359 EXPECT_EQ(GetPrerenderURL(), GetActiveWebContents()->GetURL());
360 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
363 TEST_F(InstantSearchPrerendererTest, PrerenderRequestCancelled) {
364 PrerenderSearchQuery(ASCIIToUTF16("foo"));
366 // Cancel the prerender request.
367 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
368 prerenderer->Cancel();
369 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
371 // Open a search results page. Prerendered page does not exists for |url|.
372 // Make sure the browser navigates the current tab to this |url|.
373 GURL url("https://www.google.com/alt#quux=foo&strk");
374 browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
375 content::PAGE_TRANSITION_TYPED,
376 false));
377 EXPECT_NE(GetPrerenderURL(), GetActiveWebContents()->GetURL());
378 EXPECT_EQ(url, GetActiveWebContents()->GetURL());
381 TEST_F(InstantSearchPrerendererTest,
382 CancelPrerenderRequest_SearchQueryMistmatch) {
383 PrerenderSearchQuery(ASCIIToUTF16("foo"));
385 // Open a search results page. Committed query("pen") doesn't match with the
386 // prerendered search query("foo"). Make sure the InstantSearchPrerenderer
387 // cancels the active prerender request and the browser navigates the active
388 // tab to this |url|.
389 GURL url("https://www.google.com/alt#quux=pen&strk");
390 browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
391 content::PAGE_TRANSITION_TYPED,
392 false));
393 EXPECT_NE(GetPrerenderURL(), GetActiveWebContents()->GetURL());
394 EXPECT_EQ(url, GetActiveWebContents()->GetURL());
395 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
398 TEST_F(InstantSearchPrerendererTest,
399 CancelPrerenderRequest_EmptySearchQueryCommitted) {
400 PrerenderSearchQuery(ASCIIToUTF16("foo"));
402 // Open a search results page. Make sure the InstantSearchPrerenderer cancels
403 // the active prerender request upon the receipt of empty search query.
404 GURL url("https://www.google.com/alt#quux=&strk");
405 browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
406 content::PAGE_TRANSITION_TYPED,
407 false));
408 EXPECT_NE(GetPrerenderURL(), GetActiveWebContents()->GetURL());
409 EXPECT_EQ(url, GetActiveWebContents()->GetURL());
410 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
413 class ReuseInstantSearchBasePageTest : public InstantSearchPrerendererTest {
414 public:
415 ReuseInstantSearchBasePageTest() {}
417 protected:
418 virtual void SetUp() OVERRIDE {
419 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
420 "EmbeddedSearch",
421 "Group1 strk:20 prefetch_results:1 reuse_instant_search_base_page:1"));
422 InstantUnitTestBase::SetUp();
426 TEST_F(ReuseInstantSearchBasePageTest, CanCommitQuery) {
427 Init(true, true);
428 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
429 base::string16 query = ASCIIToUTF16("flowers");
430 prerenderer->Prerender(InstantSuggestion(query, std::string()));
431 EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(), query));
433 // When the Instant search base page has finished loading,
434 // InstantSearchPrerenderer can commit any search query to the prerendered
435 // page (even if it doesn't match the last known suggestion query).
436 EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(),
437 ASCIIToUTF16("joy")));
438 // Invalid search query committed.
439 EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
440 base::string16()));
443 TEST_F(ReuseInstantSearchBasePageTest,
444 CanCommitQuery_InstantSearchBasePageLoadInProgress) {
445 Init(true, false);
446 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
447 base::string16 query = ASCIIToUTF16("flowers");
448 prerenderer->Prerender(InstantSuggestion(query, std::string()));
450 // When the Instant search base page hasn't finished loading,
451 // InstantSearchPrerenderer cannot commit any search query to the base page.
452 EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(), query));
453 EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
454 ASCIIToUTF16("joy")));
457 #if !defined(OS_IOS) && !defined(OS_ANDROID)
458 class TestUsePrerenderPage : public InstantSearchPrerendererTest {
459 protected:
460 virtual void SetUp() OVERRIDE {
461 // Disable query extraction flag in field trials.
462 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
463 "EmbeddedSearch",
464 "Group1 strk:20 query_extraction:0 prefetch_results:1"));
465 InstantUnitTestBase::SetUpWithoutQueryExtraction();
469 TEST_F(TestUsePrerenderPage, ExtractSearchTermsAndUsePrerenderPage) {
470 PrerenderSearchQuery(ASCIIToUTF16("foo"));
472 // Open a search results page. Query extraction flag is disabled in field
473 // trials. Search results page URL does not contain search terms replacement
474 // key. Make sure UsePrerenderedPage() extracts the search terms from the URL
475 // and uses the prerendered page contents.
476 GURL url("https://www.google.com/alt#quux=foo");
477 browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
478 content::PAGE_TRANSITION_TYPED,
479 false));
480 EXPECT_EQ(GetPrerenderURL(), GetActiveWebContents()->GetURL());
481 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
483 #endif