Home | History | Annotate | Download | only in search
      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.
      4 
      5 #include "chrome/browser/ui/search/instant_search_prerenderer.h"
      6 
      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/prerender/prerender_contents.h"
     14 #include "chrome/browser/prerender/prerender_handle.h"
     15 #include "chrome/browser/prerender/prerender_manager.h"
     16 #include "chrome/browser/prerender/prerender_manager_factory.h"
     17 #include "chrome/browser/prerender/prerender_origin.h"
     18 #include "chrome/browser/prerender/prerender_tab_helper.h"
     19 #include "chrome/browser/prerender/prerender_tracker.h"
     20 #include "chrome/browser/profiles/profile.h"
     21 #include "chrome/browser/search/instant_service.h"
     22 #include "chrome/browser/search/instant_unittest_base.h"
     23 #include "chrome/browser/search/search.h"
     24 #include "chrome/browser/ui/search/search_tab_helper.h"
     25 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     26 #include "chrome/common/render_messages.h"
     27 #include "components/omnibox/autocomplete_match.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"
     35 
     36 using base::ASCIIToUTF16;
     37 
     38 namespace {
     39 
     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;
     47 
     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);
     58 
     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;
     66 
     67  private:
     68   Profile* profile_;
     69   const GURL url_;
     70   bool call_did_finish_load_;
     71   content::SessionStorageNamespaceMap session_storage_namespace_map_;
     72 
     73   DISALLOW_COPY_AND_ASSIGN(DummyPrerenderContents);
     74 };
     75 
     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) {
     83   }
     84 
     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;
     92 
     93  private:
     94   bool call_did_finish_load_;
     95   content::SessionStorageNamespaceMap session_storage_namespace_map_;
     96 
     97   DISALLOW_COPY_AND_ASSIGN(DummyPrerenderContentsFactory);
     98 };
     99 
    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) {
    114 }
    115 
    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());
    129 
    130   prerendering_has_started_ = true;
    131   DCHECK(session_storage_namespace);
    132   session_storage_namespace_id_ = session_storage_namespace->id();
    133   NotifyPrerenderStart();
    134 
    135   if (call_did_finish_load_)
    136     DidFinishLoad(prerender_contents_->GetMainFrame(), url_);
    137 }
    138 
    139 bool DummyPrerenderContents::GetChildId(int* child_id) const {
    140   *child_id = 1;
    141   return true;
    142 }
    143 
    144 bool DummyPrerenderContents::GetRouteId(int* route_id) const {
    145   *route_id = 1;
    146   return true;
    147 }
    148 
    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_);
    159 }
    160 
    161 }  // namespace
    162 
    163 class InstantSearchPrerendererTest : public InstantUnitTestBase {
    164  public:
    165   InstantSearchPrerendererTest() {}
    166 
    167  protected:
    168   virtual void SetUp() OVERRIDE {
    169     ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
    170                                                        "Group1 strk:20"));
    171     InstantUnitTestBase::SetUp();
    172   }
    173 
    174   void Init(bool prerender_search_results_base_page,
    175             bool call_did_finish_load) {
    176     AddTab(browser(), GURL(url::kAboutBlankURL));
    177 
    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());
    192     }
    193   }
    194 
    195   InstantSearchPrerenderer* GetInstantSearchPrerenderer() {
    196     return instant_service_->instant_search_prerenderer();
    197   }
    198 
    199   const GURL& GetPrerenderURL() {
    200     return GetInstantSearchPrerenderer()->prerender_url_;
    201   }
    202 
    203   void SetLastQuery(const base::string16& query) {
    204     GetInstantSearchPrerenderer()->last_instant_suggestion_ =
    205         InstantSuggestion(query, std::string());
    206   }
    207 
    208   content::WebContents* prerender_contents() {
    209     return GetInstantSearchPrerenderer()->prerender_contents();
    210   }
    211 
    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;
    217   }
    218 
    219   content::WebContents* GetActiveWebContents() const {
    220     return browser()->tab_strip_model()->GetWebContentsAt(0);
    221   }
    222 
    223   PrerenderHandle* prerender_handle() {
    224     return GetInstantSearchPrerenderer()->prerender_handle_.get();
    225   }
    226 
    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());
    234   }
    235 };
    236 
    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)));
    246 
    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)));
    254 }
    255 
    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));
    265 }
    266 
    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));
    277 }
    278 
    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));
    285 
    286   // Make sure InstantSearchPrerenderer::CanCommitQuery() returns false for
    287   // invalid search queries.
    288   EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(),
    289                                           ASCIIToUTF16("joy")));
    290   EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
    291                                            base::string16()));
    292 }
    293 
    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));
    300 }
    301 
    302 TEST_F(InstantSearchPrerendererTest, CancelPrerenderRequestOnTabChangeEvent) {
    303   Init(true, true);
    304   EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
    305 
    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());
    309 
    310   // Make sure the pending prerender request is cancelled.
    311   EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
    312 }
    313 
    314 TEST_F(InstantSearchPrerendererTest, CancelPendingPrerenderRequest) {
    315   Init(true, true);
    316   EXPECT_NE(static_cast<PrerenderHandle*>(NULL), prerender_handle());
    317 
    318   InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
    319   prerenderer->Cancel();
    320   EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
    321 }
    322 
    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());
    328 
    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));
    334 
    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));
    339 
    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));
    348 }
    349 
    350 TEST_F(InstantSearchPrerendererTest, UsePrerenderPage) {
    351   PrerenderSearchQuery(ASCIIToUTF16("foo"));
    352 
    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                                             ui::PAGE_TRANSITION_TYPED,
    358                                             false));
    359   EXPECT_EQ(GetPrerenderURL(), GetActiveWebContents()->GetURL());
    360   EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
    361 }
    362 
    363 TEST_F(InstantSearchPrerendererTest, PrerenderRequestCancelled) {
    364   PrerenderSearchQuery(ASCIIToUTF16("foo"));
    365 
    366   // Cancel the prerender request.
    367   InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
    368   prerenderer->Cancel();
    369   EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
    370 
    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                                             ui::PAGE_TRANSITION_TYPED,
    376                                             false));
    377   EXPECT_NE(GetPrerenderURL(), GetActiveWebContents()->GetURL());
    378   EXPECT_EQ(url, GetActiveWebContents()->GetURL());
    379 }
    380 
    381 TEST_F(InstantSearchPrerendererTest,
    382        UsePrerenderedPage_SearchQueryMistmatch) {
    383   PrerenderSearchQuery(ASCIIToUTF16("foo"));
    384 
    385   // Open a search results page. Committed query("pen") doesn't match with the
    386   // prerendered search query("foo"). Make sure the browser swaps the current
    387   // tab contents with the prerendered contents.
    388   GURL url("https://www.google.com/alt#quux=pen&strk");
    389   browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
    390                                             ui::PAGE_TRANSITION_TYPED,
    391                                             false));
    392   EXPECT_EQ(GetPrerenderURL(), GetActiveWebContents()->GetURL());
    393   EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
    394 }
    395 
    396 TEST_F(InstantSearchPrerendererTest,
    397        CancelPrerenderRequest_EmptySearchQueryCommitted) {
    398   PrerenderSearchQuery(ASCIIToUTF16("foo"));
    399 
    400   // Open a search results page. Make sure the InstantSearchPrerenderer cancels
    401   // the active prerender request upon the receipt of empty search query.
    402   GURL url("https://www.google.com/alt#quux=&strk");
    403   browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
    404                                             ui::PAGE_TRANSITION_TYPED,
    405                                             false));
    406   EXPECT_NE(GetPrerenderURL(), GetActiveWebContents()->GetURL());
    407   EXPECT_EQ(url, GetActiveWebContents()->GetURL());
    408   EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
    409 }
    410 
    411 TEST_F(InstantSearchPrerendererTest,
    412        CancelPrerenderRequest_UnsupportedDispositions) {
    413   PrerenderSearchQuery(ASCIIToUTF16("pen"));
    414 
    415   // Open a search results page. Make sure the InstantSearchPrerenderer cancels
    416   // the active prerender request for unsupported window dispositions.
    417   GURL url("https://www.google.com/alt#quux=pen&strk");
    418   browser()->OpenURL(content::OpenURLParams(url, Referrer(), NEW_FOREGROUND_TAB,
    419                                             ui::PAGE_TRANSITION_TYPED,
    420                                             false));
    421   content::WebContents* new_tab =
    422       browser()->tab_strip_model()->GetWebContentsAt(1);
    423   EXPECT_NE(GetPrerenderURL(), new_tab->GetURL());
    424   EXPECT_EQ(url, new_tab->GetURL());
    425   EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
    426 }
    427 
    428 class ReuseInstantSearchBasePageTest : public InstantSearchPrerendererTest {
    429   public:
    430    ReuseInstantSearchBasePageTest() {}
    431 
    432   protected:
    433    virtual void SetUp() OVERRIDE {
    434     ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial("EmbeddedSearch",
    435                                                        "Group1 strk:20"));
    436     InstantUnitTestBase::SetUp();
    437    }
    438 };
    439 
    440 TEST_F(ReuseInstantSearchBasePageTest, CanCommitQuery) {
    441   Init(true, true);
    442   InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
    443   base::string16 query = ASCIIToUTF16("flowers");
    444   prerenderer->Prerender(InstantSuggestion(query, std::string()));
    445   EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(), query));
    446 
    447   // When the Instant search base page has finished loading,
    448   // InstantSearchPrerenderer can commit any search query to the prerendered
    449   // page (even if it doesn't match the last known suggestion query).
    450   EXPECT_TRUE(prerenderer->CanCommitQuery(GetActiveWebContents(),
    451                                            ASCIIToUTF16("joy")));
    452   // Invalid search query committed.
    453   EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
    454                                            base::string16()));
    455 }
    456 
    457 TEST_F(ReuseInstantSearchBasePageTest,
    458        CanCommitQuery_InstantSearchBasePageLoadInProgress) {
    459   Init(true, false);
    460   InstantSearchPrerenderer* prerenderer = GetInstantSearchPrerenderer();
    461   base::string16 query = ASCIIToUTF16("flowers");
    462   prerenderer->Prerender(InstantSuggestion(query, std::string()));
    463 
    464   // When the Instant search base page hasn't finished loading,
    465   // InstantSearchPrerenderer cannot commit any search query to the base page.
    466   EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(), query));
    467   EXPECT_FALSE(prerenderer->CanCommitQuery(GetActiveWebContents(),
    468                                            ASCIIToUTF16("joy")));
    469 }
    470 
    471 #if !defined(OS_IOS) && !defined(OS_ANDROID)
    472 class TestUsePrerenderPage : public InstantSearchPrerendererTest {
    473  protected:
    474   virtual void SetUp() OVERRIDE {
    475     // Disable query extraction flag in field trials.
    476     ASSERT_TRUE(base::FieldTrialList::CreateFieldTrial(
    477         "EmbeddedSearch", "Group1 strk:20 query_extraction:0"));
    478     InstantUnitTestBase::SetUpWithoutQueryExtraction();
    479   }
    480 };
    481 
    482 TEST_F(TestUsePrerenderPage, ExtractSearchTermsAndUsePrerenderPage) {
    483   PrerenderSearchQuery(ASCIIToUTF16("foo"));
    484 
    485   // Open a search results page. Query extraction flag is disabled in field
    486   // trials. Search results page URL does not contain search terms replacement
    487   // key. Make sure UsePrerenderedPage() extracts the search terms from the URL
    488   // and uses the prerendered page contents.
    489   GURL url("https://www.google.com/alt#quux=foo");
    490   browser()->OpenURL(content::OpenURLParams(url, Referrer(), CURRENT_TAB,
    491                                             ui::PAGE_TRANSITION_TYPED,
    492                                             false));
    493   EXPECT_EQ(GetPrerenderURL(), GetActiveWebContents()->GetURL());
    494   EXPECT_EQ(static_cast<PrerenderHandle*>(NULL), prerender_handle());
    495 }
    496 #endif
    497