Refactor views app list services to allow more code sharing
[chromium-blink-merge.git] / chrome / browser / ui / search / instant_search_prerenderer_unittest.cc
blobf4ba748015fa76cdb25fedf06b8195a799d34139
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) OVERRIDE;
63 virtual bool GetChildId(int* child_id) const OVERRIDE;
64 virtual bool GetRouteId(int* route_id) const OVERRIDE;
66 private:
67 Profile* profile_;
68 const GURL url_;
69 bool call_did_finish_load_;
70 content::SessionStorageNamespaceMap session_storage_namespace_map_;
72 DISALLOW_COPY_AND_ASSIGN(DummyPrerenderContents);
75 class DummyPrerenderContentsFactory : public PrerenderContents::Factory {
76 public:
77 DummyPrerenderContentsFactory(
78 bool call_did_finish_load,
79 const content::SessionStorageNamespaceMap& session_storage_namespace_map)
80 : call_did_finish_load_(call_did_finish_load),
81 session_storage_namespace_map_(session_storage_namespace_map) {
84 virtual PrerenderContents* CreatePrerenderContents(
85 PrerenderManager* prerender_manager,
86 Profile* profile,
87 const GURL& url,
88 const Referrer& referrer,
89 Origin origin,
90 uint8 experiment_id) OVERRIDE;
92 private:
93 bool call_did_finish_load_;
94 content::SessionStorageNamespaceMap session_storage_namespace_map_;
96 DISALLOW_COPY_AND_ASSIGN(DummyPrerenderContentsFactory);
99 DummyPrerenderContents::DummyPrerenderContents(
100 PrerenderManager* prerender_manager,
101 Profile* profile,
102 const GURL& url,
103 const Referrer& referrer,
104 Origin origin,
105 bool call_did_finish_load,
106 const content::SessionStorageNamespaceMap& session_storage_namespace_map)
107 : PrerenderContents(prerender_manager, profile, url, referrer, origin,
108 PrerenderManager::kNoExperiment),
109 profile_(profile),
110 url_(url),
111 call_did_finish_load_(call_did_finish_load),
112 session_storage_namespace_map_(session_storage_namespace_map) {
115 void DummyPrerenderContents::StartPrerendering(
116 int ALLOW_UNUSED creator_child_id,
117 const gfx::Size& ALLOW_UNUSED size,
118 content::SessionStorageNamespace* session_storage_namespace) {
119 prerender_contents_.reset(content::WebContents::CreateWithSessionStorage(
120 content::WebContents::CreateParams(profile_),
121 session_storage_namespace_map_));
122 PrerenderTabHelper::CreateForWebContentsWithPasswordManager(
123 prerender_contents_.get(), NULL);
124 content::NavigationController::LoadURLParams params(url_);
125 prerender_contents_->GetController().LoadURLWithParams(params);
126 SearchTabHelper::CreateForWebContents(prerender_contents_.get());
128 prerendering_has_started_ = true;
129 DCHECK(session_storage_namespace);
130 session_storage_namespace_id_ = session_storage_namespace->id();
131 NotifyPrerenderStart();
133 if (call_did_finish_load_)
134 DidFinishLoad(1, url_, true, NULL);
137 bool DummyPrerenderContents::GetChildId(int* child_id) const {
138 *child_id = 1;
139 return true;
142 bool DummyPrerenderContents::GetRouteId(int* route_id) const {
143 *route_id = 1;
144 return true;
147 PrerenderContents* DummyPrerenderContentsFactory::CreatePrerenderContents(
148 PrerenderManager* prerender_manager,
149 Profile* profile,
150 const GURL& url,
151 const Referrer& referrer,
152 Origin origin,
153 uint8 experiment_id) {
154 return new DummyPrerenderContents(prerender_manager, profile, url, referrer,
155 origin, call_did_finish_load_,
156 session_storage_namespace_map_);
159 } // namespace
161 class InstantSearchPrerendererTest : public InstantUnitTestBase {
162 public:
163 InstantSearchPrerendererTest() {}
165 protected:
166 virtual void SetUp() OVERRIDE {
167 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
168 "EmbeddedSearch", "Group1 strk:20 prefetch_results:1"));
169 InstantUnitTestBase::SetUp();
172 void Init(bool prerender_search_results_base_page,
173 bool call_did_finish_load) {
174 AddTab(browser(), GURL(content::kAboutBlankURL));
176 content::SessionStorageNamespaceMap session_storage_namespace_map;
177 session_storage_namespace_map[std::string()] =
178 GetActiveWebContents()->GetController().
179 GetDefaultSessionStorageNamespace();
180 PrerenderManagerFactory::GetForProfile(browser()->profile())->
181 SetPrerenderContentsFactory(
182 new DummyPrerenderContentsFactory(call_did_finish_load,
183 session_storage_namespace_map));
185 if (prerender_search_results_base_page) {
186 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
187 prerenderer->Init(session_storage_namespace_map, gfx::Size(640, 480));
188 EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
192 InstantSearchPrerenderer* GetInstantSearchPrerenderer() {
193 return instant_service_->instant_search_prerenderer();
196 const GURL& GetPrerenderURL() {
197 return GetInstantSearchPrerenderer()->prerender_url_;
200 void SetLastQuery(const base::string16& query) {
201 GetInstantSearchPrerenderer()->last_instant_suggestion_ =
202 InstantSuggestion(query, std::string());
205 content::WebContents* prerender_contents() {
206 return GetInstantSearchPrerenderer()->prerender_contents();
209 bool MessageWasSent(uint32 id) {
210 content::MockRenderProcessHost* process =
211 static_cast<content::MockRenderProcessHost*>(
212 prerender_contents()->GetRenderViewHost()->GetProcess());
213 return process->sink().GetFirstMessageMatching(id) != NULL;
216 content::WebContents* GetActiveWebContents() const {
217 return browser()->tab_strip_model()->GetWebContentsAt(0);
220 PrerenderHandle* prerender_handle() {
221 return GetInstantSearchPrerenderer()->prerender_handle_.get();
224 void PrerenderSearchQuery(const base::string16& query) {
225 Init(true, true);
226 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
227 prerenderer->Prerender(InstantSuggestion(query, std::string()));
228 CommitPendingLoad(&prerender_contents()->GetController());
229 EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(), query));
230 EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
234 TEST_F(InstantSearchPrerendererTest, GetSearchTermsFromPrerenderedPage) {
235 Init(false, false);
236 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
237 GURL url(GetPrerenderURL());
238 EXPECT_EQ(GURL("https://www.google.com/instant?ion=1&foo=foo#foo=foo&strk"),
239 url);
240 EXPECT_EQ(base::UTF16ToASCII(prerenderer->get_last_query()),
241 base::UTF16ToASCII(
242 chrome::ExtractSearchTermsFromURL(profile(), url)));
244 // Assume the prerendered page prefetched search results for the query
245 // "flowers".
246 SetLastQuery(ASCIIToUTF16("flowers"));
247 EXPECT_EQ("flowers", base::UTF16ToASCII(prerenderer->get_last_query()));
248 EXPECT_EQ(base::UTF16ToASCII(prerenderer->get_last_query()),
249 base::UTF16ToASCII(
250 chrome::ExtractSearchTermsFromURL(profile(), url)));
253 TEST_F(InstantSearchPrerendererTest, PrefetchSearchResults) {
254 Init(true, true);
255 EXPECT_TRUE(prerender_handle()->IsFinishedLoading());
256 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
257 prerenderer->Prerender(
258 InstantSuggestion(ASCIIToUTF16("flowers"), std::string()));
259 EXPECT_EQ("flowers", base::UTF16ToASCII(prerenderer->get_last_query()));
260 EXPECT_TRUE(MessageWasSent(
261 ChromeViewMsg_SearchBoxSetSuggestionToPrefetch::ID));
264 TEST_F(InstantSearchPrerendererTest, DoNotPrefetchSearchResults) {
265 Init(true, false);
266 // Page hasn't finished loading yet.
267 EXPECT_FALSE(prerender_handle()->IsFinishedLoading());
268 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
269 prerenderer->Prerender(
270 InstantSuggestion(ASCIIToUTF16("flowers"), std::string()));
271 EXPECT_EQ("", base::UTF16ToASCII(prerenderer->get_last_query()));
272 EXPECT_FALSE(MessageWasSent(
273 ChromeViewMsg_SearchBoxSetSuggestionToPrefetch::ID));
276 TEST_F(InstantSearchPrerendererTest, CanCommitQuery) {
277 Init(true, true);
278 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
279 base::string16 query = ASCIIToUTF16("flowers");
280 prerenderer->Prerender(InstantSuggestion(query, std::string()));
281 EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(), query));
283 // Make sure InstantSearchPrerenderer::CanCommitQuery() returns false for
284 // invalid search queries.
285 EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
286 ASCIIToUTF16("joy")));
287 EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
288 base::string16()));
291 TEST_F(InstantSearchPrerendererTest, CommitQuery) {
292 base::string16 query = ASCIIToUTF16("flowers");
293 PrerenderSearchQuery(query);
294 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
295 prerenderer->Commit(query);
296 EXPECT_TRUE(MessageWasSent(ChromeViewMsg_SearchBoxSubmit::ID));
299 TEST_F(InstantSearchPrerendererTest, CancelPrerenderRequestOnTabChangeEvent) {
300 Init(true, true);
301 EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
303 // Add a new tab to deactivate the current tab.
304 AddTab(browser(), GURL(content::kAboutBlankURL));
305 EXPECT_EQ(2, browser()->tab_strip_model()->count());
307 // Make sure the pending prerender request is cancelled.
308 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
311 TEST_F(InstantSearchPrerendererTest, CancelPendingPrerenderRequest) {
312 Init(true, true);
313 EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
315 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
316 prerenderer->Cancel();
317 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
320 TEST_F(InstantSearchPrerendererTest, PrerenderingAllowed) {
321 Init(true, true);
322 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
323 content::WebContents* active_tab = GetActiveWebContents();
324 EXPECT_EQ(GURL(content::kAboutBlankURL), active_tab->GetURL());
326 // Allow prerendering only for search type AutocompleteMatch suggestions.
327 AutocompleteMatch search_type_match(NULL, 1100, false,
328 AutocompleteMatchType::SEARCH_SUGGEST);
329 EXPECT_TRUE(AutocompleteMatch::IsSearchType(search_type_match.type));
330 EXPECT_TRUE(prerenderer->IsAllowed(search_type_match, active_tab));
332 AutocompleteMatch url_type_match(NULL, 1100, true,
333 AutocompleteMatchType::URL_WHAT_YOU_TYPED);
334 EXPECT_FALSE(AutocompleteMatch::IsSearchType(url_type_match.type));
335 EXPECT_FALSE(prerenderer->IsAllowed(url_type_match, active_tab));
337 // Search results page supports Instant search. InstantSearchPrerenderer is
338 // used only when the underlying page doesn't support Instant.
339 NavigateAndCommitActiveTab(GURL("https://www.google.com/alt#quux=foo&strk"));
340 active_tab = GetActiveWebContents();
341 EXPECT_FALSE(chrome::ExtractSearchTermsFromURL(profile(),
342 active_tab->GetURL()).empty());
343 EXPECT_FALSE(chrome::ShouldPrefetchSearchResultsOnSRP());
344 EXPECT_FALSE(prerenderer->IsAllowed(search_type_match, active_tab));
347 TEST_F(InstantSearchPrerendererTest, UsePrerenderPage) {
348 PrerenderSearchQuery(ASCIIToUTF16("foo"));
350 // Open a search results page. A prerendered page exists for |url|. Make sure
351 // the browser swaps the current tab contents with the prerendered contents.
352 GURL url("https://www.google.com/alt#quux=foo&strk");
353 browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
354 content::PAGE_TRANSITION_TYPED,
355 false));
356 EXPECT_EQ(GetPrerenderURL(), GetActiveWebContents()->GetURL());
357 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
360 TEST_F(InstantSearchPrerendererTest, PrerenderRequestCancelled) {
361 PrerenderSearchQuery(ASCIIToUTF16("foo"));
363 // Cancel the prerender request.
364 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
365 prerenderer->Cancel();
366 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
368 // Open a search results page. Prerendered page does not exists for |url|.
369 // Make sure the browser navigates the current tab to this |url|.
370 GURL url("https://www.google.com/alt#quux=foo&strk");
371 browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
372 content::PAGE_TRANSITION_TYPED,
373 false));
374 EXPECT_NE(GetPrerenderURL(), GetActiveWebContents()->GetURL());
375 EXPECT_EQ(url, GetActiveWebContents()->GetURL());
378 TEST_F(InstantSearchPrerendererTest,
379 CancelPrerenderRequest_SearchQueryMistmatch) {
380 PrerenderSearchQuery(ASCIIToUTF16("foo"));
382 // Open a search results page. Committed query("pen") doesn't match with the
383 // prerendered search query("foo"). Make sure the InstantSearchPrerenderer
384 // cancels the active prerender request and the browser navigates the active
385 // tab to this |url|.
386 GURL url("https://www.google.com/alt#quux=pen&strk");
387 browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
388 content::PAGE_TRANSITION_TYPED,
389 false));
390 EXPECT_NE(GetPrerenderURL(), GetActiveWebContents()->GetURL());
391 EXPECT_EQ(url, GetActiveWebContents()->GetURL());
392 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
395 TEST_F(InstantSearchPrerendererTest,
396 CancelPrerenderRequest_EmptySearchQueryCommitted) {
397 PrerenderSearchQuery(ASCIIToUTF16("foo"));
399 // Open a search results page. Make sure the InstantSearchPrerenderer cancels
400 // the active prerender request upon the receipt of empty search query.
401 GURL url("https://www.google.com/alt#quux=&strk");
402 browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
403 content::PAGE_TRANSITION_TYPED,
404 false));
405 EXPECT_NE(GetPrerenderURL(), GetActiveWebContents()->GetURL());
406 EXPECT_EQ(url, GetActiveWebContents()->GetURL());
407 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
410 class ReuseInstantSearchBasePageTest : public InstantSearchPrerendererTest {
411 public:
412 ReuseInstantSearchBasePageTest() {}
414 protected:
415 virtual void SetUp() OVERRIDE {
416 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
417 "EmbeddedSearch",
418 "Group1 strk:20 prefetch_results:1 reuse_instant_search_base_page:1"));
419 InstantUnitTestBase::SetUp();
423 TEST_F(ReuseInstantSearchBasePageTest, CanCommitQuery) {
424 Init(true, true);
425 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
426 base::string16 query = ASCIIToUTF16("flowers");
427 prerenderer->Prerender(InstantSuggestion(query, std::string()));
428 EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(), query));
430 // When the Instant search base page has finished loading,
431 // InstantSearchPrerenderer can commit any search query to the prerendered
432 // page (even if it doesn't match the last known suggestion query).
433 EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(),
434 ASCIIToUTF16("joy")));
435 // Invalid search query committed.
436 EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
437 base::string16()));
440 TEST_F(ReuseInstantSearchBasePageTest,
441 CanCommitQuery_InstantSearchBasePageLoadInProgress) {
442 Init(true, false);
443 InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
444 base::string16 query = ASCIIToUTF16("flowers");
445 prerenderer->Prerender(InstantSuggestion(query, std::string()));
447 // When the Instant search base page hasn't finished loading,
448 // InstantSearchPrerenderer cannot commit any search query to the base page.
449 EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(), query));
450 EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
451 ASCIIToUTF16("joy")));
454 #if !defined(OS_IOS) && !defined(OS_ANDROID)
455 class TestUsePrerenderPage : public InstantSearchPrerendererTest {
456 protected:
457 virtual void SetUp() OVERRIDE {
458 // Disable query extraction flag in field trials.
459 ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
460 "EmbeddedSearch",
461 "Group1 strk:20 query_extraction:0 prefetch_results:1"));
462 InstantUnitTestBase::SetUpWithoutQueryExtraction();
466 TEST_F(TestUsePrerenderPage, ExtractSearchTermsAndUsePrerenderPage) {
467 PrerenderSearchQuery(ASCIIToUTF16("foo"));
469 // Open a search results page. Query extraction flag is disabled in field
470 // trials. Search results page URL does not contain search terms replacement
471 // key. Make sure UsePrerenderedPage() extracts the search terms from the URL
472 // and uses the prerendered page contents.
473 GURL url("https://www.google.com/alt#quux=foo");
474 browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
475 content::PAGE_TRANSITION_TYPED,
476 false));
477 EXPECT_EQ(GetPrerenderURL(), GetActiveWebContents()->GetURL());
478 EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
480 #endif