Home | History | Annotate | Download | only in prerender
      1 // Copyright (c) 2012 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 <deque>
      6 #include <vector>
      7 
      8 #include "base/bind.h"
      9 #include "base/command_line.h"
     10 #include "base/files/file_path.h"
     11 #include "base/memory/ref_counted_memory.h"
     12 #include "base/memory/scoped_vector.h"
     13 #include "base/memory/weak_ptr.h"
     14 #include "base/path_service.h"
     15 #include "base/prefs/pref_service.h"
     16 #include "base/run_loop.h"
     17 #include "base/strings/string_util.h"
     18 #include "base/strings/stringprintf.h"
     19 #include "base/strings/utf_string_conversions.h"
     20 #include "base/test/histogram_tester.h"
     21 #include "base/test/test_timeouts.h"
     22 #include "base/values.h"
     23 #include "chrome/browser/browsing_data/browsing_data_helper.h"
     24 #include "chrome/browser/browsing_data/browsing_data_remover.h"
     25 #include "chrome/browser/browsing_data/browsing_data_remover_test_util.h"
     26 #include "chrome/browser/chrome_content_browser_client.h"
     27 #include "chrome/browser/chrome_notification_types.h"
     28 #include "chrome/browser/content_settings/host_content_settings_map.h"
     29 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
     30 #include "chrome/browser/extensions/extension_apitest.h"
     31 #include "chrome/browser/external_protocol/external_protocol_handler.h"
     32 #include "chrome/browser/favicon/favicon_tab_helper.h"
     33 #include "chrome/browser/net/prediction_options.h"
     34 #include "chrome/browser/predictors/autocomplete_action_predictor.h"
     35 #include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
     36 #include "chrome/browser/prerender/prerender_contents.h"
     37 #include "chrome/browser/prerender/prerender_field_trial.h"
     38 #include "chrome/browser/prerender/prerender_handle.h"
     39 #include "chrome/browser/prerender/prerender_link_manager.h"
     40 #include "chrome/browser/prerender/prerender_link_manager_factory.h"
     41 #include "chrome/browser/prerender/prerender_manager.h"
     42 #include "chrome/browser/prerender/prerender_manager_factory.h"
     43 #include "chrome/browser/profiles/profile.h"
     44 #include "chrome/browser/profiles/profile_io_data.h"
     45 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h"
     46 #include "chrome/browser/safe_browsing/database_manager.h"
     47 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
     48 #include "chrome/browser/safe_browsing/safe_browsing_util.h"
     49 #include "chrome/browser/task_manager/task_manager.h"
     50 #include "chrome/browser/task_manager/task_manager_browsertest_util.h"
     51 #include "chrome/browser/ui/browser.h"
     52 #include "chrome/browser/ui/browser_commands.h"
     53 #include "chrome/browser/ui/browser_finder.h"
     54 #include "chrome/browser/ui/browser_navigator.h"
     55 #include "chrome/browser/ui/browser_window.h"
     56 #include "chrome/browser/ui/location_bar/location_bar.h"
     57 #include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
     58 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
     59 #include "chrome/browser/ui/omnibox/omnibox_view.h"
     60 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     61 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
     62 #include "chrome/common/chrome_paths.h"
     63 #include "chrome/common/chrome_switches.h"
     64 #include "chrome/common/extensions/extension_constants.h"
     65 #include "chrome/common/extensions/manifest_handlers/mime_types_handler.h"
     66 #include "chrome/common/pref_names.h"
     67 #include "chrome/grit/generated_resources.h"
     68 #include "chrome/test/base/in_process_browser_test.h"
     69 #include "chrome/test/base/test_switches.h"
     70 #include "chrome/test/base/ui_test_utils.h"
     71 #include "components/variations/entropy_provider.h"
     72 #include "components/variations/variations_associated_data.h"
     73 #include "content/public/browser/browser_message_filter.h"
     74 #include "content/public/browser/devtools_agent_host.h"
     75 #include "content/public/browser/navigation_controller.h"
     76 #include "content/public/browser/navigation_entry.h"
     77 #include "content/public/browser/notification_service.h"
     78 #include "content/public/browser/render_frame_host.h"
     79 #include "content/public/browser/render_process_host.h"
     80 #include "content/public/browser/render_view_host.h"
     81 #include "content/public/browser/site_instance.h"
     82 #include "content/public/browser/web_contents.h"
     83 #include "content/public/browser/web_contents_observer.h"
     84 #include "content/public/common/url_constants.h"
     85 #include "content/public/test/browser_test_utils.h"
     86 #include "content/public/test/test_navigation_observer.h"
     87 #include "content/public/test/test_utils.h"
     88 #include "extensions/common/extension_urls.h"
     89 #include "extensions/common/switches.h"
     90 #include "extensions/test/result_catcher.h"
     91 #include "net/base/escape.h"
     92 #include "net/cert/x509_certificate.h"
     93 #include "net/dns/mock_host_resolver.h"
     94 #include "net/ssl/client_cert_store.h"
     95 #include "net/ssl/ssl_cert_request_info.h"
     96 #include "net/test/url_request/url_request_mock_http_job.h"
     97 #include "net/url_request/url_request_context.h"
     98 #include "net/url_request/url_request_context_getter.h"
     99 #include "net/url_request/url_request_filter.h"
    100 #include "net/url_request/url_request_interceptor.h"
    101 #include "net/url_request/url_request_job.h"
    102 #include "ui/base/l10n/l10n_util.h"
    103 #include "url/gurl.h"
    104 
    105 using chrome_browser_net::NetworkPredictionOptions;
    106 using content::BrowserThread;
    107 using content::DevToolsAgentHost;
    108 using content::NavigationController;
    109 using content::OpenURLParams;
    110 using content::Referrer;
    111 using content::RenderFrameHost;
    112 using content::RenderViewHost;
    113 using content::RenderWidgetHost;
    114 using content::TestNavigationObserver;
    115 using content::WebContents;
    116 using content::WebContentsObserver;
    117 using net::NetworkChangeNotifier;
    118 using task_manager::browsertest_util::WaitForTaskManagerRows;
    119 
    120 // Prerender tests work as follows:
    121 //
    122 // A page with a prefetch link to the test page is loaded.  Once prerendered,
    123 // its Javascript function DidPrerenderPass() is called, which returns true if
    124 // the page behaves as expected when prerendered.
    125 //
    126 // The prerendered page is then displayed on a tab.  The Javascript function
    127 // DidDisplayPass() is called, and returns true if the page behaved as it
    128 // should while being displayed.
    129 
    130 namespace prerender {
    131 
    132 namespace {
    133 
    134 class MockNetworkChangeNotifierWIFI : public NetworkChangeNotifier {
    135  public:
    136   virtual ConnectionType GetCurrentConnectionType() const OVERRIDE {
    137     return NetworkChangeNotifier::CONNECTION_WIFI;
    138   }
    139 };
    140 
    141 class MockNetworkChangeNotifier4G : public NetworkChangeNotifier {
    142  public:
    143   virtual ConnectionType GetCurrentConnectionType() const OVERRIDE {
    144     return NetworkChangeNotifier::CONNECTION_4G;
    145   }
    146 };
    147 
    148 // Constants used in the test HTML files.
    149 const char* kReadyTitle = "READY";
    150 const char* kPassTitle = "PASS";
    151 
    152 std::string CreateClientRedirect(const std::string& dest_url) {
    153   const char* const kClientRedirectBase = "client-redirect?";
    154   return kClientRedirectBase + net::EscapeQueryParamValue(dest_url, false);
    155 }
    156 
    157 std::string CreateServerRedirect(const std::string& dest_url) {
    158   const char* const kServerRedirectBase = "server-redirect?";
    159   return kServerRedirectBase + net::EscapeQueryParamValue(dest_url, false);
    160 }
    161 
    162 // Clears the specified data using BrowsingDataRemover.
    163 void ClearBrowsingData(Browser* browser, int remove_mask) {
    164   BrowsingDataRemover* remover =
    165       BrowsingDataRemover::CreateForUnboundedRange(browser->profile());
    166   BrowsingDataRemoverCompletionObserver observer(remover);
    167   remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
    168   observer.BlockUntilCompletion();
    169   // BrowsingDataRemover deletes itself.
    170 }
    171 
    172 // Returns true if the prerender is expected to abort on its own, before
    173 // attempting to swap it.
    174 bool ShouldAbortPrerenderBeforeSwap(FinalStatus status) {
    175   switch (status) {
    176     case FINAL_STATUS_USED:
    177     case FINAL_STATUS_WINDOW_OPENER:
    178     case FINAL_STATUS_APP_TERMINATING:
    179     case FINAL_STATUS_PROFILE_DESTROYED:
    180     case FINAL_STATUS_CACHE_OR_HISTORY_CLEARED:
    181     // We'll crash the renderer after it's loaded.
    182     case FINAL_STATUS_RENDERER_CRASHED:
    183     case FINAL_STATUS_CANCELLED:
    184     case FINAL_STATUS_DEVTOOLS_ATTACHED:
    185     case FINAL_STATUS_PAGE_BEING_CAPTURED:
    186     case FINAL_STATUS_NAVIGATION_UNCOMMITTED:
    187     case FINAL_STATUS_WOULD_HAVE_BEEN_USED:
    188     case FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE:
    189       return false;
    190     default:
    191       return true;
    192   }
    193 }
    194 
    195 // Convenience function to wait for a title. Handles the case when the
    196 // WebContents already has the expected title.
    197 void WaitForASCIITitle(WebContents* web_contents,
    198                        const char* expected_title_ascii) {
    199   base::string16 expected_title = base::ASCIIToUTF16(expected_title_ascii);
    200   if (web_contents->GetTitle() == expected_title)
    201     return;
    202   content::TitleWatcher title_watcher(web_contents, expected_title);
    203   EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
    204 }
    205 
    206 // Waits for the destruction of a RenderProcessHost's IPC channel.
    207 // Used to make sure the PrerenderLinkManager's OnChannelClosed function has
    208 // been called, before checking its state.
    209 class ChannelDestructionWatcher {
    210  public:
    211   ChannelDestructionWatcher() : channel_destroyed_(false) {
    212   }
    213 
    214   ~ChannelDestructionWatcher() {
    215   }
    216 
    217   void WatchChannel(content::RenderProcessHost* host) {
    218     host->AddFilter(new DestructionMessageFilter(this));
    219   }
    220 
    221   void WaitForChannelClose() {
    222     run_loop_.Run();
    223     EXPECT_TRUE(channel_destroyed_);
    224   }
    225 
    226  private:
    227   // When destroyed, calls ChannelDestructionWatcher::OnChannelDestroyed.
    228   // Ignores all messages.
    229   class DestructionMessageFilter : public content::BrowserMessageFilter {
    230    public:
    231      explicit DestructionMessageFilter(ChannelDestructionWatcher* watcher)
    232          : BrowserMessageFilter(0),
    233            watcher_(watcher) {
    234     }
    235 
    236    private:
    237     virtual ~DestructionMessageFilter() {
    238       content::BrowserThread::PostTask(
    239           content::BrowserThread::UI, FROM_HERE,
    240           base::Bind(&ChannelDestructionWatcher::OnChannelDestroyed,
    241                      base::Unretained(watcher_)));
    242     }
    243 
    244     virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
    245       return false;
    246     }
    247 
    248     ChannelDestructionWatcher* watcher_;
    249 
    250     DISALLOW_COPY_AND_ASSIGN(DestructionMessageFilter);
    251   };
    252 
    253   void OnChannelDestroyed() {
    254     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    255 
    256     EXPECT_FALSE(channel_destroyed_);
    257     channel_destroyed_ = true;
    258     run_loop_.Quit();
    259   }
    260 
    261   bool channel_destroyed_;
    262   base::RunLoop run_loop_;
    263 
    264   DISALLOW_COPY_AND_ASSIGN(ChannelDestructionWatcher);
    265 };
    266 
    267 // A navigation observer to wait on either a new load or a swap of a
    268 // WebContents. On swap, if the new WebContents is still loading, wait for that
    269 // load to complete as well. Note that the load must begin after the observer is
    270 // attached.
    271 class NavigationOrSwapObserver : public WebContentsObserver,
    272                                  public TabStripModelObserver {
    273  public:
    274   // Waits for either a new load or a swap of |tab_strip_model|'s active
    275   // WebContents.
    276   NavigationOrSwapObserver(TabStripModel* tab_strip_model,
    277                            WebContents* web_contents)
    278       : WebContentsObserver(web_contents),
    279         tab_strip_model_(tab_strip_model),
    280         did_start_loading_(false),
    281         number_of_loads_(1) {
    282     CHECK_NE(TabStripModel::kNoTab,
    283              tab_strip_model->GetIndexOfWebContents(web_contents));
    284     tab_strip_model_->AddObserver(this);
    285   }
    286 
    287   // Waits for either |number_of_loads| loads or a swap of |tab_strip_model|'s
    288   // active WebContents.
    289   NavigationOrSwapObserver(TabStripModel* tab_strip_model,
    290                            WebContents* web_contents,
    291                            int number_of_loads)
    292       : WebContentsObserver(web_contents),
    293         tab_strip_model_(tab_strip_model),
    294         did_start_loading_(false),
    295         number_of_loads_(number_of_loads) {
    296     CHECK_NE(TabStripModel::kNoTab,
    297              tab_strip_model->GetIndexOfWebContents(web_contents));
    298     tab_strip_model_->AddObserver(this);
    299   }
    300 
    301   virtual ~NavigationOrSwapObserver() {
    302     tab_strip_model_->RemoveObserver(this);
    303   }
    304 
    305   void set_did_start_loading() {
    306     did_start_loading_ = true;
    307   }
    308 
    309   void Wait() {
    310     loop_.Run();
    311   }
    312 
    313   // WebContentsObserver implementation:
    314   virtual void DidStartLoading(RenderViewHost* render_view_host) OVERRIDE {
    315     did_start_loading_ = true;
    316   }
    317   virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE {
    318     if (!did_start_loading_)
    319       return;
    320     number_of_loads_--;
    321     if (number_of_loads_ == 0)
    322       loop_.Quit();
    323   }
    324 
    325   // TabStripModelObserver implementation:
    326   virtual void TabReplacedAt(TabStripModel* tab_strip_model,
    327                              WebContents* old_contents,
    328                              WebContents* new_contents,
    329                              int index) OVERRIDE {
    330     if (old_contents != web_contents())
    331       return;
    332     // Switch to observing the new WebContents.
    333     Observe(new_contents);
    334     if (new_contents->IsLoading()) {
    335       // If the new WebContents is still loading, wait for it to complete. Only
    336       // one load post-swap is supported.
    337       did_start_loading_ = true;
    338       number_of_loads_ = 1;
    339     } else {
    340       loop_.Quit();
    341     }
    342   }
    343 
    344  private:
    345   TabStripModel* tab_strip_model_;
    346   bool did_start_loading_;
    347   int number_of_loads_;
    348   base::RunLoop loop_;
    349 };
    350 
    351 // Waits for a new tab to open and a navigation or swap in it.
    352 class NewTabNavigationOrSwapObserver {
    353  public:
    354   NewTabNavigationOrSwapObserver()
    355       : new_tab_observer_(
    356             chrome::NOTIFICATION_TAB_ADDED,
    357             base::Bind(&NewTabNavigationOrSwapObserver::OnTabAdded,
    358                        base::Unretained(this))) {
    359     // Watch for NOTIFICATION_TAB_ADDED. Add a callback so that the
    360     // NavigationOrSwapObserver can be attached synchronously and no events are
    361     // missed.
    362   }
    363 
    364   void Wait() {
    365     new_tab_observer_.Wait();
    366     swap_observer_->Wait();
    367   }
    368 
    369   bool OnTabAdded(const content::NotificationSource& source,
    370                   const content::NotificationDetails& details) {
    371     if (swap_observer_)
    372       return true;
    373     WebContents* new_tab = content::Details<WebContents>(details).ptr();
    374     // Get the TabStripModel. Assume this is attached to a Browser.
    375     TabStripModel* tab_strip_model =
    376         static_cast<Browser*>(new_tab->GetDelegate())->tab_strip_model();
    377     swap_observer_.reset(new NavigationOrSwapObserver(tab_strip_model,
    378                                                       new_tab));
    379     swap_observer_->set_did_start_loading();
    380     return true;
    381   }
    382 
    383  private:
    384   content::WindowedNotificationObserver new_tab_observer_;
    385   scoped_ptr<NavigationOrSwapObserver> swap_observer_;
    386 };
    387 
    388 // PrerenderContents that stops the UI message loop on DidStopLoading().
    389 class TestPrerenderContents : public PrerenderContents {
    390  public:
    391   TestPrerenderContents(
    392       PrerenderManager* prerender_manager,
    393       Profile* profile,
    394       const GURL& url,
    395       const content::Referrer& referrer,
    396       Origin origin,
    397       FinalStatus expected_final_status)
    398       : PrerenderContents(prerender_manager, profile, url,
    399                           referrer, origin, PrerenderManager::kNoExperiment),
    400         expected_final_status_(expected_final_status),
    401         new_render_view_host_(NULL),
    402         was_hidden_(false),
    403         was_shown_(false),
    404         should_be_shown_(expected_final_status == FINAL_STATUS_USED),
    405         skip_final_checks_(false) {
    406   }
    407 
    408   virtual ~TestPrerenderContents() {
    409     if (skip_final_checks_)
    410       return;
    411 
    412     if (expected_final_status_ == FINAL_STATUS_MAX) {
    413       EXPECT_EQ(MATCH_COMPLETE_REPLACEMENT, match_complete_status());
    414     } else {
    415       EXPECT_EQ(expected_final_status_, final_status()) <<
    416           " when testing URL " << prerender_url().path() <<
    417           " (Expected: " << NameFromFinalStatus(expected_final_status_) <<
    418           ", Actual: " << NameFromFinalStatus(final_status()) << ")";
    419     }
    420     // Prerendering RenderViewHosts should be hidden before the first
    421     // navigation, so this should be happen for every PrerenderContents for
    422     // which a RenderViewHost is created, regardless of whether or not it's
    423     // used.
    424     if (new_render_view_host_)
    425       EXPECT_TRUE(was_hidden_);
    426 
    427     // A used PrerenderContents will only be destroyed when we swap out
    428     // WebContents, at the end of a navigation caused by a call to
    429     // NavigateToURLImpl().
    430     if (final_status() == FINAL_STATUS_USED)
    431       EXPECT_TRUE(new_render_view_host_);
    432 
    433     EXPECT_EQ(should_be_shown_, was_shown_);
    434   }
    435 
    436   virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE {
    437     // On quit, it's possible to end up here when render processes are closed
    438     // before the PrerenderManager is destroyed.  As a result, it's possible to
    439     // get either FINAL_STATUS_APP_TERMINATING or FINAL_STATUS_RENDERER_CRASHED
    440     // on quit.
    441     //
    442     // It's also possible for this to be called after we've been notified of
    443     // app termination, but before we've been deleted, which is why the second
    444     // check is needed.
    445     if (expected_final_status_ == FINAL_STATUS_APP_TERMINATING &&
    446         final_status() != expected_final_status_) {
    447       expected_final_status_ = FINAL_STATUS_RENDERER_CRASHED;
    448     }
    449 
    450     PrerenderContents::RenderProcessGone(status);
    451   }
    452 
    453   virtual bool CheckURL(const GURL& url) OVERRIDE {
    454     // Prevent FINAL_STATUS_UNSUPPORTED_SCHEME when navigating to about:crash in
    455     // the PrerenderRendererCrash test.
    456     if (url.spec() != content::kChromeUICrashURL)
    457       return PrerenderContents::CheckURL(url);
    458     return true;
    459   }
    460 
    461   // For tests that open the prerender in a new background tab, the RenderView
    462   // will not have been made visible when the PrerenderContents is destroyed
    463   // even though it is used.
    464   void set_should_be_shown(bool value) { should_be_shown_ = value; }
    465 
    466   // For tests which do not know whether the prerender will be used.
    467   void set_skip_final_checks(bool value) { skip_final_checks_ = value; }
    468 
    469   FinalStatus expected_final_status() const { return expected_final_status_; }
    470 
    471  private:
    472   virtual void OnRenderViewHostCreated(
    473       RenderViewHost* new_render_view_host) OVERRIDE {
    474     // Used to make sure the RenderViewHost is hidden and, if used,
    475     // subsequently shown.
    476     notification_registrar().Add(
    477         this,
    478         content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
    479         content::Source<RenderWidgetHost>(new_render_view_host));
    480 
    481     new_render_view_host_ = new_render_view_host;
    482 
    483     PrerenderContents::OnRenderViewHostCreated(new_render_view_host);
    484   }
    485 
    486   virtual void Observe(int type,
    487                        const content::NotificationSource& source,
    488                        const content::NotificationDetails& details) OVERRIDE {
    489     if (type ==
    490         content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) {
    491       EXPECT_EQ(new_render_view_host_,
    492                 content::Source<RenderWidgetHost>(source).ptr());
    493       bool is_visible = *content::Details<bool>(details).ptr();
    494 
    495       if (!is_visible) {
    496         was_hidden_ = true;
    497       } else if (is_visible && was_hidden_) {
    498         // Once hidden, a prerendered RenderViewHost should only be shown after
    499         // being removed from the PrerenderContents for display.
    500         EXPECT_FALSE(GetRenderViewHost());
    501         was_shown_ = true;
    502       }
    503       return;
    504     }
    505     PrerenderContents::Observe(type, source, details);
    506   }
    507 
    508   FinalStatus expected_final_status_;
    509 
    510   // The RenderViewHost created for the prerender, if any.
    511   RenderViewHost* new_render_view_host_;
    512   // Set to true when the prerendering RenderWidget is hidden.
    513   bool was_hidden_;
    514   // Set to true when the prerendering RenderWidget is shown, after having been
    515   // hidden.
    516   bool was_shown_;
    517   // Expected final value of was_shown_.  Defaults to true for
    518   // FINAL_STATUS_USED, and false otherwise.
    519   bool should_be_shown_;
    520   // If true, |expected_final_status_| and other shutdown checks are skipped.
    521   bool skip_final_checks_;
    522 };
    523 
    524 // A handle to a TestPrerenderContents whose lifetime is under the caller's
    525 // control. A PrerenderContents may be destroyed at any point. This allows
    526 // tracking the final status, etc.
    527 class TestPrerender : public PrerenderContents::Observer,
    528                       public base::SupportsWeakPtr<TestPrerender> {
    529  public:
    530   TestPrerender()
    531       : contents_(NULL),
    532         number_of_loads_(0),
    533         expected_number_of_loads_(0) {
    534   }
    535   virtual ~TestPrerender() {
    536     if (contents_)
    537       contents_->RemoveObserver(this);
    538   }
    539 
    540   TestPrerenderContents* contents() const { return contents_; }
    541   int number_of_loads() const { return number_of_loads_; }
    542 
    543   void WaitForCreate() { create_loop_.Run(); }
    544   void WaitForStart() { start_loop_.Run(); }
    545   void WaitForStop() { stop_loop_.Run(); }
    546 
    547   // Waits for |number_of_loads()| to be at least |expected_number_of_loads| OR
    548   // for the prerender to stop running (just to avoid a timeout if the prerender
    549   // dies). Note: this does not assert equality on the number of loads; the
    550   // caller must do it instead.
    551   void WaitForLoads(int expected_number_of_loads) {
    552     DCHECK(!load_waiter_);
    553     DCHECK(!expected_number_of_loads_);
    554     if (number_of_loads_ < expected_number_of_loads) {
    555       load_waiter_.reset(new base::RunLoop);
    556       expected_number_of_loads_ = expected_number_of_loads;
    557       load_waiter_->Run();
    558       load_waiter_.reset();
    559       expected_number_of_loads_ = 0;
    560     }
    561     EXPECT_LE(expected_number_of_loads, number_of_loads_);
    562   }
    563 
    564   void OnPrerenderCreated(TestPrerenderContents* contents) {
    565     DCHECK(!contents_);
    566     contents_ = contents;
    567     contents_->AddObserver(this);
    568     create_loop_.Quit();
    569   }
    570 
    571   // PrerenderContents::Observer implementation:
    572   virtual void OnPrerenderStart(PrerenderContents* contents) OVERRIDE {
    573     start_loop_.Quit();
    574   }
    575 
    576   virtual void OnPrerenderStopLoading(PrerenderContents* contents) OVERRIDE {
    577     number_of_loads_++;
    578     if (load_waiter_ && number_of_loads_ >= expected_number_of_loads_)
    579       load_waiter_->Quit();
    580   }
    581 
    582   virtual void OnPrerenderStop(PrerenderContents* contents) OVERRIDE {
    583     DCHECK(contents_);
    584     contents_ = NULL;
    585     stop_loop_.Quit();
    586     // If there is a WaitForLoads call and it has yet to see the expected number
    587     // of loads, stop the loop so the test fails instead of timing out.
    588     if (load_waiter_)
    589       load_waiter_->Quit();
    590   }
    591 
    592   virtual void OnPrerenderCreatedMatchCompleteReplacement(
    593       PrerenderContents* contents, PrerenderContents* replacement) OVERRIDE {
    594   }
    595 
    596  private:
    597   TestPrerenderContents* contents_;
    598   int number_of_loads_;
    599 
    600   int expected_number_of_loads_;
    601   scoped_ptr<base::RunLoop> load_waiter_;
    602 
    603   base::RunLoop create_loop_;
    604   base::RunLoop start_loop_;
    605   base::RunLoop stop_loop_;
    606 
    607   DISALLOW_COPY_AND_ASSIGN(TestPrerender);
    608 };
    609 
    610 // PrerenderManager that uses TestPrerenderContents.
    611 class TestPrerenderContentsFactory : public PrerenderContents::Factory {
    612  public:
    613   TestPrerenderContentsFactory() {}
    614 
    615   virtual ~TestPrerenderContentsFactory() {
    616     EXPECT_TRUE(expected_contents_queue_.empty());
    617   }
    618 
    619   scoped_ptr<TestPrerender> ExpectPrerenderContents(FinalStatus final_status) {
    620     scoped_ptr<TestPrerender> handle(new TestPrerender());
    621     expected_contents_queue_.push_back(
    622         ExpectedContents(final_status, handle->AsWeakPtr()));
    623     return handle.Pass();
    624   }
    625 
    626   virtual PrerenderContents* CreatePrerenderContents(
    627       PrerenderManager* prerender_manager,
    628       Profile* profile,
    629       const GURL& url,
    630       const content::Referrer& referrer,
    631       Origin origin,
    632       uint8 experiment_id) OVERRIDE {
    633     ExpectedContents expected;
    634     if (!expected_contents_queue_.empty()) {
    635       expected = expected_contents_queue_.front();
    636       expected_contents_queue_.pop_front();
    637     }
    638     VLOG(1) << "Creating prerender contents for " << url.path() <<
    639                " with expected final status " << expected.final_status;
    640     VLOG(1) << expected_contents_queue_.size() << " left in the queue.";
    641     TestPrerenderContents* contents =
    642         new TestPrerenderContents(prerender_manager,
    643                                   profile, url, referrer, origin,
    644                                   expected.final_status);
    645     if (expected.handle)
    646       expected.handle->OnPrerenderCreated(contents);
    647     return contents;
    648   }
    649 
    650  private:
    651   struct ExpectedContents {
    652     ExpectedContents() : final_status(FINAL_STATUS_MAX) { }
    653     ExpectedContents(FinalStatus final_status,
    654                      const base::WeakPtr<TestPrerender>& handle)
    655         : final_status(final_status),
    656           handle(handle) {
    657     }
    658 
    659     FinalStatus final_status;
    660     base::WeakPtr<TestPrerender> handle;
    661   };
    662 
    663   std::deque<ExpectedContents> expected_contents_queue_;
    664 };
    665 
    666 #if defined(FULL_SAFE_BROWSING)
    667 // A SafeBrowsingDatabaseManager implementation that returns a fixed result for
    668 // a given URL.
    669 class FakeSafeBrowsingDatabaseManager :  public SafeBrowsingDatabaseManager {
    670  public:
    671   explicit FakeSafeBrowsingDatabaseManager(SafeBrowsingService* service)
    672       : SafeBrowsingDatabaseManager(service),
    673         threat_type_(SB_THREAT_TYPE_SAFE) { }
    674 
    675   // Called on the IO thread to check if the given url is safe or not.  If we
    676   // can synchronously determine that the url is safe, CheckUrl returns true.
    677   // Otherwise it returns false, and "client" is called asynchronously with the
    678   // result when it is ready.
    679   // Returns true, indicating a SAFE result, unless the URL is the fixed URL
    680   // specified by the user, and the user-specified result is not SAFE
    681   // (in which that result will be communicated back via a call into the
    682   // client, and false will be returned).
    683   // Overrides SafeBrowsingService::CheckBrowseUrl.
    684   virtual bool CheckBrowseUrl(const GURL& gurl, Client* client) OVERRIDE {
    685     if (gurl != url_ || threat_type_ == SB_THREAT_TYPE_SAFE)
    686       return true;
    687 
    688     BrowserThread::PostTask(
    689         BrowserThread::IO, FROM_HERE,
    690         base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone,
    691                    this, gurl, client));
    692     return false;
    693   }
    694 
    695   void SetThreatTypeForUrl(const GURL& url, SBThreatType threat_type) {
    696     url_ = url;
    697     threat_type_ = threat_type;
    698   }
    699 
    700  private:
    701   virtual ~FakeSafeBrowsingDatabaseManager() {}
    702 
    703   void OnCheckBrowseURLDone(const GURL& gurl, Client* client) {
    704     std::vector<SBThreatType> expected_threats;
    705     expected_threats.push_back(SB_THREAT_TYPE_URL_MALWARE);
    706     expected_threats.push_back(SB_THREAT_TYPE_URL_PHISHING);
    707     SafeBrowsingDatabaseManager::SafeBrowsingCheck sb_check(
    708         std::vector<GURL>(1, gurl),
    709         std::vector<SBFullHash>(),
    710         client,
    711         safe_browsing_util::MALWARE,
    712         expected_threats);
    713     sb_check.url_results[0] = threat_type_;
    714     client->OnSafeBrowsingResult(sb_check);
    715   }
    716 
    717   GURL url_;
    718   SBThreatType threat_type_;
    719   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager);
    720 };
    721 
    722 class FakeSafeBrowsingService : public SafeBrowsingService {
    723  public:
    724   FakeSafeBrowsingService() { }
    725 
    726   // Returned pointer has the same lifespan as the database_manager_ refcounted
    727   // object.
    728   FakeSafeBrowsingDatabaseManager* fake_database_manager() {
    729     return fake_database_manager_;
    730   }
    731 
    732  protected:
    733   virtual ~FakeSafeBrowsingService() { }
    734 
    735   virtual SafeBrowsingDatabaseManager* CreateDatabaseManager() OVERRIDE {
    736     fake_database_manager_ = new FakeSafeBrowsingDatabaseManager(this);
    737     return fake_database_manager_;
    738   }
    739 
    740  private:
    741   FakeSafeBrowsingDatabaseManager* fake_database_manager_;
    742 
    743   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
    744 };
    745 
    746 // Factory that creates FakeSafeBrowsingService instances.
    747 class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
    748  public:
    749   TestSafeBrowsingServiceFactory() :
    750       most_recent_service_(NULL) { }
    751   virtual ~TestSafeBrowsingServiceFactory() { }
    752 
    753   virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE {
    754     most_recent_service_ =  new FakeSafeBrowsingService();
    755     return most_recent_service_;
    756   }
    757 
    758   FakeSafeBrowsingService* most_recent_service() const {
    759     return most_recent_service_;
    760   }
    761 
    762  private:
    763   FakeSafeBrowsingService* most_recent_service_;
    764 };
    765 #endif
    766 
    767 class FakeDevToolsClient : public content::DevToolsAgentHostClient {
    768  public:
    769   FakeDevToolsClient() {}
    770   virtual ~FakeDevToolsClient() {}
    771   virtual void DispatchProtocolMessage(
    772       DevToolsAgentHost* agent_host, const std::string& message) OVERRIDE {}
    773   virtual void AgentHostClosed(
    774       DevToolsAgentHost* agent_host, bool replaced) OVERRIDE {}
    775 };
    776 
    777 class RestorePrerenderMode {
    778  public:
    779   RestorePrerenderMode() : prev_mode_(PrerenderManager::GetMode()) {
    780   }
    781 
    782   ~RestorePrerenderMode() { PrerenderManager::SetMode(prev_mode_); }
    783  private:
    784   PrerenderManager::PrerenderManagerMode prev_mode_;
    785 };
    786 
    787 // URLRequestJob (and associated handler) which hangs.
    788 class HangingURLRequestJob : public net::URLRequestJob {
    789  public:
    790   HangingURLRequestJob(net::URLRequest* request,
    791                           net::NetworkDelegate* network_delegate)
    792       : net::URLRequestJob(request, network_delegate) {
    793   }
    794 
    795   virtual void Start() OVERRIDE {}
    796 
    797  private:
    798   virtual ~HangingURLRequestJob() {}
    799 };
    800 
    801 class HangingFirstRequestInterceptor : public net::URLRequestInterceptor {
    802  public:
    803   HangingFirstRequestInterceptor(const base::FilePath& file,
    804                                  base::Closure callback)
    805       : file_(file),
    806         callback_(callback),
    807         first_run_(true) {
    808   }
    809   virtual ~HangingFirstRequestInterceptor() {}
    810 
    811   virtual net::URLRequestJob* MaybeInterceptRequest(
    812       net::URLRequest* request,
    813       net::NetworkDelegate* network_delegate) const OVERRIDE {
    814     if (first_run_) {
    815       first_run_ = false;
    816       if (!callback_.is_null()) {
    817         BrowserThread::PostTask(
    818             BrowserThread::UI, FROM_HERE, callback_);
    819       }
    820       return new HangingURLRequestJob(request, network_delegate);
    821     }
    822     return new net::URLRequestMockHTTPJob(
    823         request,
    824         network_delegate,
    825         file_,
    826         BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
    827             base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
    828   }
    829 
    830  private:
    831   base::FilePath file_;
    832   base::Closure callback_;
    833   mutable bool first_run_;
    834 };
    835 
    836 // Makes |url| never respond on the first load, and then with the contents of
    837 // |file| afterwards. When the first load has been scheduled, runs |callback| on
    838 // the UI thread.
    839 void CreateHangingFirstRequestInterceptorOnIO(
    840     const GURL& url, const base::FilePath& file, base::Closure callback) {
    841   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    842   scoped_ptr<net::URLRequestInterceptor> never_respond_handler(
    843       new HangingFirstRequestInterceptor(file, callback));
    844   net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
    845       url, never_respond_handler.Pass());
    846 }
    847 
    848 // Wrapper over URLRequestMockHTTPJob that exposes extra callbacks.
    849 class MockHTTPJob : public net::URLRequestMockHTTPJob {
    850  public:
    851   MockHTTPJob(net::URLRequest* request,
    852               net::NetworkDelegate* delegate,
    853               const base::FilePath& file)
    854       : net::URLRequestMockHTTPJob(
    855             request,
    856             delegate,
    857             file,
    858             BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
    859                 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)) {}
    860 
    861   void set_start_callback(const base::Closure& start_callback) {
    862     start_callback_ = start_callback;
    863   }
    864 
    865   virtual void Start() OVERRIDE {
    866     if (!start_callback_.is_null())
    867       start_callback_.Run();
    868     net::URLRequestMockHTTPJob::Start();
    869   }
    870 
    871  private:
    872   virtual ~MockHTTPJob() {}
    873 
    874   base::Closure start_callback_;
    875 };
    876 
    877 // Dummy counter class to live on the UI thread for counting requests.
    878 class RequestCounter : public base::SupportsWeakPtr<RequestCounter> {
    879  public:
    880   RequestCounter() : count_(0), expected_count_(-1) {}
    881   int count() const { return count_; }
    882 
    883   void RequestStarted() {
    884     count_++;
    885     if (loop_ && count_ == expected_count_)
    886       loop_->Quit();
    887   }
    888 
    889   void WaitForCount(int expected_count) {
    890     ASSERT_TRUE(!loop_);
    891     ASSERT_EQ(-1, expected_count_);
    892     if (count_ < expected_count) {
    893       expected_count_ = expected_count;
    894       loop_.reset(new base::RunLoop);
    895       loop_->Run();
    896       expected_count_ = -1;
    897       loop_.reset();
    898     }
    899 
    900     EXPECT_EQ(expected_count, count_);
    901   }
    902  private:
    903   int count_;
    904   int expected_count_;
    905   scoped_ptr<base::RunLoop> loop_;
    906 };
    907 
    908 // Protocol handler which counts the number of requests that start.
    909 class CountingInterceptor : public net::URLRequestInterceptor {
    910  public:
    911   CountingInterceptor(const base::FilePath& file,
    912                       const base::WeakPtr<RequestCounter>& counter)
    913       : file_(file),
    914         counter_(counter),
    915         weak_factory_(this) {
    916   }
    917   virtual ~CountingInterceptor() {}
    918 
    919   virtual net::URLRequestJob* MaybeInterceptRequest(
    920       net::URLRequest* request,
    921       net::NetworkDelegate* network_delegate) const OVERRIDE {
    922     MockHTTPJob* job = new MockHTTPJob(request, network_delegate, file_);
    923     job->set_start_callback(base::Bind(&CountingInterceptor::RequestStarted,
    924                                        weak_factory_.GetWeakPtr()));
    925     return job;
    926   }
    927 
    928   void RequestStarted() {
    929     BrowserThread::PostTask(
    930         BrowserThread::UI, FROM_HERE,
    931         base::Bind(&RequestCounter::RequestStarted, counter_));
    932   }
    933 
    934  private:
    935   base::FilePath file_;
    936   base::WeakPtr<RequestCounter> counter_;
    937   mutable base::WeakPtrFactory<CountingInterceptor> weak_factory_;
    938 };
    939 
    940 // Makes |url| respond to requests with the contents of |file|, counting the
    941 // number that start in |counter|.
    942 void CreateCountingInterceptorOnIO(
    943     const GURL& url,
    944     const base::FilePath& file,
    945     const base::WeakPtr<RequestCounter>& counter) {
    946   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    947   scoped_ptr<net::URLRequestInterceptor> request_interceptor(
    948       new CountingInterceptor(file, counter));
    949   net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
    950       url, request_interceptor.Pass());
    951 }
    952 
    953 // Makes |url| respond to requests with the contents of |file|.
    954 void CreateMockInterceptorOnIO(const GURL& url, const base::FilePath& file) {
    955   CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    956   net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
    957       url,
    958       net::URLRequestMockHTTPJob::CreateInterceptorForSingleFile(
    959           file, BrowserThread::GetBlockingPool()));
    960 }
    961 
    962 // A ContentBrowserClient that cancels all prerenderers on OpenURL.
    963 class TestContentBrowserClient : public chrome::ChromeContentBrowserClient {
    964  public:
    965   TestContentBrowserClient() {}
    966   virtual ~TestContentBrowserClient() {}
    967 
    968   // chrome::ChromeContentBrowserClient implementation.
    969   virtual bool ShouldAllowOpenURL(content::SiteInstance* site_instance,
    970                                   const GURL& url) OVERRIDE {
    971     PrerenderManagerFactory::GetForProfile(
    972         Profile::FromBrowserContext(site_instance->GetBrowserContext()))
    973         ->CancelAllPrerenders();
    974     return chrome::ChromeContentBrowserClient::ShouldAllowOpenURL(site_instance,
    975                                                                   url);
    976   }
    977 
    978  private:
    979   DISALLOW_COPY_AND_ASSIGN(TestContentBrowserClient);
    980 };
    981 
    982 // A ContentBrowserClient that forces cross-process navigations.
    983 class SwapProcessesContentBrowserClient
    984     : public chrome::ChromeContentBrowserClient {
    985  public:
    986   SwapProcessesContentBrowserClient() {}
    987   virtual ~SwapProcessesContentBrowserClient() {}
    988 
    989   // chrome::ChromeContentBrowserClient implementation.
    990   virtual bool ShouldSwapProcessesForRedirect(
    991       content::ResourceContext* resource_context,
    992       const GURL& current_url,
    993       const GURL& new_url) OVERRIDE {
    994     return true;
    995   }
    996 
    997  private:
    998   DISALLOW_COPY_AND_ASSIGN(SwapProcessesContentBrowserClient);
    999 };
   1000 
   1001 // An ExternalProtocolHandler that blocks everything and asserts it never is
   1002 // called.
   1003 class NeverRunsExternalProtocolHandlerDelegate
   1004     : public ExternalProtocolHandler::Delegate {
   1005  public:
   1006   // ExternalProtocolHandler::Delegate implementation.
   1007   virtual ShellIntegration::DefaultProtocolClientWorker* CreateShellWorker(
   1008       ShellIntegration::DefaultWebClientObserver* observer,
   1009       const std::string& protocol) OVERRIDE {
   1010     NOTREACHED();
   1011     // This will crash, but it shouldn't get this far with BlockState::BLOCK
   1012     // anyway.
   1013     return NULL;
   1014   }
   1015   virtual ExternalProtocolHandler::BlockState GetBlockState(
   1016       const std::string& scheme) OVERRIDE {
   1017     // Block everything and fail the test.
   1018     ADD_FAILURE();
   1019     return ExternalProtocolHandler::BLOCK;
   1020   }
   1021   virtual void BlockRequest() OVERRIDE { }
   1022   virtual void RunExternalProtocolDialog(const GURL& url,
   1023                                          int render_process_host_id,
   1024                                          int routing_id) OVERRIDE {
   1025     NOTREACHED();
   1026   }
   1027   virtual void LaunchUrlWithoutSecurityCheck(const GURL& url) OVERRIDE {
   1028     NOTREACHED();
   1029   }
   1030   virtual void FinishedProcessingCheck() OVERRIDE {
   1031     NOTREACHED();
   1032   }
   1033 };
   1034 
   1035 base::FilePath GetTestPath(const std::string& file_name) {
   1036   return ui_test_utils::GetTestFilePath(
   1037       base::FilePath(FILE_PATH_LITERAL("prerender")),
   1038       base::FilePath().AppendASCII(file_name));
   1039 }
   1040 
   1041 }  // namespace
   1042 
   1043 // Many of these tests are flaky. See http://crbug.com/249179
   1044 class PrerenderBrowserTest : virtual public InProcessBrowserTest {
   1045  public:
   1046   PrerenderBrowserTest()
   1047       : autostart_test_server_(true),
   1048         prerender_contents_factory_(NULL),
   1049 #if defined(FULL_SAFE_BROWSING)
   1050         safe_browsing_factory_(new TestSafeBrowsingServiceFactory()),
   1051 #endif
   1052         call_javascript_(true),
   1053         check_load_events_(true),
   1054         loader_path_("files/prerender/prerender_loader.html"),
   1055         explicitly_set_browser_(NULL) {}
   1056 
   1057   virtual ~PrerenderBrowserTest() {}
   1058 
   1059   content::SessionStorageNamespace* GetSessionStorageNamespace() const {
   1060     WebContents* web_contents = GetActiveWebContents();
   1061     if (!web_contents)
   1062       return NULL;
   1063     return web_contents->GetController().GetDefaultSessionStorageNamespace();
   1064   }
   1065 
   1066   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
   1067 #if defined(FULL_SAFE_BROWSING)
   1068     SafeBrowsingService::RegisterFactory(safe_browsing_factory_.get());
   1069 #endif
   1070   }
   1071 
   1072   virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
   1073 #if defined(FULL_SAFE_BROWSING)
   1074     SafeBrowsingService::RegisterFactory(NULL);
   1075 #endif
   1076   }
   1077 
   1078   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
   1079     command_line->AppendSwitchASCII(switches::kPrerenderMode,
   1080                                     switches::kPrerenderModeSwitchValueEnabled);
   1081 #if defined(OS_MACOSX)
   1082     // The plugins directory isn't read by default on the Mac, so it needs to be
   1083     // explicitly registered.
   1084     base::FilePath app_dir;
   1085     PathService::Get(chrome::DIR_APP, &app_dir);
   1086     command_line->AppendSwitchPath(
   1087         switches::kExtraPluginDir,
   1088         app_dir.Append(FILE_PATH_LITERAL("plugins")));
   1089 #endif
   1090     command_line->AppendSwitch(switches::kAlwaysAuthorizePlugins);
   1091   }
   1092 
   1093   void SetPreference(NetworkPredictionOptions value) {
   1094     browser()->profile()->GetPrefs()->SetInteger(
   1095         prefs::kNetworkPredictionOptions, value);
   1096   }
   1097 
   1098   void CreateTestFieldTrial(const std::string& name,
   1099                             const std::string& group_name) {
   1100     base::FieldTrial* trial = base::FieldTrialList::CreateFieldTrial(
   1101         name, group_name);
   1102     trial->group();
   1103   }
   1104 
   1105   // Verifies, for the current field trial, whether
   1106   // ShouldDisableLocalPredictorDueToPreferencesAndNetwork produces the desired
   1107   // output.
   1108   void TestShouldDisableLocalPredictorPreferenceNetworkMatrix(
   1109       bool preference_wifi_network_wifi,
   1110       bool preference_wifi_network_4g,
   1111       bool preference_always_network_wifi,
   1112       bool preference_always_network_4g,
   1113       bool preference_never_network_wifi,
   1114       bool preference_never_network_4g) {
   1115     Profile* profile = browser()->profile();
   1116 
   1117     // Set real NetworkChangeNotifier singleton aside.
   1118     scoped_ptr<NetworkChangeNotifier::DisableForTest> disable_for_test(
   1119         new NetworkChangeNotifier::DisableForTest);
   1120 
   1121     // Set preference to WIFI_ONLY: prefetch when not on cellular.
   1122     SetPreference(NetworkPredictionOptions::NETWORK_PREDICTION_WIFI_ONLY);
   1123     {
   1124       scoped_ptr<NetworkChangeNotifier> mock(new MockNetworkChangeNotifierWIFI);
   1125       EXPECT_EQ(
   1126           ShouldDisableLocalPredictorDueToPreferencesAndNetwork(profile),
   1127           preference_wifi_network_wifi);
   1128     }
   1129     {
   1130       scoped_ptr<NetworkChangeNotifier> mock(new MockNetworkChangeNotifier4G);
   1131       EXPECT_EQ(
   1132           ShouldDisableLocalPredictorDueToPreferencesAndNetwork(profile),
   1133           preference_wifi_network_4g);
   1134     }
   1135 
   1136     // Set preference to ALWAYS: always prefetch.
   1137     SetPreference(NetworkPredictionOptions::NETWORK_PREDICTION_ALWAYS);
   1138     {
   1139       scoped_ptr<NetworkChangeNotifier> mock(new MockNetworkChangeNotifierWIFI);
   1140       EXPECT_EQ(
   1141           ShouldDisableLocalPredictorDueToPreferencesAndNetwork(profile),
   1142           preference_always_network_wifi);
   1143     }
   1144     {
   1145       scoped_ptr<NetworkChangeNotifier> mock(new MockNetworkChangeNotifier4G);
   1146       EXPECT_EQ(
   1147           ShouldDisableLocalPredictorDueToPreferencesAndNetwork(profile),
   1148           preference_always_network_4g);
   1149     }
   1150 
   1151     // Set preference to NEVER: never prefetch.
   1152     SetPreference(NetworkPredictionOptions::NETWORK_PREDICTION_NEVER);
   1153     {
   1154       scoped_ptr<NetworkChangeNotifier> mock(new MockNetworkChangeNotifierWIFI);
   1155       EXPECT_EQ(
   1156           ShouldDisableLocalPredictorDueToPreferencesAndNetwork(profile),
   1157           preference_never_network_wifi);
   1158     }
   1159     {
   1160       scoped_ptr<NetworkChangeNotifier> mock(new MockNetworkChangeNotifier4G);
   1161       EXPECT_EQ(
   1162           ShouldDisableLocalPredictorDueToPreferencesAndNetwork(profile),
   1163           preference_never_network_4g);
   1164     }
   1165   }
   1166 
   1167   virtual void SetUpOnMainThread() OVERRIDE {
   1168     current_browser()->profile()->GetPrefs()->SetBoolean(
   1169         prefs::kPromptForDownload, false);
   1170     IncreasePrerenderMemory();
   1171     if (autostart_test_server_)
   1172       ASSERT_TRUE(test_server()->Start());
   1173     ChromeResourceDispatcherHostDelegate::
   1174         SetExternalProtocolHandlerDelegateForTesting(
   1175             &external_protocol_handler_delegate_);
   1176 
   1177     PrerenderManager* prerender_manager = GetPrerenderManager();
   1178     ASSERT_TRUE(prerender_manager);
   1179     prerender_manager->mutable_config().rate_limit_enabled = false;
   1180     ASSERT_TRUE(prerender_contents_factory_ == NULL);
   1181     prerender_contents_factory_ = new TestPrerenderContentsFactory;
   1182     prerender_manager->SetPrerenderContentsFactory(prerender_contents_factory_);
   1183   }
   1184 
   1185   // Convenience function to get the currently active WebContents in
   1186   // current_browser().
   1187   WebContents* GetActiveWebContents() const {
   1188     return current_browser()->tab_strip_model()->GetActiveWebContents();
   1189   }
   1190 
   1191   // Overload for a single expected final status
   1192   scoped_ptr<TestPrerender> PrerenderTestURL(
   1193       const std::string& html_file,
   1194       FinalStatus expected_final_status,
   1195       int expected_number_of_loads) {
   1196     GURL url = test_server()->GetURL(html_file);
   1197     return PrerenderTestURL(url,
   1198                             expected_final_status,
   1199                             expected_number_of_loads);
   1200   }
   1201 
   1202   ScopedVector<TestPrerender> PrerenderTestURL(
   1203       const std::string& html_file,
   1204       const std::vector<FinalStatus>& expected_final_status_queue,
   1205       int expected_number_of_loads) {
   1206     GURL url = test_server()->GetURL(html_file);
   1207     return PrerenderTestURLImpl(url,
   1208                                 expected_final_status_queue,
   1209                                 expected_number_of_loads);
   1210   }
   1211 
   1212   scoped_ptr<TestPrerender> PrerenderTestURL(
   1213       const GURL& url,
   1214       FinalStatus expected_final_status,
   1215       int expected_number_of_loads) {
   1216     std::vector<FinalStatus> expected_final_status_queue(
   1217         1, expected_final_status);
   1218     std::vector<TestPrerender*> prerenders;
   1219     PrerenderTestURLImpl(url,
   1220                          expected_final_status_queue,
   1221                          expected_number_of_loads).release(&prerenders);
   1222     CHECK_EQ(1u, prerenders.size());
   1223     return scoped_ptr<TestPrerender>(prerenders[0]);
   1224   }
   1225 
   1226   // Navigates to a URL, unrelated to prerendering
   1227   void NavigateStraightToURL(const std::string dest_html_file) {
   1228     ui_test_utils::NavigateToURL(current_browser(),
   1229                                  test_server()->GetURL(dest_html_file));
   1230   }
   1231 
   1232   void NavigateToDestURL() const {
   1233     NavigateToDestURLWithDisposition(CURRENT_TAB, true);
   1234   }
   1235 
   1236   // Opens the url in a new tab, with no opener.
   1237   void NavigateToDestURLWithDisposition(
   1238       WindowOpenDisposition disposition,
   1239       bool expect_swap_to_succeed) const {
   1240     NavigateToURLWithParams(
   1241         content::OpenURLParams(dest_url_, Referrer(), disposition,
   1242                                ui::PAGE_TRANSITION_TYPED, false),
   1243         expect_swap_to_succeed);
   1244   }
   1245 
   1246   void NavigateToURL(const std::string& dest_html_file) const {
   1247     NavigateToURLWithDisposition(dest_html_file, CURRENT_TAB, true);
   1248   }
   1249 
   1250   void NavigateToURLWithDisposition(const std::string& dest_html_file,
   1251                                     WindowOpenDisposition disposition,
   1252                                     bool expect_swap_to_succeed) const {
   1253     GURL dest_url = test_server()->GetURL(dest_html_file);
   1254     NavigateToURLWithDisposition(dest_url, disposition, expect_swap_to_succeed);
   1255   }
   1256 
   1257   void NavigateToURLWithDisposition(const GURL& dest_url,
   1258                                     WindowOpenDisposition disposition,
   1259                                     bool expect_swap_to_succeed) const {
   1260     NavigateToURLWithParams(
   1261         content::OpenURLParams(dest_url, Referrer(), disposition,
   1262                                ui::PAGE_TRANSITION_TYPED, false),
   1263         expect_swap_to_succeed);
   1264   }
   1265 
   1266   void NavigateToURLWithParams(const content::OpenURLParams& params,
   1267                                bool expect_swap_to_succeed) const {
   1268     NavigateToURLImpl(params, expect_swap_to_succeed);
   1269   }
   1270 
   1271   void OpenDestURLViaClick() const {
   1272     OpenURLViaClick(dest_url_);
   1273   }
   1274 
   1275   void OpenURLViaClick(const GURL& url) const {
   1276     OpenURLWithJSImpl("Click", url, GURL(), false);
   1277   }
   1278 
   1279   void OpenDestURLViaClickTarget() const {
   1280     OpenURLWithJSImpl("ClickTarget", dest_url_, GURL(), true);
   1281   }
   1282 
   1283   void OpenDestURLViaClickPing(const GURL& ping_url) const {
   1284     OpenURLWithJSImpl("ClickPing", dest_url_, ping_url, false);
   1285   }
   1286 
   1287   void OpenDestURLViaClickNewWindow() const {
   1288     OpenURLWithJSImpl("ShiftClick", dest_url_, GURL(), true);
   1289   }
   1290 
   1291   void OpenDestURLViaClickNewForegroundTab() const {
   1292 #if defined(OS_MACOSX)
   1293     OpenURLWithJSImpl("MetaShiftClick", dest_url_, GURL(), true);
   1294 #else
   1295     OpenURLWithJSImpl("CtrlShiftClick", dest_url_, GURL(), true);
   1296 #endif
   1297   }
   1298 
   1299   void OpenDestURLViaClickNewBackgroundTab() const {
   1300 #if defined(OS_MACOSX)
   1301     OpenURLWithJSImpl("MetaClick", dest_url_, GURL(), true);
   1302 #else
   1303     OpenURLWithJSImpl("CtrlClick", dest_url_, GURL(), true);
   1304 #endif
   1305   }
   1306 
   1307   void OpenDestURLViaWindowOpen() const {
   1308     OpenURLViaWindowOpen(dest_url_);
   1309   }
   1310 
   1311   void OpenURLViaWindowOpen(const GURL& url) const {
   1312     OpenURLWithJSImpl("WindowOpen", url, GURL(), true);
   1313   }
   1314 
   1315   void RemoveLinkElement(int i) const {
   1316     GetActiveWebContents()->GetMainFrame()->ExecuteJavaScript(
   1317         base::ASCIIToUTF16(base::StringPrintf("RemoveLinkElement(%d)", i)));
   1318   }
   1319 
   1320   void ClickToNextPageAfterPrerender() {
   1321     TestNavigationObserver nav_observer(GetActiveWebContents());
   1322     RenderFrameHost* render_frame_host = GetActiveWebContents()->GetMainFrame();
   1323     render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("ClickOpenLink()"));
   1324     nav_observer.Wait();
   1325   }
   1326 
   1327   void NavigateToNextPageAfterPrerender() const {
   1328     ui_test_utils::NavigateToURL(
   1329         current_browser(),
   1330         test_server()->GetURL("files/prerender/prerender_page.html"));
   1331   }
   1332 
   1333   // Called after the prerendered page has been navigated to and then away from.
   1334   // Navigates back through the history to the prerendered page.
   1335   void GoBackToPrerender() {
   1336     TestNavigationObserver back_nav_observer(GetActiveWebContents());
   1337     chrome::GoBack(current_browser(), CURRENT_TAB);
   1338     back_nav_observer.Wait();
   1339     bool original_prerender_page = false;
   1340     ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
   1341         GetActiveWebContents(),
   1342         "window.domAutomationController.send(IsOriginalPrerenderPage())",
   1343         &original_prerender_page));
   1344     EXPECT_TRUE(original_prerender_page);
   1345   }
   1346 
   1347   // Goes back to the page that was active before the prerender was swapped
   1348   // in. This must be called when the prerendered page is the current page
   1349   // in the active tab.
   1350   void GoBackToPageBeforePrerender() {
   1351     WebContents* tab = GetActiveWebContents();
   1352     ASSERT_TRUE(tab);
   1353     EXPECT_FALSE(tab->IsLoading());
   1354     TestNavigationObserver back_nav_observer(tab);
   1355     chrome::GoBack(current_browser(), CURRENT_TAB);
   1356     back_nav_observer.Wait();
   1357     bool js_result;
   1358     ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
   1359         tab,
   1360         "window.domAutomationController.send(DidBackToOriginalPagePass())",
   1361         &js_result));
   1362     EXPECT_TRUE(js_result);
   1363   }
   1364 
   1365   bool UrlIsInPrerenderManager(const std::string& html_file) const {
   1366     return UrlIsInPrerenderManager(test_server()->GetURL(html_file));
   1367   }
   1368 
   1369   bool UrlIsInPrerenderManager(const GURL& url) const {
   1370     return GetPrerenderManager()->FindPrerenderData(
   1371         url, GetSessionStorageNamespace()) != NULL;
   1372   }
   1373 
   1374   void UseHttpsSrcServer() {
   1375     if (https_src_server_)
   1376       return;
   1377     https_src_server_.reset(
   1378         new net::SpawnedTestServer(
   1379             net::SpawnedTestServer::TYPE_HTTPS,
   1380             net::SpawnedTestServer::kLocalhost,
   1381             base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
   1382     CHECK(https_src_server_->Start());
   1383   }
   1384 
   1385   void DisableJavascriptCalls() {
   1386     call_javascript_ = false;
   1387   }
   1388 
   1389   void DisableLoadEventCheck() {
   1390     check_load_events_ = false;
   1391   }
   1392 
   1393   TaskManagerModel* GetModel() const {
   1394     return TaskManager::GetInstance()->model();
   1395   }
   1396 
   1397   PrerenderManager* GetPrerenderManager() const {
   1398     PrerenderManager* prerender_manager =
   1399         PrerenderManagerFactory::GetForProfile(current_browser()->profile());
   1400     return prerender_manager;
   1401   }
   1402 
   1403   const PrerenderLinkManager* GetPrerenderLinkManager() const {
   1404     PrerenderLinkManager* prerender_link_manager =
   1405         PrerenderLinkManagerFactory::GetForProfile(
   1406             current_browser()->profile());
   1407     return prerender_link_manager;
   1408   }
   1409 
   1410   int GetPrerenderEventCount(int index, const std::string& type) const {
   1411     int event_count;
   1412     std::string expression = base::StringPrintf(
   1413         "window.domAutomationController.send("
   1414         "    GetPrerenderEventCount(%d, '%s'))", index, type.c_str());
   1415 
   1416     CHECK(content::ExecuteScriptAndExtractInt(
   1417         GetActiveWebContents(), expression, &event_count));
   1418     return event_count;
   1419   }
   1420 
   1421   bool DidReceivePrerenderStartEventForLinkNumber(int index) const {
   1422     return GetPrerenderEventCount(index, "webkitprerenderstart") > 0;
   1423   }
   1424 
   1425   int GetPrerenderLoadEventCountForLinkNumber(int index) const {
   1426     return GetPrerenderEventCount(index, "webkitprerenderload");
   1427   }
   1428 
   1429   int GetPrerenderDomContentLoadedEventCountForLinkNumber(int index) const {
   1430     return GetPrerenderEventCount(index, "webkitprerenderdomcontentloaded");
   1431   }
   1432 
   1433   bool DidReceivePrerenderStopEventForLinkNumber(int index) const {
   1434     return GetPrerenderEventCount(index, "webkitprerenderstop") > 0;
   1435   }
   1436 
   1437   void WaitForPrerenderEventCount(int index,
   1438                                   const std::string& type,
   1439                                   int count) const {
   1440     int dummy;
   1441     std::string expression = base::StringPrintf(
   1442         "WaitForPrerenderEventCount(%d, '%s', %d,"
   1443         "    window.domAutomationController.send.bind("
   1444         "        window.domAutomationController, 0))",
   1445         index, type.c_str(), count);
   1446 
   1447     CHECK(content::ExecuteScriptAndExtractInt(
   1448         GetActiveWebContents(), expression, &dummy));
   1449     CHECK_EQ(0, dummy);
   1450   }
   1451 
   1452   bool HadPrerenderEventErrors() const {
   1453     bool had_prerender_event_errors;
   1454     CHECK(content::ExecuteScriptAndExtractBool(
   1455         GetActiveWebContents(),
   1456         "window.domAutomationController.send(Boolean("
   1457         "    hadPrerenderEventErrors))",
   1458         &had_prerender_event_errors));
   1459     return had_prerender_event_errors;
   1460   }
   1461 
   1462   // Asserting on this can result in flaky tests.  PrerenderHandles are
   1463   // removed from the PrerenderLinkManager when the prerender is canceled from
   1464   // the browser, when the prerenders are cancelled from the renderer process,
   1465   // or the channel for the renderer process is closed on the IO thread.  In the
   1466   // last case, the code must be careful to wait for the channel to close, as it
   1467   // is done asynchronously after swapping out the old process.  See
   1468   // ChannelDestructionWatcher.
   1469   bool IsEmptyPrerenderLinkManager() const {
   1470     return GetPrerenderLinkManager()->IsEmpty();
   1471   }
   1472 
   1473   size_t GetLinkPrerenderCount() const {
   1474     return GetPrerenderLinkManager()->prerenders_.size();
   1475   }
   1476 
   1477   size_t GetRunningLinkPrerenderCount() const {
   1478     return GetPrerenderLinkManager()->CountRunningPrerenders();
   1479   }
   1480 
   1481   // Returns length of |prerender_manager_|'s history, or -1 on failure.
   1482   int GetHistoryLength() const {
   1483     scoped_ptr<base::DictionaryValue> prerender_dict(
   1484         static_cast<base::DictionaryValue*>(
   1485             GetPrerenderManager()->GetAsValue()));
   1486     if (!prerender_dict.get())
   1487       return -1;
   1488     base::ListValue* history_list;
   1489     if (!prerender_dict->GetList("history", &history_list))
   1490       return -1;
   1491     return static_cast<int>(history_list->GetSize());
   1492   }
   1493 
   1494 #if defined(FULL_SAFE_BROWSING)
   1495   FakeSafeBrowsingDatabaseManager* GetFakeSafeBrowsingDatabaseManager() {
   1496     return safe_browsing_factory_->most_recent_service()->
   1497         fake_database_manager();
   1498   }
   1499 #endif
   1500 
   1501   TestPrerenderContents* GetPrerenderContentsFor(const GURL& url) const {
   1502     PrerenderManager::PrerenderData* prerender_data =
   1503         GetPrerenderManager()->FindPrerenderData(url, NULL);
   1504     return static_cast<TestPrerenderContents*>(
   1505         prerender_data ? prerender_data->contents() : NULL);
   1506   }
   1507 
   1508   void SetLoaderHostOverride(const std::string& host) {
   1509     loader_host_override_ = host;
   1510     host_resolver()->AddRule(host, "127.0.0.1");
   1511   }
   1512 
   1513   void set_loader_path(const std::string& path) {
   1514     loader_path_ = path;
   1515   }
   1516 
   1517   void set_loader_query(const std::string& query) {
   1518     loader_query_ = query;
   1519   }
   1520 
   1521   GURL GetCrossDomainTestUrl(const std::string& path) {
   1522     static const std::string secondary_domain = "www.foo.com";
   1523     host_resolver()->AddRule(secondary_domain, "127.0.0.1");
   1524     std::string url_str(base::StringPrintf(
   1525         "http://%s:%d/%s",
   1526         secondary_domain.c_str(),
   1527         test_server()->host_port_pair().port(),
   1528         path.c_str()));
   1529     return GURL(url_str);
   1530   }
   1531 
   1532   void set_browser(Browser* browser) {
   1533     explicitly_set_browser_ = browser;
   1534   }
   1535 
   1536   Browser* current_browser() const {
   1537     return explicitly_set_browser_ ? explicitly_set_browser_ : browser();
   1538   }
   1539 
   1540   const GURL& dest_url() const {
   1541     return dest_url_;
   1542   }
   1543 
   1544   void IncreasePrerenderMemory() {
   1545     // Increase the memory allowed in a prerendered page above normal settings.
   1546     // Debug build bots occasionally run against the default limit, and tests
   1547     // were failing because the prerender was canceled due to memory exhaustion.
   1548     // http://crbug.com/93076
   1549     GetPrerenderManager()->mutable_config().max_bytes = 1000 * 1024 * 1024;
   1550   }
   1551 
   1552   bool DidPrerenderPass(WebContents* web_contents) const {
   1553     bool prerender_test_result = false;
   1554     if (!content::ExecuteScriptAndExtractBool(
   1555             web_contents,
   1556             "window.domAutomationController.send(DidPrerenderPass())",
   1557             &prerender_test_result))
   1558       return false;
   1559     return prerender_test_result;
   1560   }
   1561 
   1562   bool DidDisplayPass(WebContents* web_contents) const {
   1563     bool display_test_result = false;
   1564     if (!content::ExecuteScriptAndExtractBool(
   1565             web_contents,
   1566             "window.domAutomationController.send(DidDisplayPass())",
   1567             &display_test_result))
   1568       return false;
   1569     return display_test_result;
   1570   }
   1571 
   1572   scoped_ptr<TestPrerender> ExpectPrerender(FinalStatus expected_final_status) {
   1573     return prerender_contents_factory_->ExpectPrerenderContents(
   1574         expected_final_status);
   1575   }
   1576 
   1577   void AddPrerender(const GURL& url, int index) {
   1578     std::string javascript = base::StringPrintf(
   1579         "AddPrerender('%s', %d)", url.spec().c_str(), index);
   1580     RenderFrameHost* render_frame_host = GetActiveWebContents()->GetMainFrame();
   1581     render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16(javascript));
   1582   }
   1583 
   1584   // Returns a string for pattern-matching TaskManager tab entries.
   1585   base::string16 MatchTaskManagerTab(const char* page_title) {
   1586     return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX,
   1587                                       base::ASCIIToUTF16(page_title));
   1588   }
   1589 
   1590   // Returns a string for pattern-matching TaskManager prerender entries.
   1591   base::string16 MatchTaskManagerPrerender(const char* page_title) {
   1592     return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRERENDER_PREFIX,
   1593                                       base::ASCIIToUTF16(page_title));
   1594   }
   1595 
   1596   void RunJSReturningString(const char* js, std::string* result) {
   1597     ASSERT_TRUE(
   1598         content::ExecuteScriptAndExtractString(
   1599             GetActiveWebContents(),
   1600             base::StringPrintf("window.domAutomationController.send(%s)",
   1601                                js).c_str(),
   1602             result));
   1603   }
   1604 
   1605   void RunJS(const char* js) {
   1606     ASSERT_TRUE(content::ExecuteScript(
   1607         GetActiveWebContents(),
   1608         base::StringPrintf("window.domAutomationController.send(%s)",
   1609                            js).c_str()));
   1610   }
   1611 
   1612   const base::HistogramTester& histogram_tester() { return histogram_tester_; }
   1613 
   1614  protected:
   1615   bool autostart_test_server_;
   1616 
   1617  private:
   1618   // TODO(davidben): Remove this altogether so the tests don't globally assume
   1619   // only one prerender.
   1620   TestPrerenderContents* GetPrerenderContents() const {
   1621     return GetPrerenderContentsFor(dest_url_);
   1622   }
   1623 
   1624   ScopedVector<TestPrerender> PrerenderTestURLImpl(
   1625       const GURL& prerender_url,
   1626       const std::vector<FinalStatus>& expected_final_status_queue,
   1627       int expected_number_of_loads) {
   1628     dest_url_ = prerender_url;
   1629 
   1630     std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   1631     replacement_text.push_back(
   1632         make_pair("REPLACE_WITH_PRERENDER_URL", prerender_url.spec()));
   1633     std::string replacement_path;
   1634     CHECK(net::SpawnedTestServer::GetFilePathWithReplacements(
   1635         loader_path_,
   1636         replacement_text,
   1637         &replacement_path));
   1638 
   1639     const net::SpawnedTestServer* src_server = test_server();
   1640     if (https_src_server_)
   1641       src_server = https_src_server_.get();
   1642     GURL loader_url = src_server->GetURL(
   1643         replacement_path + "&" + loader_query_);
   1644 
   1645     GURL::Replacements loader_replacements;
   1646     if (!loader_host_override_.empty())
   1647       loader_replacements.SetHostStr(loader_host_override_);
   1648     loader_url = loader_url.ReplaceComponents(loader_replacements);
   1649 
   1650     VLOG(1) << "Running test with queue length " <<
   1651                expected_final_status_queue.size();
   1652     CHECK(!expected_final_status_queue.empty());
   1653     ScopedVector<TestPrerender> prerenders;
   1654     for (size_t i = 0; i < expected_final_status_queue.size(); i++) {
   1655       prerenders.push_back(
   1656           prerender_contents_factory_->ExpectPrerenderContents(
   1657               expected_final_status_queue[i]).release());
   1658     }
   1659 
   1660     FinalStatus expected_final_status = expected_final_status_queue.front();
   1661 
   1662     // Navigate to the loader URL and then wait for the first prerender to be
   1663     // created.
   1664     ui_test_utils::NavigateToURL(current_browser(), loader_url);
   1665     prerenders[0]->WaitForCreate();
   1666     prerenders[0]->WaitForLoads(expected_number_of_loads);
   1667 
   1668     if (ShouldAbortPrerenderBeforeSwap(expected_final_status)) {
   1669       // The prerender will abort on its own. Assert it does so correctly.
   1670       prerenders[0]->WaitForStop();
   1671       EXPECT_FALSE(prerenders[0]->contents());
   1672       EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(0));
   1673     } else {
   1674       // Otherwise, check that it prerendered correctly.
   1675       TestPrerenderContents* prerender_contents = prerenders[0]->contents();
   1676 
   1677       CHECK_NE(static_cast<PrerenderContents*>(NULL), prerender_contents);
   1678       EXPECT_EQ(FINAL_STATUS_MAX, prerender_contents->final_status());
   1679       EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
   1680 
   1681       if (call_javascript_) {
   1682         // Check if page behaves as expected while in prerendered state.
   1683         EXPECT_TRUE(DidPrerenderPass(prerender_contents->prerender_contents()));
   1684       }
   1685     }
   1686 
   1687     // Test that the referring page received the right start and load events.
   1688     EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
   1689     if (check_load_events_) {
   1690       EXPECT_EQ(expected_number_of_loads, prerenders[0]->number_of_loads());
   1691       EXPECT_EQ(expected_number_of_loads,
   1692                 GetPrerenderLoadEventCountForLinkNumber(0));
   1693     }
   1694     EXPECT_FALSE(HadPrerenderEventErrors());
   1695 
   1696     return prerenders.Pass();
   1697   }
   1698 
   1699   void NavigateToURLImpl(const content::OpenURLParams& params,
   1700                          bool expect_swap_to_succeed) const {
   1701     ASSERT_NE(static_cast<PrerenderManager*>(NULL), GetPrerenderManager());
   1702     // Make sure in navigating we have a URL to use in the PrerenderManager.
   1703     ASSERT_NE(static_cast<PrerenderContents*>(NULL), GetPrerenderContents());
   1704 
   1705     WebContents* web_contents = GetPrerenderContents()->prerender_contents();
   1706 
   1707     // Navigate and wait for either the load to finish normally or for a swap to
   1708     // occur.
   1709     // TODO(davidben): The only handles CURRENT_TAB navigations, which is the
   1710     // only case tested or prerendered right now.
   1711     CHECK_EQ(CURRENT_TAB, params.disposition);
   1712     NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(),
   1713                                            GetActiveWebContents());
   1714     WebContents* target_web_contents = current_browser()->OpenURL(params);
   1715     swap_observer.Wait();
   1716 
   1717     if (web_contents && expect_swap_to_succeed) {
   1718       EXPECT_EQ(web_contents, target_web_contents);
   1719       if (call_javascript_)
   1720         EXPECT_TRUE(DidDisplayPass(web_contents));
   1721     }
   1722   }
   1723 
   1724   // Opens the prerendered page using javascript functions in the loader
   1725   // page. |javascript_function_name| should be a 0 argument function which is
   1726   // invoked. |new_web_contents| is true if the navigation is expected to
   1727   // happen in a new WebContents via OpenURL.
   1728   void OpenURLWithJSImpl(const std::string& javascript_function_name,
   1729                          const GURL& url,
   1730                          const GURL& ping_url,
   1731                          bool new_web_contents) const {
   1732     WebContents* web_contents = GetActiveWebContents();
   1733     RenderFrameHost* render_frame_host = web_contents->GetMainFrame();
   1734     // Extra arguments in JS are ignored.
   1735     std::string javascript = base::StringPrintf(
   1736         "%s('%s', '%s')", javascript_function_name.c_str(),
   1737         url.spec().c_str(), ping_url.spec().c_str());
   1738 
   1739     if (new_web_contents) {
   1740       NewTabNavigationOrSwapObserver observer;
   1741       render_frame_host->
   1742           ExecuteJavaScriptForTests(base::ASCIIToUTF16(javascript));
   1743       observer.Wait();
   1744     } else {
   1745       NavigationOrSwapObserver observer(current_browser()->tab_strip_model(),
   1746                                         web_contents);
   1747       render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16(javascript));
   1748       observer.Wait();
   1749     }
   1750   }
   1751 
   1752   TestPrerenderContentsFactory* prerender_contents_factory_;
   1753 #if defined(FULL_SAFE_BROWSING)
   1754   scoped_ptr<TestSafeBrowsingServiceFactory> safe_browsing_factory_;
   1755 #endif
   1756   NeverRunsExternalProtocolHandlerDelegate external_protocol_handler_delegate_;
   1757   GURL dest_url_;
   1758   scoped_ptr<net::SpawnedTestServer> https_src_server_;
   1759   bool call_javascript_;
   1760   bool check_load_events_;
   1761   std::string loader_host_override_;
   1762   std::string loader_path_;
   1763   std::string loader_query_;
   1764   Browser* explicitly_set_browser_;
   1765   base::HistogramTester histogram_tester_;
   1766   scoped_ptr<base::FieldTrialList> field_trial_list_;
   1767 };
   1768 
   1769 // Checks that a page is correctly prerendered in the case of a
   1770 // <link rel=prerender> tag and then loaded into a tab in response to a
   1771 // navigation.
   1772 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPage) {
   1773   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   1774   EXPECT_EQ(1, GetPrerenderDomContentLoadedEventCountForLinkNumber(0));
   1775   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
   1776   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
   1777   histogram_tester().ExpectTotalCount(
   1778       "Prerender.none_PerceivedPLTMatchedComplete", 0);
   1779   histogram_tester().ExpectTotalCount(
   1780       "Prerender.websame_PrerenderNotSwappedInPLT", 1);
   1781 
   1782   ChannelDestructionWatcher channel_close_watcher;
   1783   channel_close_watcher.WatchChannel(
   1784       GetActiveWebContents()->GetRenderProcessHost());
   1785   NavigateToDestURL();
   1786   channel_close_watcher.WaitForChannelClose();
   1787 
   1788   histogram_tester().ExpectTotalCount("Prerender.websame_PerceivedPLT", 1);
   1789   histogram_tester().ExpectTotalCount("Prerender.websame_PerceivedPLTMatched",
   1790                                       1);
   1791   histogram_tester().ExpectTotalCount(
   1792       "Prerender.websame_PerceivedPLTMatchedComplete", 1);
   1793 
   1794   ASSERT_TRUE(IsEmptyPrerenderLinkManager());
   1795 }
   1796 
   1797 // Checks that cross-domain prerenders emit the correct histograms.
   1798 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageCrossDomain) {
   1799   PrerenderTestURL(GetCrossDomainTestUrl("files/prerender/prerender_page.html"),
   1800                    FINAL_STATUS_USED, 1);
   1801   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
   1802   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
   1803   histogram_tester().ExpectTotalCount(
   1804       "Prerender.none_PerceivedPLTMatchedComplete", 0);
   1805   histogram_tester().ExpectTotalCount(
   1806       "Prerender.webcross_PrerenderNotSwappedInPLT", 1);
   1807 
   1808   NavigateToDestURL();
   1809   histogram_tester().ExpectTotalCount("Prerender.webcross_PerceivedPLT", 1);
   1810   histogram_tester().ExpectTotalCount("Prerender.webcross_PerceivedPLTMatched",
   1811                                       1);
   1812   histogram_tester().ExpectTotalCount(
   1813       "Prerender.webcross_PerceivedPLTMatchedComplete", 1);
   1814 }
   1815 
   1816 // Checks that pending prerenders launch and receive proper event treatment.
   1817 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPagePending) {
   1818   scoped_ptr<TestPrerender> prerender =
   1819       PrerenderTestURL("files/prerender/prerender_page_pending.html",
   1820                        FINAL_STATUS_USED, 1);
   1821 
   1822   // Navigate to the prerender.
   1823   scoped_ptr<TestPrerender> prerender2 = ExpectPrerender(FINAL_STATUS_USED);
   1824   NavigateToDestURL();
   1825   // Abort early if the original prerender didn't swap, so as not to hang.
   1826   ASSERT_FALSE(prerender->contents());
   1827 
   1828   // Wait for the new prerender to be ready.
   1829   prerender2->WaitForStart();
   1830   prerender2->WaitForLoads(1);
   1831 
   1832   const GURL prerender_page_url =
   1833       test_server()->GetURL("files/prerender/prerender_page.html");
   1834   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
   1835   EXPECT_NE(static_cast<TestPrerenderContents*>(NULL),
   1836             GetPrerenderContentsFor(prerender_page_url));
   1837 
   1838   // Now navigate to our target page.
   1839   NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(),
   1840                                          GetActiveWebContents());
   1841   ui_test_utils::NavigateToURLWithDisposition(
   1842       current_browser(), prerender_page_url, CURRENT_TAB,
   1843       ui_test_utils::BROWSER_TEST_NONE);
   1844   swap_observer.Wait();
   1845 
   1846   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
   1847 }
   1848 
   1849 // Checks that pending prerenders which are canceled before they are launched
   1850 // never get started.
   1851 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageRemovesPending) {
   1852   PrerenderTestURL("files/prerender/prerender_page_removes_pending.html",
   1853                    FINAL_STATUS_USED, 1);
   1854 
   1855   ChannelDestructionWatcher channel_close_watcher;
   1856   channel_close_watcher.WatchChannel(
   1857       GetActiveWebContents()->GetRenderProcessHost());
   1858   NavigateToDestURL();
   1859   channel_close_watcher.WaitForChannelClose();
   1860 
   1861   EXPECT_FALSE(DidReceivePrerenderStartEventForLinkNumber(1));
   1862   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
   1863   EXPECT_FALSE(HadPrerenderEventErrors());
   1864   // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
   1865   // calls did a thread/process hop to the renderer which insured pending
   1866   // renderer events have arrived.
   1867   ASSERT_TRUE(IsEmptyPrerenderLinkManager());
   1868 }
   1869 
   1870 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageRemovingLink) {
   1871   scoped_ptr<TestPrerender> prerender =
   1872       PrerenderTestURL("files/prerender/prerender_page.html",
   1873                        FINAL_STATUS_CANCELLED, 1);
   1874 
   1875   // No ChannelDestructionWatcher is needed here, since prerenders in the
   1876   // PrerenderLinkManager should be deleted by removing the links, rather than
   1877   // shutting down the renderer process.
   1878   RemoveLinkElement(0);
   1879   prerender->WaitForStop();
   1880 
   1881   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
   1882   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
   1883   EXPECT_FALSE(HadPrerenderEventErrors());
   1884   // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
   1885   // calls did a thread/process hop to the renderer which insured pending
   1886   // renderer events have arrived.
   1887   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
   1888 }
   1889 
   1890 IN_PROC_BROWSER_TEST_F(
   1891     PrerenderBrowserTest, PrerenderPageRemovingLinkWithTwoLinks) {
   1892   GetPrerenderManager()->mutable_config().max_link_concurrency = 2;
   1893   GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2;
   1894 
   1895   set_loader_query("links_to_insert=2");
   1896   scoped_ptr<TestPrerender> prerender =
   1897       PrerenderTestURL("files/prerender/prerender_page.html",
   1898                        FINAL_STATUS_CANCELLED, 1);
   1899   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
   1900   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
   1901   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
   1902   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
   1903 
   1904   RemoveLinkElement(0);
   1905   RemoveLinkElement(1);
   1906   prerender->WaitForStop();
   1907 
   1908   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
   1909   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
   1910   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
   1911   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
   1912   EXPECT_FALSE(HadPrerenderEventErrors());
   1913   // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
   1914   // calls did a thread/process hop to the renderer which insured pending
   1915   // renderer events have arrived.
   1916   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
   1917 }
   1918 
   1919 IN_PROC_BROWSER_TEST_F(
   1920     PrerenderBrowserTest, PrerenderPageRemovingLinkWithTwoLinksOneLate) {
   1921   GetPrerenderManager()->mutable_config().max_link_concurrency = 2;
   1922   GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2;
   1923 
   1924   GURL url = test_server()->GetURL("files/prerender/prerender_page.html");
   1925   scoped_ptr<TestPrerender> prerender =
   1926       PrerenderTestURL(url, FINAL_STATUS_CANCELLED, 1);
   1927 
   1928   // Add a second prerender for the same link. It reuses the prerender, so only
   1929   // the start event fires here.
   1930   AddPrerender(url, 1);
   1931   WaitForPrerenderEventCount(1, "webkitprerenderstart", 1);
   1932   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
   1933   EXPECT_EQ(0, GetPrerenderLoadEventCountForLinkNumber(1));
   1934   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
   1935 
   1936   RemoveLinkElement(0);
   1937   RemoveLinkElement(1);
   1938   prerender->WaitForStop();
   1939 
   1940   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
   1941   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
   1942   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
   1943   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
   1944   EXPECT_FALSE(HadPrerenderEventErrors());
   1945   // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
   1946   // calls did a thread/process hop to the renderer which insured pending
   1947   // renderer events have arrived.
   1948   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
   1949 }
   1950 
   1951 IN_PROC_BROWSER_TEST_F(
   1952     PrerenderBrowserTest,
   1953     PrerenderPageRemovingLinkWithTwoLinksRemovingOne) {
   1954   GetPrerenderManager()->mutable_config().max_link_concurrency = 2;
   1955   GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2;
   1956   set_loader_query("links_to_insert=2");
   1957   PrerenderTestURL("files/prerender/prerender_page.html",
   1958                    FINAL_STATUS_USED, 1);
   1959   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
   1960   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
   1961   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
   1962   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
   1963 
   1964   RemoveLinkElement(0);
   1965   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
   1966   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
   1967   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
   1968   EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
   1969   EXPECT_FALSE(HadPrerenderEventErrors());
   1970   // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
   1971   // calls did a thread/process hop to the renderer which insured pending
   1972   // renderer events have arrived.
   1973   EXPECT_FALSE(IsEmptyPrerenderLinkManager());
   1974 
   1975   ChannelDestructionWatcher channel_close_watcher;
   1976   channel_close_watcher.WatchChannel(
   1977       GetActiveWebContents()->GetRenderProcessHost());
   1978   NavigateToDestURL();
   1979   channel_close_watcher.WaitForChannelClose();
   1980 
   1981   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
   1982 }
   1983 
   1984 // Checks that the visibility API works.
   1985 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderVisibility) {
   1986   PrerenderTestURL("files/prerender/prerender_visibility.html",
   1987                    FINAL_STATUS_USED,
   1988                    1);
   1989   NavigateToDestURL();
   1990 }
   1991 
   1992 // Checks that the prerendering of a page is canceled correctly if we try to
   1993 // swap it in before it commits.
   1994 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNoCommitNoSwap) {
   1995   // Navigate to a page that triggers a prerender for a URL that never commits.
   1996   const GURL kNoCommitUrl("http://never-respond.example.com");
   1997   base::FilePath file(GetTestPath("prerender_page.html"));
   1998 
   1999   base::RunLoop prerender_start_loop;
   2000   BrowserThread::PostTask(
   2001       BrowserThread::IO, FROM_HERE,
   2002       base::Bind(&CreateHangingFirstRequestInterceptorOnIO, kNoCommitUrl, file,
   2003                  prerender_start_loop.QuitClosure()));
   2004   DisableJavascriptCalls();
   2005   PrerenderTestURL(kNoCommitUrl,
   2006                    FINAL_STATUS_NAVIGATION_UNCOMMITTED,
   2007                    0);
   2008   // Wait for the hanging request to be scheduled.
   2009   prerender_start_loop.Run();
   2010 
   2011   // Navigate to the URL, but assume the contents won't be swapped in.
   2012   NavigateToDestURLWithDisposition(CURRENT_TAB, false);
   2013 }
   2014 
   2015 // Checks that client redirects don't add alias URLs until after they commit.
   2016 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNoCommitNoSwap2) {
   2017   // Navigate to a page that then navigates to a URL that never commits.
   2018   const GURL kNoCommitUrl("http://never-respond.example.com");
   2019   base::FilePath file(GetTestPath("prerender_page.html"));
   2020 
   2021   base::RunLoop prerender_start_loop;
   2022   BrowserThread::PostTask(
   2023       BrowserThread::IO, FROM_HERE,
   2024       base::Bind(&CreateHangingFirstRequestInterceptorOnIO, kNoCommitUrl, file,
   2025                  prerender_start_loop.QuitClosure()));
   2026   DisableJavascriptCalls();
   2027   PrerenderTestURL(CreateClientRedirect(kNoCommitUrl.spec()),
   2028                    FINAL_STATUS_APP_TERMINATING, 1);
   2029   // Wait for the hanging request to be scheduled.
   2030   prerender_start_loop.Run();
   2031 
   2032   // Navigating to the second URL should not swap.
   2033   NavigateToURLWithDisposition(kNoCommitUrl, CURRENT_TAB, false);
   2034 }
   2035 
   2036 // Checks that the prerendering of a page is canceled correctly when a
   2037 // Javascript alert is called.
   2038 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertBeforeOnload) {
   2039   PrerenderTestURL("files/prerender/prerender_alert_before_onload.html",
   2040                    FINAL_STATUS_JAVASCRIPT_ALERT,
   2041                    0);
   2042 }
   2043 
   2044 // Checks that the prerendering of a page is canceled correctly when a
   2045 // Javascript alert is called.
   2046 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertAfterOnload) {
   2047   PrerenderTestURL("files/prerender/prerender_alert_after_onload.html",
   2048                    FINAL_STATUS_JAVASCRIPT_ALERT,
   2049                    1);
   2050 }
   2051 
   2052 // Checks that plugins are not loaded while a page is being preloaded, but
   2053 // are loaded when the page is displayed.
   2054 #if defined(USE_AURA) && !defined(OS_WIN)
   2055 // http://crbug.com/103496
   2056 #define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin
   2057 #elif defined(OS_MACOSX)
   2058 // http://crbug.com/100514
   2059 #define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin
   2060 #elif defined(OS_WIN) && defined(ARCH_CPU_X86_64)
   2061 // TODO(jschuh): Failing plugin tests. crbug.com/244653
   2062 #define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin
   2063 #elif defined(OS_LINUX)
   2064 // http://crbug.com/306715
   2065 #define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin
   2066 #else
   2067 #define MAYBE_PrerenderDelayLoadPlugin PrerenderDelayLoadPlugin
   2068 #endif
   2069 // http://crbug.com/306715
   2070 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MAYBE_PrerenderDelayLoadPlugin) {
   2071   PrerenderTestURL("files/prerender/plugin_delay_load.html",
   2072                    FINAL_STATUS_USED,
   2073                    1);
   2074   NavigateToDestURL();
   2075 }
   2076 
   2077 // Checks that plugins are not loaded on prerendering pages when click-to-play
   2078 // is enabled.
   2079 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickToPlay) {
   2080   // Enable click-to-play.
   2081   HostContentSettingsMap* content_settings_map =
   2082       current_browser()->profile()->GetHostContentSettingsMap();
   2083   content_settings_map->SetDefaultContentSetting(
   2084       CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_ASK);
   2085 
   2086   PrerenderTestURL("files/prerender/prerender_plugin_click_to_play.html",
   2087                    FINAL_STATUS_USED,
   2088                    1);
   2089   NavigateToDestURL();
   2090 }
   2091 
   2092 // Checks that we don't load a NaCl plugin when NaCl is disabled.
   2093 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNaClPluginDisabled) {
   2094   PrerenderTestURL("files/prerender/prerender_plugin_nacl_disabled.html",
   2095                    FINAL_STATUS_USED,
   2096                    1);
   2097   NavigateToDestURL();
   2098 
   2099 
   2100   // Run this check again.  When we try to load aa ppapi plugin, the
   2101   // "loadstart" event is asynchronously posted to a message loop.
   2102   // It's possible that earlier call could have been run before the
   2103   // the "loadstart" event was posted.
   2104   // TODO(mmenke):  While this should reliably fail on regressions, the
   2105   //                reliability depends on the specifics of ppapi plugin
   2106   //                loading.  It would be great if we could avoid that.
   2107   EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
   2108 }
   2109 
   2110 // Checks that plugins in an iframe are not loaded while a page is
   2111 // being preloaded, but are loaded when the page is displayed.
   2112 #if defined(USE_AURA) && !defined(OS_WIN)
   2113 // http://crbug.com/103496
   2114 #define MAYBE_PrerenderIframeDelayLoadPlugin \
   2115         DISABLED_PrerenderIframeDelayLoadPlugin
   2116 #elif defined(OS_MACOSX)
   2117 // http://crbug.com/100514
   2118 #define MAYBE_PrerenderIframeDelayLoadPlugin \
   2119         DISABLED_PrerenderIframeDelayLoadPlugin
   2120 #elif defined(OS_WIN) && defined(ARCH_CPU_X86_64)
   2121 // TODO(jschuh): Failing plugin tests. crbug.com/244653
   2122 #define MAYBE_PrerenderIframeDelayLoadPlugin \
   2123         DISABLED_PrerenderIframeDelayLoadPlugin
   2124 #else
   2125 #define MAYBE_PrerenderIframeDelayLoadPlugin PrerenderIframeDelayLoadPlugin
   2126 #endif
   2127 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2128                        MAYBE_PrerenderIframeDelayLoadPlugin) {
   2129   PrerenderTestURL("files/prerender/prerender_iframe_plugin_delay_load.html",
   2130                    FINAL_STATUS_USED,
   2131                    1);
   2132   NavigateToDestURL();
   2133 }
   2134 
   2135 // Renders a page that contains a prerender link to a page that contains an
   2136 // iframe with a source that requires http authentication. This should not
   2137 // prerender successfully.
   2138 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHttpAuthentication) {
   2139   PrerenderTestURL("files/prerender/prerender_http_auth_container.html",
   2140                    FINAL_STATUS_AUTH_NEEDED,
   2141                    0);
   2142 }
   2143 
   2144 // Checks that client-issued redirects work with prerendering.
   2145 // This version navigates to the page which issues the redirection, rather
   2146 // than the final destination page.
   2147 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2148                        PrerenderClientRedirectNavigateToFirst) {
   2149   PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"),
   2150                    FINAL_STATUS_USED,
   2151                    2);
   2152   NavigateToDestURL();
   2153 }
   2154 
   2155 // Checks that client-issued redirects work with prerendering.
   2156 // This version navigates to the final destination page, rather than the
   2157 // page which does the redirection.
   2158 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2159                        PrerenderClientRedirectNavigateToSecond) {
   2160   PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"),
   2161                    FINAL_STATUS_USED,
   2162                    2);
   2163   NavigateToURL("files/prerender/prerender_page.html");
   2164 }
   2165 
   2166 // Checks that redirects with location.replace do not cancel a prerender and
   2167 // and swap when navigating to the first page.
   2168 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2169                        PrerenderLocationReplaceNavigateToFirst) {
   2170   PrerenderTestURL("files/prerender/prerender_location_replace.html",
   2171                    FINAL_STATUS_USED,
   2172                    2);
   2173   NavigateToDestURL();
   2174 }
   2175 
   2176 // Checks that redirects with location.replace do not cancel a prerender and
   2177 // and swap when navigating to the second.
   2178 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2179                        PrerenderLocationReplaceNavigateToSecond) {
   2180   PrerenderTestURL("files/prerender/prerender_location_replace.html",
   2181                    FINAL_STATUS_USED,
   2182                    2);
   2183   NavigateToURL("files/prerender/prerender_page.html");
   2184 }
   2185 
   2186 // Checks that we get the right PPLT histograms for client redirect prerenders
   2187 // and navigations when the referring page is Google.
   2188 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2189                        PrerenderLocationReplaceGWSHistograms) {
   2190   DisableJavascriptCalls();
   2191 
   2192   // The loader page should look like Google.
   2193   const std::string kGoogleDotCom("www.google.com");
   2194   SetLoaderHostOverride(kGoogleDotCom);
   2195   set_loader_path("files/prerender/prerender_loader_with_replace_state.html");
   2196 
   2197   GURL dest_url = GetCrossDomainTestUrl(
   2198       "files/prerender/prerender_deferred_image.html");
   2199 
   2200   GURL prerender_url = test_server()->GetURL(
   2201       "files/prerender/prerender_location_replace.html?" +
   2202       net::EscapeQueryParamValue(dest_url.spec(), false) +
   2203       "#prerender");
   2204   GURL::Replacements replacements;
   2205   replacements.SetHostStr(kGoogleDotCom);
   2206   prerender_url = prerender_url.ReplaceComponents(replacements);
   2207 
   2208   // The prerender will not completely load until after the swap, so wait for a
   2209   // title change before calling DidPrerenderPass.
   2210   scoped_ptr<TestPrerender> prerender =
   2211       PrerenderTestURL(prerender_url, FINAL_STATUS_USED, 1);
   2212   WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle);
   2213   EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents()));
   2214   EXPECT_EQ(1, prerender->number_of_loads());
   2215 
   2216   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
   2217   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
   2218   histogram_tester().ExpectTotalCount(
   2219       "Prerender.none_PerceivedPLTMatchedComplete", 0);
   2220   // Although there is a client redirect, it is dropped from histograms because
   2221   // it is a Google URL. The target page itself does not load until after the
   2222   // swap.
   2223   histogram_tester().ExpectTotalCount("Prerender.gws_PrerenderNotSwappedInPLT",
   2224                                       0);
   2225 
   2226   GURL navigate_url = test_server()->GetURL(
   2227       "files/prerender/prerender_location_replace.html?" +
   2228       net::EscapeQueryParamValue(dest_url.spec(), false) +
   2229       "#navigate");
   2230   navigate_url = navigate_url.ReplaceComponents(replacements);
   2231 
   2232   NavigationOrSwapObserver swap_observer(
   2233       current_browser()->tab_strip_model(),
   2234       GetActiveWebContents(), 2);
   2235   current_browser()->OpenURL(OpenURLParams(
   2236       navigate_url, Referrer(), CURRENT_TAB,
   2237       ui::PAGE_TRANSITION_TYPED, false));
   2238   swap_observer.Wait();
   2239 
   2240   EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
   2241 
   2242   histogram_tester().ExpectTotalCount("Prerender.gws_PrerenderNotSwappedInPLT",
   2243                                       0);
   2244   histogram_tester().ExpectTotalCount("Prerender.gws_PerceivedPLT", 1);
   2245   histogram_tester().ExpectTotalCount("Prerender.gws_PerceivedPLTMatched", 1);
   2246   histogram_tester().ExpectTotalCount(
   2247       "Prerender.gws_PerceivedPLTMatchedComplete", 1);
   2248 
   2249   // The client redirect does /not/ count as a miss because it's a Google URL.
   2250   histogram_tester().ExpectTotalCount("Prerender.PerceivedPLTFirstAfterMiss",
   2251                                       0);
   2252 }
   2253 
   2254 // Checks that client-issued redirects work with prerendering.
   2255 // This version navigates to the final destination page, rather than the
   2256 // page which does the redirection via a mouse click.
   2257 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2258                        PrerenderClientRedirectNavigateToSecondViaClick) {
   2259   GURL prerender_url = test_server()->GetURL(
   2260       CreateClientRedirect("files/prerender/prerender_page.html"));
   2261   GURL destination_url = test_server()->GetURL(
   2262       "files/prerender/prerender_page.html");
   2263   PrerenderTestURL(prerender_url, FINAL_STATUS_USED, 2);
   2264   OpenURLViaClick(destination_url);
   2265 }
   2266 
   2267 // Checks that a page served over HTTPS is correctly prerendered.
   2268 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHttps) {
   2269   net::SpawnedTestServer https_server(
   2270       net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
   2271       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
   2272   ASSERT_TRUE(https_server.Start());
   2273   GURL https_url = https_server.GetURL("files/prerender/prerender_page.html");
   2274   PrerenderTestURL(https_url,
   2275                    FINAL_STATUS_USED,
   2276                    1);
   2277   NavigateToDestURL();
   2278 }
   2279 
   2280 // Checks that client-issued redirects within an iframe in a prerendered
   2281 // page will not count as an "alias" for the prerendered page.
   2282 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2283                        PrerenderClientRedirectInIframe) {
   2284   std::string redirect_path = CreateClientRedirect(
   2285       "/files/prerender/prerender_embedded_content.html");
   2286   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   2287   replacement_text.push_back(
   2288       std::make_pair("REPLACE_WITH_URL", "/" + redirect_path));
   2289   std::string replacement_path;
   2290   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   2291       "files/prerender/prerender_with_iframe.html",
   2292       replacement_text,
   2293       &replacement_path));
   2294   PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 2);
   2295   EXPECT_FALSE(UrlIsInPrerenderManager(
   2296       "files/prerender/prerender_embedded_content.html"));
   2297   NavigateToDestURL();
   2298 }
   2299 
   2300 // Checks that server-issued redirects work with prerendering.
   2301 // This version navigates to the page which issues the redirection, rather
   2302 // than the final destination page.
   2303 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2304                        PrerenderServerRedirectNavigateToFirst) {
   2305   PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"),
   2306                    FINAL_STATUS_USED,
   2307                    1);
   2308   NavigateToDestURL();
   2309 }
   2310 
   2311 // Checks that server-issued redirects work with prerendering.
   2312 // This version navigates to the final destination page, rather than the
   2313 // page which does the redirection.
   2314 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2315                        PrerenderServerRedirectNavigateToSecond) {
   2316   PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"),
   2317                    FINAL_STATUS_USED,
   2318                    1);
   2319   NavigateToURL("files/prerender/prerender_page.html");
   2320 }
   2321 
   2322 // Checks that server-issued redirects work with prerendering.
   2323 // This version navigates to the final destination page, rather than the
   2324 // page which does the redirection via a mouse click.
   2325 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2326                        PrerenderServerRedirectNavigateToSecondViaClick) {
   2327   GURL prerender_url = test_server()->GetURL(
   2328       CreateServerRedirect("files/prerender/prerender_page.html"));
   2329   GURL destination_url = test_server()->GetURL(
   2330       "files/prerender/prerender_page.html");
   2331   PrerenderTestURL(prerender_url, FINAL_STATUS_USED, 1);
   2332   OpenURLViaClick(destination_url);
   2333 }
   2334 
   2335 // Checks that server-issued redirects within an iframe in a prerendered
   2336 // page will not count as an "alias" for the prerendered page.
   2337 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderServerRedirectInIframe) {
   2338   std::string redirect_path = CreateServerRedirect(
   2339       "/files/prerender/prerender_embedded_content.html");
   2340   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   2341   replacement_text.push_back(
   2342       std::make_pair("REPLACE_WITH_URL", "/" + redirect_path));
   2343   std::string replacement_path;
   2344   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   2345       "files/prerender/prerender_with_iframe.html",
   2346       replacement_text,
   2347       &replacement_path));
   2348   PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
   2349   EXPECT_FALSE(UrlIsInPrerenderManager(
   2350       "files/prerender/prerender_embedded_content.html"));
   2351   NavigateToDestURL();
   2352 }
   2353 
   2354 // Prerenders a page that contains an automatic download triggered through an
   2355 // iframe. This should not prerender successfully.
   2356 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDownloadIframe) {
   2357   PrerenderTestURL("files/prerender/prerender_download_iframe.html",
   2358                    FINAL_STATUS_DOWNLOAD,
   2359                    0);
   2360 }
   2361 
   2362 // Prerenders a page that contains an automatic download triggered through
   2363 // Javascript changing the window.location. This should not prerender
   2364 // successfully
   2365 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDownloadLocation) {
   2366   PrerenderTestURL(CreateClientRedirect("files/download-test1.lib"),
   2367                    FINAL_STATUS_DOWNLOAD,
   2368                    1);
   2369 }
   2370 
   2371 // Prerenders a page that contains an automatic download triggered through a
   2372 // client-issued redirect. This should not prerender successfully.
   2373 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDownloadClientRedirect) {
   2374   PrerenderTestURL("files/prerender/prerender_download_refresh.html",
   2375                    FINAL_STATUS_DOWNLOAD,
   2376                    1);
   2377 }
   2378 
   2379 // Checks that the referrer is set when prerendering.
   2380 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReferrer) {
   2381   PrerenderTestURL("files/prerender/prerender_referrer.html",
   2382                    FINAL_STATUS_USED,
   2383                    1);
   2384   NavigateToDestURL();
   2385 }
   2386 
   2387 // Checks that the referrer is not set when prerendering and the source page is
   2388 // HTTPS.
   2389 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2390                        PrerenderNoSSLReferrer) {
   2391   UseHttpsSrcServer();
   2392   PrerenderTestURL("files/prerender/prerender_no_referrer.html",
   2393                    FINAL_STATUS_USED,
   2394                    1);
   2395   NavigateToDestURL();
   2396 }
   2397 
   2398 // Checks that the referrer is set when prerendering is cancelled.
   2399 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelReferrer) {
   2400   scoped_ptr<TestContentBrowserClient> test_content_browser_client(
   2401       new TestContentBrowserClient);
   2402   content::ContentBrowserClient* original_browser_client =
   2403       content::SetBrowserClientForTesting(test_content_browser_client.get());
   2404 
   2405   PrerenderTestURL("files/prerender/prerender_referrer.html",
   2406                    FINAL_STATUS_CANCELLED,
   2407                    1);
   2408   OpenDestURLViaClick();
   2409 
   2410   EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
   2411 
   2412   content::SetBrowserClientForTesting(original_browser_client);
   2413 }
   2414 
   2415 // Checks that popups on a prerendered page cause cancellation.
   2416 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPopup) {
   2417   PrerenderTestURL("files/prerender/prerender_popup.html",
   2418                    FINAL_STATUS_CREATE_NEW_WINDOW,
   2419                    0);
   2420 }
   2421 
   2422 // Checks that registering a protocol handler causes cancellation.
   2423 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderRegisterProtocolHandler) {
   2424   PrerenderTestURL("files/prerender/prerender_register_protocol_handler.html",
   2425                    FINAL_STATUS_REGISTER_PROTOCOL_HANDLER,
   2426                    0);
   2427 }
   2428 
   2429 // Checks that renderers using excessive memory will be terminated.
   2430 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderExcessiveMemory) {
   2431   ASSERT_TRUE(GetPrerenderManager());
   2432   GetPrerenderManager()->mutable_config().max_bytes = 30 * 1024 * 1024;
   2433   // The excessive memory kill may happen before or after the load event as it
   2434   // happens asynchronously with IPC calls. Even if the test does not start
   2435   // allocating until after load, the browser process might notice before the
   2436   // message gets through. This happens on XP debug bots because they're so
   2437   // slow. Instead, don't bother checking the load event count.
   2438   DisableLoadEventCheck();
   2439   PrerenderTestURL("files/prerender/prerender_excessive_memory.html",
   2440                    FINAL_STATUS_MEMORY_LIMIT_EXCEEDED, 0);
   2441 }
   2442 
   2443 // Checks shutdown code while a prerender is active.
   2444 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderQuickQuit) {
   2445   DisableJavascriptCalls();
   2446   DisableLoadEventCheck();
   2447   PrerenderTestURL("files/prerender/prerender_page.html",
   2448                    FINAL_STATUS_APP_TERMINATING,
   2449                    0);
   2450 }
   2451 
   2452 // Checks that we don't prerender in an infinite loop.
   2453 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderInfiniteLoop) {
   2454   const char* const kHtmlFileA = "files/prerender/prerender_infinite_a.html";
   2455   const char* const kHtmlFileB = "files/prerender/prerender_infinite_b.html";
   2456 
   2457   std::vector<FinalStatus> expected_final_status_queue;
   2458   expected_final_status_queue.push_back(FINAL_STATUS_USED);
   2459   expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING);
   2460 
   2461   ScopedVector<TestPrerender> prerenders =
   2462       PrerenderTestURL(kHtmlFileA, expected_final_status_queue, 1);
   2463   ASSERT_TRUE(prerenders[0]->contents());
   2464   // Assert that the pending prerender is in there already. This relies on the
   2465   // fact that the renderer sends out the AddLinkRelPrerender IPC before sending
   2466   // the page load one.
   2467   EXPECT_EQ(2U, GetLinkPrerenderCount());
   2468   EXPECT_EQ(1U, GetRunningLinkPrerenderCount());
   2469 
   2470   // Next url should be in pending list but not an active entry.
   2471   EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB));
   2472 
   2473   NavigateToDestURL();
   2474 
   2475   // Make sure the PrerenderContents for the next url is now in the manager and
   2476   // not pending. This relies on pending prerenders being resolved in the same
   2477   // event loop iteration as OnPrerenderStop.
   2478   EXPECT_TRUE(UrlIsInPrerenderManager(kHtmlFileB));
   2479   EXPECT_EQ(1U, GetLinkPrerenderCount());
   2480   EXPECT_EQ(1U, GetRunningLinkPrerenderCount());
   2481 }
   2482 
   2483 // Checks that we don't prerender in an infinite loop and multiple links are
   2484 // handled correctly.
   2485 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2486                        PrerenderInfiniteLoopMultiple) {
   2487   const char* const kHtmlFileA =
   2488       "files/prerender/prerender_infinite_a_multiple.html";
   2489   const char* const kHtmlFileB =
   2490       "files/prerender/prerender_infinite_b_multiple.html";
   2491   const char* const kHtmlFileC =
   2492       "files/prerender/prerender_infinite_c_multiple.html";
   2493 
   2494   // This test is conceptually simplest if concurrency is at two, since we
   2495   // don't have to worry about which of kHtmlFileB or kHtmlFileC gets evicted.
   2496   GetPrerenderManager()->mutable_config().max_link_concurrency = 2;
   2497   GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2;
   2498 
   2499   std::vector<FinalStatus> expected_final_status_queue;
   2500   expected_final_status_queue.push_back(FINAL_STATUS_USED);
   2501   expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING);
   2502   expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING);
   2503 
   2504   ScopedVector<TestPrerender> prerenders =
   2505       PrerenderTestURL(kHtmlFileA, expected_final_status_queue, 1);
   2506   ASSERT_TRUE(prerenders[0]->contents());
   2507 
   2508   // Next url should be in pending list but not an active entry. This relies on
   2509   // the fact that the renderer sends out the AddLinkRelPrerender IPC before
   2510   // sending the page load one.
   2511   EXPECT_EQ(3U, GetLinkPrerenderCount());
   2512   EXPECT_EQ(1U, GetRunningLinkPrerenderCount());
   2513   EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB));
   2514   EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileC));
   2515 
   2516   NavigateToDestURL();
   2517 
   2518   // Make sure the PrerenderContents for the next urls are now in the manager
   2519   // and not pending. One and only one of the URLs (the last seen) should be the
   2520   // active entry. This relies on pending prerenders being resolved in the same
   2521   // event loop iteration as OnPrerenderStop.
   2522   bool url_b_is_active_prerender = UrlIsInPrerenderManager(kHtmlFileB);
   2523   bool url_c_is_active_prerender = UrlIsInPrerenderManager(kHtmlFileC);
   2524   EXPECT_TRUE(url_b_is_active_prerender && url_c_is_active_prerender);
   2525   EXPECT_EQ(2U, GetLinkPrerenderCount());
   2526   EXPECT_EQ(2U, GetRunningLinkPrerenderCount());
   2527 }
   2528 
   2529 // Checks that pending prerenders are aborted (and never launched) when launched
   2530 // by a prerender that itself gets aborted.
   2531 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAbortPendingOnCancel) {
   2532   const char* const kHtmlFileA = "files/prerender/prerender_infinite_a.html";
   2533   const char* const kHtmlFileB = "files/prerender/prerender_infinite_b.html";
   2534 
   2535   scoped_ptr<TestPrerender> prerender =
   2536       PrerenderTestURL(kHtmlFileA, FINAL_STATUS_CANCELLED, 1);
   2537   ASSERT_TRUE(prerender->contents());
   2538   // Assert that the pending prerender is in there already. This relies on the
   2539   // fact that the renderer sends out the AddLinkRelPrerender IPC before sending
   2540   // the page load one.
   2541   EXPECT_EQ(2U, GetLinkPrerenderCount());
   2542   EXPECT_EQ(1U, GetRunningLinkPrerenderCount());
   2543 
   2544   // Next url should be in pending list but not an active entry.
   2545   EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB));
   2546 
   2547   // Cancel the prerender.
   2548   GetPrerenderManager()->CancelAllPrerenders();
   2549   prerender->WaitForStop();
   2550 
   2551   // All prerenders are now gone.
   2552   EXPECT_TRUE(IsEmptyPrerenderLinkManager());
   2553 }
   2554 
   2555 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, OpenTaskManagerBeforePrerender) {
   2556   const base::string16 any_prerender = MatchTaskManagerPrerender("*");
   2557   const base::string16 any_tab = MatchTaskManagerTab("*");
   2558   const base::string16 original = MatchTaskManagerTab("Preloader");
   2559   const base::string16 prerender = MatchTaskManagerPrerender("Prerender Page");
   2560   const base::string16 final = MatchTaskManagerTab("Prerender Page");
   2561 
   2562   // Show the task manager. This populates the model.
   2563   chrome::OpenTaskManager(current_browser());
   2564   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab));
   2565   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, any_prerender));
   2566 
   2567   // Prerender a page in addition to the original tab.
   2568   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   2569 
   2570   // A TaskManager entry should appear like "Prerender: Prerender Page"
   2571   // alongside the original tab entry. There should be just these two entries.
   2572   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, prerender));
   2573   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, original));
   2574   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, final));
   2575   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_prerender));
   2576   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab));
   2577 
   2578   // Swap in the prerendered content.
   2579   NavigateToDestURL();
   2580 
   2581   // The "Prerender: " TaskManager entry should disappear, being replaced by a
   2582   // "Tab: Prerender Page" entry, and nothing else.
   2583   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, prerender));
   2584   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, original));
   2585   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, final));
   2586   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab));
   2587   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, any_prerender));
   2588 }
   2589 
   2590 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, OpenTaskManagerAfterPrerender) {
   2591   const base::string16 any_prerender = MatchTaskManagerPrerender("*");
   2592   const base::string16 any_tab = MatchTaskManagerTab("*");
   2593   const base::string16 original = MatchTaskManagerTab("Preloader");
   2594   const base::string16 prerender = MatchTaskManagerPrerender("Prerender Page");
   2595   const base::string16 final = MatchTaskManagerTab("Prerender Page");
   2596 
   2597   // Start with two resources.
   2598   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   2599 
   2600   // Show the task manager. This populates the model. Importantly, we're doing
   2601   // this after the prerender WebContents already exists - the task manager
   2602   // needs to find it, it can't just listen for creation.
   2603   chrome::OpenTaskManager(current_browser());
   2604 
   2605   // A TaskManager entry should appear like "Prerender: Prerender Page"
   2606   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, prerender));
   2607   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, original));
   2608   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, final));
   2609   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_prerender));
   2610   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab));
   2611 
   2612   // Swap in the tab.
   2613   NavigateToDestURL();
   2614 
   2615   // The "Prerender: Prerender Page" TaskManager row should disappear, being
   2616   // replaced by "Tab: Prerender Page"
   2617   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, prerender));
   2618   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, original));
   2619   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, final));
   2620   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab));
   2621   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, any_prerender));
   2622 }
   2623 
   2624 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, OpenTaskManagerAfterSwapIn) {
   2625   const base::string16 any_prerender = MatchTaskManagerPrerender("*");
   2626   const base::string16 any_tab = MatchTaskManagerTab("*");
   2627   const base::string16 final = MatchTaskManagerTab("Prerender Page");
   2628 
   2629   // Prerender, and swap it in.
   2630   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   2631   NavigateToDestURL();
   2632 
   2633   // Show the task manager. This populates the model. Importantly, we're doing
   2634   // this after the prerender has been swapped in.
   2635   chrome::OpenTaskManager(current_browser());
   2636 
   2637   // We should not see a prerender resource in the task manager, just a normal
   2638   // page.
   2639   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, final));
   2640   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab));
   2641   ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, any_prerender));
   2642 }
   2643 
   2644 // Checks that audio loads are deferred on prerendering.
   2645 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5Audio) {
   2646   PrerenderTestURL("files/prerender/prerender_html5_audio.html",
   2647                    FINAL_STATUS_USED,
   2648                    1);
   2649   NavigateToDestURL();
   2650   WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
   2651 }
   2652 
   2653 // Checks that audio loads are deferred on prerendering and played back when
   2654 // the prerender is swapped in if autoplay is set.
   2655 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5AudioAutoplay) {
   2656   PrerenderTestURL("files/prerender/prerender_html5_audio_autoplay.html",
   2657                    FINAL_STATUS_USED,
   2658                    1);
   2659   NavigateToDestURL();
   2660   WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
   2661 }
   2662 
   2663 // Checks that audio loads are deferred on prerendering and played back when
   2664 // the prerender is swapped in if js starts playing.
   2665 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5AudioJsplay) {
   2666   PrerenderTestURL("files/prerender/prerender_html5_audio_jsplay.html",
   2667                    FINAL_STATUS_USED,
   2668                    1);
   2669   NavigateToDestURL();
   2670   WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
   2671 }
   2672 
   2673 // Checks that video loads are deferred on prerendering.
   2674 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5Video) {
   2675   PrerenderTestURL("files/prerender/prerender_html5_video.html",
   2676                    FINAL_STATUS_USED,
   2677                    1);
   2678   NavigateToDestURL();
   2679   WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
   2680 }
   2681 
   2682 // Checks that video tags inserted by javascript are deferred and played
   2683 // correctly on swap in.
   2684 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5VideoJs) {
   2685   PrerenderTestURL("files/prerender/prerender_html5_video_script.html",
   2686                    FINAL_STATUS_USED,
   2687                    1);
   2688   NavigateToDestURL();
   2689   WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
   2690 }
   2691 
   2692 // Checks for correct network events by using a busy sleep the javascript.
   2693 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5VideoNetwork) {
   2694   DisableJavascriptCalls();
   2695   scoped_ptr<TestPrerender> prerender =
   2696       PrerenderTestURL("files/prerender/prerender_html5_video_network.html",
   2697                        FINAL_STATUS_USED,
   2698                        1);
   2699   WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle);
   2700   EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents()));
   2701   NavigateToDestURL();
   2702   WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
   2703 }
   2704 
   2705 // Checks that scripts can retrieve the correct window size while prerendering.
   2706 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderWindowSize) {
   2707   PrerenderTestURL("files/prerender/prerender_size.html",
   2708                    FINAL_STATUS_USED,
   2709                    1);
   2710   NavigateToDestURL();
   2711 }
   2712 
   2713 // TODO(jam): http://crbug.com/350550
   2714 #if !(defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER))
   2715 
   2716 // Checks that prerenderers will terminate when the RenderView crashes.
   2717 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderRendererCrash) {
   2718   scoped_ptr<TestPrerender> prerender =
   2719       PrerenderTestURL("files/prerender/prerender_page.html",
   2720                        FINAL_STATUS_RENDERER_CRASHED,
   2721                        1);
   2722 
   2723   // Navigate to about:crash and then wait for the renderer to crash.
   2724   ASSERT_TRUE(prerender->contents());
   2725   ASSERT_TRUE(prerender->contents()->prerender_contents());
   2726   prerender->contents()->prerender_contents()->GetController().
   2727       LoadURL(
   2728           GURL(content::kChromeUICrashURL),
   2729           content::Referrer(),
   2730           ui::PAGE_TRANSITION_TYPED,
   2731           std::string());
   2732   prerender->WaitForStop();
   2733 }
   2734 #endif
   2735 
   2736 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2737                        PrerenderPageWithFragment) {
   2738   PrerenderTestURL("files/prerender/prerender_page.html#fragment",
   2739                    FINAL_STATUS_USED,
   2740                    1);
   2741 
   2742   ChannelDestructionWatcher channel_close_watcher;
   2743   channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
   2744       GetActiveWebContents()->GetRenderProcessHost());
   2745   NavigateToDestURL();
   2746   channel_close_watcher.WaitForChannelClose();
   2747 
   2748   ASSERT_TRUE(IsEmptyPrerenderLinkManager());
   2749 }
   2750 
   2751 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2752                        PrerenderPageWithRedirectedFragment) {
   2753   PrerenderTestURL(
   2754       CreateClientRedirect("files/prerender/prerender_page.html#fragment"),
   2755       FINAL_STATUS_USED,
   2756       2);
   2757 
   2758   ChannelDestructionWatcher channel_close_watcher;
   2759   channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
   2760       GetActiveWebContents()->GetRenderProcessHost());
   2761   NavigateToDestURL();
   2762   channel_close_watcher.WaitForChannelClose();
   2763 
   2764   ASSERT_TRUE(IsEmptyPrerenderLinkManager());
   2765 }
   2766 
   2767 // Checks that we do not use a prerendered page when navigating from
   2768 // the main page to a fragment.
   2769 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2770                        PrerenderPageNavigateFragment) {
   2771   PrerenderTestURL("files/prerender/no_prerender_page.html",
   2772                    FINAL_STATUS_APP_TERMINATING,
   2773                    1);
   2774   NavigateToURLWithDisposition(
   2775       "files/prerender/no_prerender_page.html#fragment",
   2776       CURRENT_TAB, false);
   2777 }
   2778 
   2779 // Checks that we do not use a prerendered page when we prerender a fragment
   2780 // but navigate to the main page.
   2781 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2782                        PrerenderFragmentNavigatePage) {
   2783   PrerenderTestURL("files/prerender/no_prerender_page.html#fragment",
   2784                    FINAL_STATUS_APP_TERMINATING,
   2785                    1);
   2786   NavigateToURLWithDisposition(
   2787       "files/prerender/no_prerender_page.html",
   2788       CURRENT_TAB, false);
   2789 }
   2790 
   2791 // Checks that we do not use a prerendered page when we prerender a fragment
   2792 // but navigate to a different fragment on the same page.
   2793 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2794                        PrerenderFragmentNavigateFragment) {
   2795   PrerenderTestURL("files/prerender/no_prerender_page.html#other_fragment",
   2796                    FINAL_STATUS_APP_TERMINATING,
   2797                    1);
   2798   NavigateToURLWithDisposition(
   2799       "files/prerender/no_prerender_page.html#fragment",
   2800       CURRENT_TAB, false);
   2801 }
   2802 
   2803 // Checks that we do not use a prerendered page when the page uses a client
   2804 // redirect to refresh from a fragment on the same page.
   2805 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2806                        PrerenderClientRedirectFromFragment) {
   2807   PrerenderTestURL(
   2808       CreateClientRedirect("files/prerender/no_prerender_page.html#fragment"),
   2809       FINAL_STATUS_APP_TERMINATING,
   2810       2);
   2811   NavigateToURLWithDisposition(
   2812       "files/prerender/no_prerender_page.html",
   2813       CURRENT_TAB, false);
   2814 }
   2815 
   2816 // Checks that we do not use a prerendered page when the page uses a client
   2817 // redirect to refresh to a fragment on the same page.
   2818 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2819                        PrerenderClientRedirectToFragment) {
   2820   PrerenderTestURL(
   2821       CreateClientRedirect("files/prerender/no_prerender_page.html"),
   2822       FINAL_STATUS_APP_TERMINATING,
   2823       2);
   2824   NavigateToURLWithDisposition(
   2825       "files/prerender/no_prerender_page.html#fragment",
   2826       CURRENT_TAB, false);
   2827 }
   2828 
   2829 // Checks that we correctly use a prerendered page when the page uses JS to set
   2830 // the window.location.hash to a fragment on the same page.
   2831 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2832                        PrerenderPageChangeFragmentLocationHash) {
   2833   PrerenderTestURL("files/prerender/prerender_fragment_location_hash.html",
   2834                    FINAL_STATUS_USED,
   2835                    1);
   2836   NavigateToURL("files/prerender/prerender_fragment_location_hash.html");
   2837 }
   2838 
   2839 // Checks that prerendering a PNG works correctly.
   2840 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderImagePng) {
   2841   DisableJavascriptCalls();
   2842   PrerenderTestURL("files/prerender/image.png", FINAL_STATUS_USED, 1);
   2843   NavigateToDestURL();
   2844 }
   2845 
   2846 // Checks that prerendering a JPG works correctly.
   2847 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderImageJpeg) {
   2848   DisableJavascriptCalls();
   2849   PrerenderTestURL("files/prerender/image.jpeg", FINAL_STATUS_USED, 1);
   2850   NavigateToDestURL();
   2851 }
   2852 
   2853 // Checks that a prerender of a CRX will result in a cancellation due to
   2854 // download.
   2855 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCrx) {
   2856   PrerenderTestURL("files/prerender/extension.crx", FINAL_STATUS_DOWNLOAD, 0);
   2857 }
   2858 
   2859 // Checks that xhr GET requests allow prerenders.
   2860 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrGet) {
   2861   PrerenderTestURL("files/prerender/prerender_xhr_get.html",
   2862                    FINAL_STATUS_USED,
   2863                    1);
   2864   NavigateToDestURL();
   2865 }
   2866 
   2867 // Checks that xhr HEAD requests allow prerenders.
   2868 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrHead) {
   2869   PrerenderTestURL("files/prerender/prerender_xhr_head.html",
   2870                    FINAL_STATUS_USED,
   2871                    1);
   2872   NavigateToDestURL();
   2873 }
   2874 
   2875 // Checks that xhr OPTIONS requests allow prerenders.
   2876 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrOptions) {
   2877   PrerenderTestURL("files/prerender/prerender_xhr_options.html",
   2878                    FINAL_STATUS_USED,
   2879                    1);
   2880   NavigateToDestURL();
   2881 }
   2882 
   2883 // Checks that xhr TRACE requests allow prerenders.
   2884 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrTrace) {
   2885   PrerenderTestURL("files/prerender/prerender_xhr_trace.html",
   2886                    FINAL_STATUS_USED,
   2887                    1);
   2888   NavigateToDestURL();
   2889 }
   2890 
   2891 // Checks that xhr POST requests allow prerenders.
   2892 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrPost) {
   2893   PrerenderTestURL("files/prerender/prerender_xhr_post.html",
   2894                    FINAL_STATUS_USED,
   2895                    1);
   2896   NavigateToDestURL();
   2897 }
   2898 
   2899 // Checks that xhr PUT cancels prerenders.
   2900 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrPut) {
   2901   PrerenderTestURL("files/prerender/prerender_xhr_put.html",
   2902                    FINAL_STATUS_INVALID_HTTP_METHOD,
   2903                    1);
   2904 }
   2905 
   2906 // Checks that xhr DELETE cancels prerenders.
   2907 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrDelete) {
   2908   PrerenderTestURL("files/prerender/prerender_xhr_delete.html",
   2909                    FINAL_STATUS_INVALID_HTTP_METHOD,
   2910                    1);
   2911 }
   2912 
   2913 // Checks that a top-level page which would trigger an SSL error is canceled.
   2914 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorTopLevel) {
   2915   net::SpawnedTestServer::SSLOptions ssl_options;
   2916   ssl_options.server_certificate =
   2917       net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
   2918   net::SpawnedTestServer https_server(
   2919       net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
   2920       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
   2921   ASSERT_TRUE(https_server.Start());
   2922   GURL https_url = https_server.GetURL("files/prerender/prerender_page.html");
   2923   PrerenderTestURL(https_url,
   2924                    FINAL_STATUS_SSL_ERROR,
   2925                    0);
   2926 }
   2927 
   2928 // Checks that an SSL error that comes from a subresource does not cancel
   2929 // the page. Non-main-frame requests are simply cancelled if they run into
   2930 // an SSL problem.
   2931 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorSubresource) {
   2932   net::SpawnedTestServer::SSLOptions ssl_options;
   2933   ssl_options.server_certificate =
   2934       net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
   2935   net::SpawnedTestServer https_server(
   2936       net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
   2937       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
   2938   ASSERT_TRUE(https_server.Start());
   2939   GURL https_url = https_server.GetURL("files/prerender/image.jpeg");
   2940   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   2941   replacement_text.push_back(
   2942       std::make_pair("REPLACE_WITH_IMAGE_URL", https_url.spec()));
   2943   std::string replacement_path;
   2944   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   2945       "files/prerender/prerender_with_image.html",
   2946       replacement_text,
   2947       &replacement_path));
   2948   PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
   2949   NavigateToDestURL();
   2950 }
   2951 
   2952 // Checks that an SSL error that comes from an iframe does not cancel
   2953 // the page. Non-main-frame requests are simply cancelled if they run into
   2954 // an SSL problem.
   2955 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorIframe) {
   2956   net::SpawnedTestServer::SSLOptions ssl_options;
   2957   ssl_options.server_certificate =
   2958       net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
   2959   net::SpawnedTestServer https_server(
   2960       net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
   2961       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
   2962   ASSERT_TRUE(https_server.Start());
   2963   GURL https_url = https_server.GetURL(
   2964       "files/prerender/prerender_embedded_content.html");
   2965   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   2966   replacement_text.push_back(
   2967       std::make_pair("REPLACE_WITH_URL", https_url.spec()));
   2968   std::string replacement_path;
   2969   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   2970       "files/prerender/prerender_with_iframe.html",
   2971       replacement_text,
   2972       &replacement_path));
   2973   PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
   2974   NavigateToDestURL();
   2975 }
   2976 
   2977 // Checks that we cancel correctly when window.print() is called.
   2978 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPrint) {
   2979   DisableLoadEventCheck();
   2980   PrerenderTestURL("files/prerender/prerender_print.html",
   2981                    FINAL_STATUS_WINDOW_PRINT,
   2982                    0);
   2983 }
   2984 
   2985 // Checks that if a page is opened in a new window by javascript and both the
   2986 // pages are in the same domain, the prerendered page is not used, due to
   2987 // there being other tabs in the same browsing instance.
   2988 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   2989                        PrerenderSameDomainWindowOpenerWindowOpen) {
   2990   PrerenderTestURL("files/prerender/prerender_page.html",
   2991                    FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE,
   2992                    1);
   2993   OpenDestURLViaWindowOpen();
   2994 }
   2995 
   2996 // Checks that if a page is opened due to click on a href with target="_blank"
   2997 // and both pages are in the same domain the prerendered page is not used, due
   2998 // there being other tabs in the same browsing instance.
   2999 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3000                        PrerenderSameDomainWindowOpenerClickTarget) {
   3001   PrerenderTestURL("files/prerender/prerender_page.html",
   3002                    FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE,
   3003                    1);
   3004   OpenDestURLViaClickTarget();
   3005 }
   3006 
   3007 // Checks that prerenders do not get swapped into target pages that have opened
   3008 // a popup, even if the target page itself does not have an opener.
   3009 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderTargetHasPopup) {
   3010   PrerenderTestURL("files/prerender/prerender_page.html",
   3011                    FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE,
   3012                    1);
   3013   OpenURLViaWindowOpen(GURL(url::kAboutBlankURL));
   3014   NavigateToDestURLWithDisposition(CURRENT_TAB, false);
   3015 }
   3016 
   3017 class TestClientCertStore : public net::ClientCertStore {
   3018  public:
   3019   TestClientCertStore() {}
   3020   virtual ~TestClientCertStore() {}
   3021 
   3022   // net::ClientCertStore:
   3023   virtual void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
   3024                               net::CertificateList* selected_certs,
   3025                               const base::Closure& callback) OVERRIDE {
   3026     *selected_certs = net::CertificateList(
   3027         1, scoped_refptr<net::X509Certificate>(
   3028         new net::X509Certificate("test", "test", base::Time(), base::Time())));
   3029     callback.Run();
   3030   }
   3031 };
   3032 
   3033 scoped_ptr<net::ClientCertStore> CreateCertStore() {
   3034   return scoped_ptr<net::ClientCertStore>(new TestClientCertStore);
   3035 }
   3036 
   3037 // Checks that a top-level page which would normally request an SSL client
   3038 // certificate will never be seen since it's an https top-level resource.
   3039 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3040                        PrerenderSSLClientCertTopLevel) {
   3041   ProfileIOData::FromResourceContext(
   3042       current_browser()->profile()->GetResourceContext())->
   3043           set_client_cert_store_factory_for_testing(
   3044               base::Bind(&CreateCertStore));
   3045   net::SpawnedTestServer::SSLOptions ssl_options;
   3046   ssl_options.request_client_certificate = true;
   3047   net::SpawnedTestServer https_server(
   3048       net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
   3049       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
   3050   ASSERT_TRUE(https_server.Start());
   3051   GURL https_url = https_server.GetURL("files/prerender/prerender_page.html");
   3052   PrerenderTestURL(https_url, FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED, 0);
   3053 }
   3054 
   3055 // Checks that an SSL Client Certificate request that originates from a
   3056 // subresource will cancel the prerendered page.
   3057 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3058                        PrerenderSSLClientCertSubresource) {
   3059   ProfileIOData::FromResourceContext(
   3060       current_browser()->profile()->GetResourceContext())->
   3061           set_client_cert_store_factory_for_testing(
   3062               base::Bind(&CreateCertStore));
   3063   net::SpawnedTestServer::SSLOptions ssl_options;
   3064   ssl_options.request_client_certificate = true;
   3065   net::SpawnedTestServer https_server(
   3066       net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
   3067       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
   3068   ASSERT_TRUE(https_server.Start());
   3069   GURL https_url = https_server.GetURL("files/prerender/image.jpeg");
   3070   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   3071   replacement_text.push_back(
   3072       std::make_pair("REPLACE_WITH_IMAGE_URL", https_url.spec()));
   3073   std::string replacement_path;
   3074   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   3075       "files/prerender/prerender_with_image.html",
   3076       replacement_text,
   3077       &replacement_path));
   3078   PrerenderTestURL(replacement_path,
   3079                    FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED,
   3080                    0);
   3081 }
   3082 
   3083 // Checks that an SSL Client Certificate request that originates from an
   3084 // iframe will cancel the prerendered page.
   3085 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLClientCertIframe) {
   3086   ProfileIOData::FromResourceContext(
   3087       current_browser()->profile()->GetResourceContext())->
   3088           set_client_cert_store_factory_for_testing(
   3089               base::Bind(&CreateCertStore));
   3090   net::SpawnedTestServer::SSLOptions ssl_options;
   3091   ssl_options.request_client_certificate = true;
   3092   net::SpawnedTestServer https_server(
   3093       net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
   3094       base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
   3095   ASSERT_TRUE(https_server.Start());
   3096   GURL https_url = https_server.GetURL(
   3097       "files/prerender/prerender_embedded_content.html");
   3098   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   3099   replacement_text.push_back(
   3100       std::make_pair("REPLACE_WITH_URL", https_url.spec()));
   3101   std::string replacement_path;
   3102   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   3103       "files/prerender/prerender_with_iframe.html",
   3104       replacement_text,
   3105       &replacement_path));
   3106   PrerenderTestURL(replacement_path,
   3107                    FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED,
   3108                    0);
   3109 }
   3110 
   3111 #if defined(FULL_SAFE_BROWSING)
   3112 // Ensures that we do not prerender pages with a safe browsing
   3113 // interstitial.
   3114 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSafeBrowsingTopLevel) {
   3115   GURL url = test_server()->GetURL("files/prerender/prerender_page.html");
   3116   GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
   3117       url, SB_THREAT_TYPE_URL_MALWARE);
   3118   PrerenderTestURL("files/prerender/prerender_page.html",
   3119                    FINAL_STATUS_SAFE_BROWSING, 0);
   3120 }
   3121 
   3122 // Ensures that server redirects to a malware page will cancel prerenders.
   3123 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3124                        PrerenderSafeBrowsingServerRedirect) {
   3125   GURL url = test_server()->GetURL("files/prerender/prerender_page.html");
   3126   GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
   3127       url, SB_THREAT_TYPE_URL_MALWARE);
   3128   PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"),
   3129                    FINAL_STATUS_SAFE_BROWSING,
   3130                    0);
   3131 }
   3132 
   3133 // Ensures that client redirects to a malware page will cancel prerenders.
   3134 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3135                        PrerenderSafeBrowsingClientRedirect) {
   3136   GURL url = test_server()->GetURL("files/prerender/prerender_page.html");
   3137   GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
   3138       url, SB_THREAT_TYPE_URL_MALWARE);
   3139   PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"),
   3140                    FINAL_STATUS_SAFE_BROWSING,
   3141                    1);
   3142 }
   3143 
   3144 // Ensures that we do not prerender pages which have a malware subresource.
   3145 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSafeBrowsingSubresource) {
   3146   GURL image_url = test_server()->GetURL("files/prerender/image.jpeg");
   3147   GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
   3148       image_url, SB_THREAT_TYPE_URL_MALWARE);
   3149   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   3150   replacement_text.push_back(
   3151       std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
   3152   std::string replacement_path;
   3153   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   3154       "files/prerender/prerender_with_image.html",
   3155       replacement_text,
   3156       &replacement_path));
   3157   PrerenderTestURL(replacement_path,
   3158                    FINAL_STATUS_SAFE_BROWSING,
   3159                    0);
   3160 }
   3161 
   3162 // Ensures that we do not prerender pages which have a malware iframe.
   3163 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSafeBrowsingIframe) {
   3164   GURL iframe_url = test_server()->GetURL(
   3165       "files/prerender/prerender_embedded_content.html");
   3166   GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
   3167       iframe_url, SB_THREAT_TYPE_URL_MALWARE);
   3168   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   3169   replacement_text.push_back(
   3170       std::make_pair("REPLACE_WITH_URL", iframe_url.spec()));
   3171   std::string replacement_path;
   3172   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   3173       "files/prerender/prerender_with_iframe.html",
   3174       replacement_text,
   3175       &replacement_path));
   3176   PrerenderTestURL(replacement_path,
   3177                    FINAL_STATUS_SAFE_BROWSING,
   3178                    0);
   3179 }
   3180 
   3181 #endif
   3182 
   3183 // Checks that a local storage read will not cause prerender to fail.
   3184 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderLocalStorageRead) {
   3185   PrerenderTestURL("files/prerender/prerender_localstorage_read.html",
   3186                    FINAL_STATUS_USED,
   3187                    1);
   3188   NavigateToDestURL();
   3189 }
   3190 
   3191 // Checks that a local storage write will not cause prerender to fail.
   3192 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderLocalStorageWrite) {
   3193   PrerenderTestURL("files/prerender/prerender_localstorage_write.html",
   3194                    FINAL_STATUS_USED,
   3195                    1);
   3196   NavigateToDestURL();
   3197 }
   3198 
   3199 // Checks that the favicon is properly loaded on prerender.
   3200 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderFavicon) {
   3201   scoped_ptr<TestPrerender> prerender =
   3202       PrerenderTestURL("files/prerender/prerender_favicon.html",
   3203                        FINAL_STATUS_USED,
   3204                        1);
   3205   NavigateToDestURL();
   3206 
   3207   if (!FaviconTabHelper::FromWebContents(
   3208           GetActiveWebContents())->FaviconIsValid()) {
   3209     // If the favicon has not been set yet, wait for it to be.
   3210     content::WindowedNotificationObserver favicon_update_watcher(
   3211         chrome::NOTIFICATION_FAVICON_UPDATED,
   3212         content::Source<WebContents>(GetActiveWebContents()));
   3213     favicon_update_watcher.Wait();
   3214   }
   3215   EXPECT_TRUE(FaviconTabHelper::FromWebContents(
   3216       GetActiveWebContents())->FaviconIsValid());
   3217 }
   3218 
   3219 // Checks that when a prerendered page is swapped in to a referring page, the
   3220 // unload handlers on the referring page are executed.
   3221 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderUnload) {
   3222   // Matches URL in prerender_loader_with_unload.html.
   3223   const GURL unload_url("http://unload-url.test");
   3224   base::FilePath empty_file = ui_test_utils::GetTestFilePath(
   3225       base::FilePath(), base::FilePath(FILE_PATH_LITERAL("empty.html")));
   3226   RequestCounter unload_counter;
   3227   BrowserThread::PostTask(
   3228       BrowserThread::IO, FROM_HERE,
   3229       base::Bind(&CreateCountingInterceptorOnIO,
   3230                  unload_url, empty_file, unload_counter.AsWeakPtr()));
   3231 
   3232   set_loader_path("files/prerender/prerender_loader_with_unload.html");
   3233   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   3234   NavigateToDestURL();
   3235   unload_counter.WaitForCount(1);
   3236 }
   3237 
   3238 // Checks that a hanging unload on the referring page of a prerender swap does
   3239 // not crash the browser on exit.
   3240 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHangingUnload) {
   3241   // Matches URL in prerender_loader_with_unload.html.
   3242   const GURL hang_url("http://unload-url.test");
   3243   base::FilePath empty_file = ui_test_utils::GetTestFilePath(
   3244       base::FilePath(), base::FilePath(FILE_PATH_LITERAL("empty.html")));
   3245   BrowserThread::PostTask(
   3246       BrowserThread::IO, FROM_HERE,
   3247       base::Bind(&CreateHangingFirstRequestInterceptorOnIO,
   3248                  hang_url, empty_file,
   3249                  base::Closure()));
   3250 
   3251   set_loader_path("files/prerender/prerender_loader_with_unload.html");
   3252   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   3253   NavigateToDestURL();
   3254 }
   3255 
   3256 
   3257 // Checks that when the history is cleared, prerendering is cancelled and
   3258 // prerendering history is cleared.
   3259 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClearHistory) {
   3260   scoped_ptr<TestPrerender> prerender =
   3261       PrerenderTestURL("files/prerender/prerender_page.html",
   3262                        FINAL_STATUS_CACHE_OR_HISTORY_CLEARED,
   3263                        1);
   3264 
   3265   ClearBrowsingData(current_browser(), BrowsingDataRemover::REMOVE_HISTORY);
   3266   prerender->WaitForStop();
   3267 
   3268   // Make sure prerender history was cleared.
   3269   EXPECT_EQ(0, GetHistoryLength());
   3270 }
   3271 
   3272 // Checks that when the cache is cleared, prerenders are cancelled but
   3273 // prerendering history is not cleared.
   3274 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClearCache) {
   3275   scoped_ptr<TestPrerender> prerender =
   3276       PrerenderTestURL("files/prerender/prerender_page.html",
   3277                        FINAL_STATUS_CACHE_OR_HISTORY_CLEARED,
   3278                        1);
   3279 
   3280   ClearBrowsingData(current_browser(), BrowsingDataRemover::REMOVE_CACHE);
   3281   prerender->WaitForStop();
   3282 
   3283   // Make sure prerender history was not cleared.  Not a vital behavior, but
   3284   // used to compare with PrerenderClearHistory test.
   3285   EXPECT_EQ(1, GetHistoryLength());
   3286 }
   3287 
   3288 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelAll) {
   3289   scoped_ptr<TestPrerender> prerender =
   3290       PrerenderTestURL("files/prerender/prerender_page.html",
   3291                        FINAL_STATUS_CANCELLED,
   3292                        1);
   3293 
   3294   GetPrerenderManager()->CancelAllPrerenders();
   3295   prerender->WaitForStop();
   3296 
   3297   EXPECT_FALSE(prerender->contents());
   3298 }
   3299 
   3300 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderEvents) {
   3301   scoped_ptr<TestPrerender> prerender =
   3302       PrerenderTestURL("files/prerender/prerender_page.html",
   3303                        FINAL_STATUS_CANCELLED, 1);
   3304 
   3305   GetPrerenderManager()->CancelAllPrerenders();
   3306   prerender->WaitForStop();
   3307 
   3308   EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
   3309   EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(0));
   3310   EXPECT_FALSE(HadPrerenderEventErrors());
   3311 }
   3312 
   3313 // Cancels the prerender of a page with its own prerender.  The second prerender
   3314 // should never be started.
   3315 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3316                        PrerenderCancelPrerenderWithPrerender) {
   3317   scoped_ptr<TestPrerender> prerender =
   3318       PrerenderTestURL("files/prerender/prerender_infinite_a.html",
   3319                        FINAL_STATUS_CANCELLED,
   3320                        1);
   3321 
   3322   GetPrerenderManager()->CancelAllPrerenders();
   3323   prerender->WaitForStop();
   3324 
   3325   EXPECT_FALSE(prerender->contents());
   3326 }
   3327 
   3328 // Prerendering and history tests.
   3329 // The prerendered page is navigated to in several ways [navigate via
   3330 // omnibox, click on link, key-modified click to open in background tab, etc],
   3331 // followed by a navigation to another page from the prerendered page, followed
   3332 // by a back navigation.
   3333 
   3334 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNavigateClickGoBack) {
   3335   PrerenderTestURL("files/prerender/prerender_page_with_link.html",
   3336                    FINAL_STATUS_USED,
   3337                    1);
   3338   NavigateToDestURL();
   3339   ClickToNextPageAfterPrerender();
   3340   GoBackToPrerender();
   3341 }
   3342 
   3343 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNavigateNavigateGoBack) {
   3344   PrerenderTestURL("files/prerender/prerender_page_with_link.html",
   3345                    FINAL_STATUS_USED,
   3346                    1);
   3347   NavigateToDestURL();
   3348   NavigateToNextPageAfterPrerender();
   3349   GoBackToPrerender();
   3350 }
   3351 
   3352 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickClickGoBack) {
   3353   PrerenderTestURL("files/prerender/prerender_page_with_link.html",
   3354                    FINAL_STATUS_USED,
   3355                    1);
   3356   OpenDestURLViaClick();
   3357   ClickToNextPageAfterPrerender();
   3358   GoBackToPrerender();
   3359 }
   3360 
   3361 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNavigateGoBack) {
   3362   PrerenderTestURL("files/prerender/prerender_page_with_link.html",
   3363                    FINAL_STATUS_USED,
   3364                    1);
   3365   OpenDestURLViaClick();
   3366   NavigateToNextPageAfterPrerender();
   3367   GoBackToPrerender();
   3368 }
   3369 
   3370 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewWindow) {
   3371   // Prerender currently doesn't interpose on this navigation.
   3372   // http://crbug.com/345474.
   3373   PrerenderTestURL("files/prerender/prerender_page_with_link.html",
   3374                    FINAL_STATUS_USED,
   3375                    1);
   3376   OpenDestURLViaClickNewWindow();
   3377 }
   3378 
   3379 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewForegroundTab) {
   3380   // Prerender currently doesn't interpose on this navigation.
   3381   // http://crbug.com/345474.
   3382   PrerenderTestURL("files/prerender/prerender_page_with_link.html",
   3383                    FINAL_STATUS_USED,
   3384                    1);
   3385   OpenDestURLViaClickNewForegroundTab();
   3386 }
   3387 
   3388 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewBackgroundTab) {
   3389   // Prerender currently doesn't interpose on this navigation.
   3390   // http://crbug.com/345474.
   3391   scoped_ptr<TestPrerender> prerender =
   3392       PrerenderTestURL("files/prerender/prerender_page_with_link.html",
   3393                        FINAL_STATUS_USED,
   3394                        1);
   3395   ASSERT_TRUE(prerender->contents());
   3396   prerender->contents()->set_should_be_shown(false);
   3397   OpenDestURLViaClickNewBackgroundTab();
   3398 }
   3399 
   3400 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3401                        NavigateToPrerenderedPageWhenDevToolsAttached) {
   3402   DisableJavascriptCalls();
   3403   WebContents* web_contents =
   3404       current_browser()->tab_strip_model()->GetActiveWebContents();
   3405   scoped_refptr<DevToolsAgentHost> agent(
   3406       DevToolsAgentHost::GetOrCreateFor(web_contents));
   3407   FakeDevToolsClient client;
   3408   agent->AttachClient(&client);
   3409   const char* url = "files/prerender/prerender_page.html";
   3410   PrerenderTestURL(url, FINAL_STATUS_DEVTOOLS_ATTACHED, 1);
   3411   NavigateToURLWithDisposition(url, CURRENT_TAB, false);
   3412   agent->DetachClient();
   3413 }
   3414 
   3415 // Validate that the sessionStorage namespace remains the same when swapping
   3416 // in a prerendered page.
   3417 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSessionStorage) {
   3418   set_loader_path("files/prerender/prerender_loader_with_session_storage.html");
   3419   PrerenderTestURL(GetCrossDomainTestUrl("files/prerender/prerender_page.html"),
   3420                    FINAL_STATUS_USED,
   3421                    1);
   3422   NavigateToDestURL();
   3423   GoBackToPageBeforePrerender();
   3424 }
   3425 
   3426 // Checks that the control group works.  An XHR PUT cannot be detected in the
   3427 // control group.
   3428 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ControlGroup) {
   3429   RestorePrerenderMode restore_prerender_mode;
   3430   PrerenderManager::SetMode(
   3431       PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
   3432   DisableJavascriptCalls();
   3433   PrerenderTestURL("files/prerender/prerender_xhr_put.html",
   3434                    FINAL_STATUS_WOULD_HAVE_BEEN_USED, 0);
   3435   NavigateToDestURL();
   3436 }
   3437 
   3438 // Checks that the control group correctly hits WOULD_HAVE_BEEN_USED
   3439 // renderer-initiated navigations. (This verifies that the ShouldFork logic
   3440 // behaves correctly.)
   3441 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ControlGroupRendererInitiated) {
   3442   RestorePrerenderMode restore_prerender_mode;
   3443   PrerenderManager::SetMode(
   3444       PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
   3445   DisableJavascriptCalls();
   3446   PrerenderTestURL("files/prerender/prerender_xhr_put.html",
   3447                    FINAL_STATUS_WOULD_HAVE_BEEN_USED, 0);
   3448   OpenDestURLViaClick();
   3449 }
   3450 
   3451 // Make sure that the MatchComplete dummy works in the normal case.  Once
   3452 // a prerender is cancelled because of a script, a dummy must be created to
   3453 // account for the MatchComplete case, and it must have a final status of
   3454 // FINAL_STATUS_WOULD_HAVE_BEEN_USED.
   3455 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MatchCompleteDummy) {
   3456   RestorePrerenderMode restore_prerender_mode;
   3457   PrerenderManager::SetMode(
   3458       PrerenderManager::PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP);
   3459 
   3460   std::vector<FinalStatus> expected_final_status_queue;
   3461   expected_final_status_queue.push_back(FINAL_STATUS_INVALID_HTTP_METHOD);
   3462   expected_final_status_queue.push_back(FINAL_STATUS_WOULD_HAVE_BEEN_USED);
   3463   PrerenderTestURL("files/prerender/prerender_xhr_put.html",
   3464                    expected_final_status_queue, 1);
   3465   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
   3466   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
   3467   histogram_tester().ExpectTotalCount(
   3468       "Prerender.none_PerceivedPLTMatchedComplete", 0);
   3469   histogram_tester().ExpectTotalCount(
   3470       "Prerender.websame_PrerenderNotSwappedInPLT", 1);
   3471 
   3472   NavigateToDestURL();
   3473   histogram_tester().ExpectTotalCount("Prerender.websame_PerceivedPLT", 1);
   3474   histogram_tester().ExpectTotalCount("Prerender.websame_PerceivedPLTMatched",
   3475                                       0);
   3476   histogram_tester().ExpectTotalCount(
   3477       "Prerender.websame_PerceivedPLTMatchedComplete", 1);
   3478 }
   3479 
   3480 // Verify that a navigation that hits a MatchComplete dummy while another is in
   3481 // progress does not also classify the previous navigation as a MatchComplete.
   3482 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3483                        MatchCompleteDummyCancelNavigation) {
   3484   RestorePrerenderMode restore_prerender_mode;
   3485   PrerenderManager::SetMode(
   3486       PrerenderManager::PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP);
   3487 
   3488   // Arrange for a URL to hang.
   3489   const GURL kNoCommitUrl("http://never-respond.example.com");
   3490   base::FilePath file(FILE_PATH_LITERAL(
   3491       "chrome/test/data/prerender/prerender_page.html"));
   3492   base::RunLoop hang_loop;
   3493   BrowserThread::PostTask(
   3494       BrowserThread::IO, FROM_HERE,
   3495       base::Bind(&CreateHangingFirstRequestInterceptorOnIO, kNoCommitUrl,
   3496                  file, hang_loop.QuitClosure()));
   3497 
   3498   // First, fire a prerender that aborts after it completes its load.
   3499   std::vector<FinalStatus> expected_final_status_queue;
   3500   expected_final_status_queue.push_back(FINAL_STATUS_INVALID_HTTP_METHOD);
   3501   expected_final_status_queue.push_back(FINAL_STATUS_WOULD_HAVE_BEEN_USED);
   3502   PrerenderTestURL("files/prerender/prerender_xhr_put.html",
   3503                    expected_final_status_queue, 1);
   3504   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
   3505   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
   3506   histogram_tester().ExpectTotalCount(
   3507       "Prerender.none_PerceivedPLTMatchedComplete", 0);
   3508   histogram_tester().ExpectTotalCount(
   3509       "Prerender.websame_PrerenderNotSwappedInPLT", 1);
   3510 
   3511   // Open the hanging URL in a new tab. Wait for both the new tab to open and
   3512   // the hanging request to be scheduled.
   3513   ui_test_utils::NavigateToURLWithDisposition(
   3514       current_browser(), kNoCommitUrl, NEW_FOREGROUND_TAB,
   3515       ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
   3516   hang_loop.Run();
   3517 
   3518   // Now interrupt that navigation and navigate to the destination URL. This
   3519   // should forcibly complete the previous navigation and also complete a
   3520   // WOULD_HAVE_BEEN_PRERENDERED navigation.
   3521   NavigateToDestURL();
   3522   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLT", 2);
   3523   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
   3524   histogram_tester().ExpectTotalCount(
   3525       "Prerender.none_PerceivedPLTMatchedComplete", 0);
   3526   histogram_tester().ExpectTotalCount("Prerender.websame_PerceivedPLT", 1);
   3527   histogram_tester().ExpectTotalCount("Prerender.websame_PerceivedPLTMatched",
   3528                                       0);
   3529   histogram_tester().ExpectTotalCount(
   3530       "Prerender.websame_PerceivedPLTMatchedComplete", 1);
   3531 }
   3532 
   3533 class PrerenderBrowserTestWithNaCl : public PrerenderBrowserTest {
   3534  public:
   3535   PrerenderBrowserTestWithNaCl() {}
   3536   virtual ~PrerenderBrowserTestWithNaCl() {}
   3537 
   3538   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
   3539     PrerenderBrowserTest::SetUpCommandLine(command_line);
   3540     command_line->AppendSwitch(switches::kEnableNaCl);
   3541   }
   3542 };
   3543 
   3544 // Check that NaCl plugins work when enabled, with prerendering.
   3545 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithNaCl,
   3546                        PrerenderNaClPluginEnabled) {
   3547 #if defined(OS_WIN) && defined(USE_ASH)
   3548   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
   3549   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
   3550     return;
   3551 #endif
   3552 
   3553   PrerenderTestURL("files/prerender/prerender_plugin_nacl_enabled.html",
   3554                    FINAL_STATUS_USED,
   3555                    1);
   3556   NavigateToDestURL();
   3557 
   3558   // To avoid any chance of a race, we have to let the script send its response
   3559   // asynchronously.
   3560   WebContents* web_contents =
   3561       browser()->tab_strip_model()->GetActiveWebContents();
   3562   bool display_test_result = false;
   3563   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents,
   3564                                                    "DidDisplayReallyPass()",
   3565                                                    &display_test_result));
   3566   ASSERT_TRUE(display_test_result);
   3567 }
   3568 
   3569 // Checks that the referrer policy is used when prerendering.
   3570 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReferrerPolicy) {
   3571   set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html");
   3572   PrerenderTestURL("files/prerender/prerender_referrer_policy.html",
   3573                    FINAL_STATUS_USED,
   3574                    1);
   3575   NavigateToDestURL();
   3576 }
   3577 
   3578 // Checks that the referrer policy is used when prerendering on HTTPS.
   3579 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3580                        PrerenderSSLReferrerPolicy) {
   3581   UseHttpsSrcServer();
   3582   set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html");
   3583   PrerenderTestURL("files/prerender/prerender_referrer_policy.html",
   3584                    FINAL_STATUS_USED,
   3585                    1);
   3586   NavigateToDestURL();
   3587 }
   3588 
   3589 // Checks that the referrer policy is used when prerendering is cancelled.
   3590 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelReferrerPolicy) {
   3591   scoped_ptr<TestContentBrowserClient> test_content_browser_client(
   3592       new TestContentBrowserClient);
   3593   content::ContentBrowserClient* original_browser_client =
   3594       content::SetBrowserClientForTesting(test_content_browser_client.get());
   3595 
   3596   set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html");
   3597   PrerenderTestURL("files/prerender/prerender_referrer_policy.html",
   3598                    FINAL_STATUS_CANCELLED,
   3599                    1);
   3600   OpenDestURLViaClick();
   3601 
   3602   bool display_test_result = false;
   3603   WebContents* web_contents =
   3604       browser()->tab_strip_model()->GetActiveWebContents();
   3605   ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
   3606       web_contents,
   3607       "window.domAutomationController.send(DidDisplayPass())",
   3608       &display_test_result));
   3609   EXPECT_TRUE(display_test_result);
   3610 
   3611   content::SetBrowserClientForTesting(original_browser_client);
   3612 }
   3613 
   3614 // Test interaction of the webNavigation and tabs API with prerender.
   3615 class PrerenderBrowserTestWithExtensions : public PrerenderBrowserTest,
   3616                                            public ExtensionApiTest {
   3617  public:
   3618   PrerenderBrowserTestWithExtensions() {
   3619     // The individual tests start the test server through ExtensionApiTest, so
   3620     // the port number can be passed through to the extension.
   3621     autostart_test_server_ = false;
   3622   }
   3623 
   3624   virtual void SetUp() OVERRIDE {
   3625     PrerenderBrowserTest::SetUp();
   3626   }
   3627 
   3628   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
   3629     PrerenderBrowserTest::SetUpCommandLine(command_line);
   3630     ExtensionApiTest::SetUpCommandLine(command_line);
   3631   }
   3632 
   3633   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
   3634     PrerenderBrowserTest::SetUpInProcessBrowserTestFixture();
   3635     ExtensionApiTest::SetUpInProcessBrowserTestFixture();
   3636   }
   3637 
   3638   virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
   3639     PrerenderBrowserTest::TearDownInProcessBrowserTestFixture();
   3640     ExtensionApiTest::TearDownInProcessBrowserTestFixture();
   3641   }
   3642 
   3643   virtual void SetUpOnMainThread() OVERRIDE {
   3644     PrerenderBrowserTest::SetUpOnMainThread();
   3645   }
   3646 };
   3647 
   3648 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, WebNavigation) {
   3649   ASSERT_TRUE(StartSpawnedTestServer());
   3650   extensions::FrameNavigationState::set_allow_extension_scheme(true);
   3651 
   3652   // Wait for the extension to set itself up and return control to us.
   3653   ASSERT_TRUE(RunExtensionTest("webnavigation/prerender")) << message_;
   3654 
   3655   extensions::ResultCatcher catcher;
   3656 
   3657   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   3658 
   3659   ChannelDestructionWatcher channel_close_watcher;
   3660   channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
   3661       GetActiveWebContents()->GetRenderProcessHost());
   3662   NavigateToDestURL();
   3663   channel_close_watcher.WaitForChannelClose();
   3664 
   3665   ASSERT_TRUE(IsEmptyPrerenderLinkManager());
   3666   ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
   3667 }
   3668 
   3669 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, TabsApi) {
   3670   ASSERT_TRUE(StartSpawnedTestServer());
   3671   extensions::FrameNavigationState::set_allow_extension_scheme(true);
   3672 
   3673   // Wait for the extension to set itself up and return control to us.
   3674   ASSERT_TRUE(RunExtensionTest("tabs/on_replaced")) << message_;
   3675 
   3676   extensions::ResultCatcher catcher;
   3677 
   3678   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   3679 
   3680   ChannelDestructionWatcher channel_close_watcher;
   3681   channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
   3682       GetActiveWebContents()->GetRenderProcessHost());
   3683   NavigateToDestURL();
   3684   channel_close_watcher.WaitForChannelClose();
   3685 
   3686   ASSERT_TRUE(IsEmptyPrerenderLinkManager());
   3687   ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
   3688 }
   3689 
   3690 // Test that prerenders abort when navigating to a stream.
   3691 // See chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
   3692 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, StreamsTest) {
   3693   RestorePrerenderMode restore_prerender_mode;
   3694   PrerenderManager::SetMode(
   3695       PrerenderManager::PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP);
   3696 
   3697   ASSERT_TRUE(StartSpawnedTestServer());
   3698 
   3699   const extensions::Extension* extension = LoadExtension(
   3700       test_data_dir_.AppendASCII("streams_private/handle_mime_type"));
   3701   ASSERT_TRUE(extension);
   3702   EXPECT_EQ(std::string(extension_misc::kStreamsPrivateTestExtensionId),
   3703             extension->id());
   3704   MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension);
   3705   ASSERT_TRUE(handler);
   3706   EXPECT_TRUE(handler->CanHandleMIMEType("application/msword"));
   3707 
   3708   PrerenderTestURL("files/prerender/document.doc", FINAL_STATUS_DOWNLOAD, 0);
   3709 
   3710   // Sanity-check that the extension would have picked up the stream in a normal
   3711   // navigation had prerender not intercepted it.
   3712   // streams_private/handle_mime_type reports success if it has handled the
   3713   // application/msword type.
   3714   extensions::ResultCatcher catcher;
   3715   NavigateToDestURL();
   3716   EXPECT_TRUE(catcher.GetNextResult());
   3717 }
   3718 
   3719 // Checks that non-http/https/chrome-extension subresource cancels the
   3720 // prerender.
   3721 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3722                        PrerenderCancelSubresourceUnsupportedScheme) {
   3723   GURL image_url = GURL("invalidscheme://www.google.com/test.jpg");
   3724   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   3725   replacement_text.push_back(
   3726       std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
   3727   std::string replacement_path;
   3728   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   3729       "files/prerender/prerender_with_image.html",
   3730       replacement_text,
   3731       &replacement_path));
   3732   PrerenderTestURL(replacement_path, FINAL_STATUS_UNSUPPORTED_SCHEME, 0);
   3733 }
   3734 
   3735 // Ensure that about:blank is permitted for any subresource.
   3736 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3737                        PrerenderAllowAboutBlankSubresource) {
   3738   GURL image_url = GURL("about:blank");
   3739   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   3740   replacement_text.push_back(
   3741       std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
   3742   std::string replacement_path;
   3743   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   3744       "files/prerender/prerender_with_image.html",
   3745       replacement_text,
   3746       &replacement_path));
   3747   PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
   3748   NavigateToDestURL();
   3749 }
   3750 
   3751 // Checks that non-http/https/chrome-extension subresource cancels the prerender
   3752 // on redirect.
   3753 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3754                        PrerenderCancelSubresourceRedirectUnsupportedScheme) {
   3755   GURL image_url = test_server()->GetURL(
   3756       CreateServerRedirect("invalidscheme://www.google.com/test.jpg"));
   3757   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   3758   replacement_text.push_back(
   3759       std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
   3760   std::string replacement_path;
   3761   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   3762       "files/prerender/prerender_with_image.html",
   3763       replacement_text,
   3764       &replacement_path));
   3765   PrerenderTestURL(replacement_path, FINAL_STATUS_UNSUPPORTED_SCHEME, 0);
   3766 }
   3767 
   3768 // Checks that chrome-extension subresource does not cancel the prerender.
   3769 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3770                        PrerenderKeepSubresourceExtensionScheme) {
   3771   GURL image_url = GURL("chrome-extension://abcdefg/test.jpg");
   3772   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   3773   replacement_text.push_back(
   3774       std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
   3775   std::string replacement_path;
   3776   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   3777       "files/prerender/prerender_with_image.html",
   3778       replacement_text,
   3779       &replacement_path));
   3780   PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
   3781   NavigateToDestURL();
   3782 }
   3783 
   3784 // Checks that redirect to chrome-extension subresource does not cancel the
   3785 // prerender.
   3786 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3787                        PrerenderKeepSubresourceRedirectExtensionScheme) {
   3788   GURL image_url = test_server()->GetURL(
   3789       CreateServerRedirect("chrome-extension://abcdefg/test.jpg"));
   3790   std::vector<net::SpawnedTestServer::StringPair> replacement_text;
   3791   replacement_text.push_back(
   3792       std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
   3793   std::string replacement_path;
   3794   ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
   3795       "files/prerender/prerender_with_image.html",
   3796       replacement_text,
   3797       &replacement_path));
   3798   PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
   3799   NavigateToDestURL();
   3800 }
   3801 
   3802 // Checks that non-http/https main page redirects cancel the prerender.
   3803 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3804                        PrerenderCancelMainFrameRedirectUnsupportedScheme) {
   3805   GURL url = test_server()->GetURL(
   3806       CreateServerRedirect("invalidscheme://www.google.com/test.html"));
   3807   PrerenderTestURL(url, FINAL_STATUS_UNSUPPORTED_SCHEME, 0);
   3808 }
   3809 
   3810 // Checks that media source video loads are deferred on prerendering.
   3811 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5MediaSourceVideo) {
   3812   PrerenderTestURL("files/prerender/prerender_html5_video_media_source.html",
   3813                    FINAL_STATUS_USED,
   3814                    1);
   3815   NavigateToDestURL();
   3816   WaitForASCIITitle(GetActiveWebContents(), kPassTitle);
   3817 }
   3818 
   3819 // Checks that a prerender that creates an audio stream (via a WebAudioDevice)
   3820 // is cancelled.
   3821 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderWebAudioDevice) {
   3822   DisableLoadEventCheck();
   3823   PrerenderTestURL("files/prerender/prerender_web_audio_device.html",
   3824                    FINAL_STATUS_CREATING_AUDIO_STREAM, 0);
   3825 }
   3826 
   3827 // Checks that prerenders do not swap in to WebContents being captured.
   3828 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCapturedWebContents) {
   3829   PrerenderTestURL("files/prerender/prerender_page.html",
   3830                    FINAL_STATUS_PAGE_BEING_CAPTURED, 1);
   3831   WebContents* web_contents = GetActiveWebContents();
   3832   web_contents->IncrementCapturerCount(gfx::Size());
   3833   NavigateToDestURLWithDisposition(CURRENT_TAB, false);
   3834   web_contents->DecrementCapturerCount();
   3835 }
   3836 
   3837 // Checks that prerenders are aborted on cross-process navigation from
   3838 // a server redirect.
   3839 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3840                        PrerenderCrossProcessServerRedirect) {
   3841   // Force everything to be a process swap.
   3842   SwapProcessesContentBrowserClient test_browser_client;
   3843   content::ContentBrowserClient* original_browser_client =
   3844       content::SetBrowserClientForTesting(&test_browser_client);
   3845 
   3846   PrerenderTestURL(
   3847       CreateServerRedirect("files/prerender/prerender_page.html"),
   3848       FINAL_STATUS_OPEN_URL, 0);
   3849 
   3850   content::SetBrowserClientForTesting(original_browser_client);
   3851 }
   3852 
   3853 // Checks that URLRequests for prerenders being aborted on cross-process
   3854 // navigation from a server redirect are cleaned up, so they don't keep cache
   3855 // entries locked.
   3856 // See http://crbug.com/341134
   3857 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3858                        PrerenderCrossProcessServerRedirectNoHang) {
   3859   const char kDestPath[] = "files/prerender/prerender_page.html";
   3860   // Force everything to be a process swap.
   3861   SwapProcessesContentBrowserClient test_browser_client;
   3862   content::ContentBrowserClient* original_browser_client =
   3863       content::SetBrowserClientForTesting(&test_browser_client);
   3864 
   3865   PrerenderTestURL(CreateServerRedirect(kDestPath), FINAL_STATUS_OPEN_URL, 0);
   3866 
   3867   ui_test_utils::NavigateToURL(
   3868       browser(),
   3869       test_server()->GetURL(kDestPath));
   3870 
   3871   content::SetBrowserClientForTesting(original_browser_client);
   3872 }
   3873 
   3874 // Checks that prerenders are aborted on cross-process navigation from
   3875 // a client redirect.
   3876 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3877                        PrerenderCrossProcessClientRedirect) {
   3878   // Cross-process navigation logic for renderer-initiated navigations
   3879   // is partially controlled by the renderer, namely
   3880   // ChromeContentRendererClient. This test instead relies on the Web
   3881   // Store triggering such navigations.
   3882   std::string webstore_url = extension_urls::GetWebstoreLaunchURL();
   3883 
   3884   // Mock out requests to the Web Store.
   3885   base::FilePath file(GetTestPath("prerender_page.html"));
   3886   BrowserThread::PostTask(
   3887       BrowserThread::IO, FROM_HERE,
   3888       base::Bind(&CreateMockInterceptorOnIO, GURL(webstore_url), file));
   3889 
   3890   PrerenderTestURL(CreateClientRedirect(webstore_url),
   3891                    FINAL_STATUS_OPEN_URL, 1);
   3892 }
   3893 
   3894 // Checks that canceling a MatchComplete dummy doesn't result in two
   3895 // stop events.
   3896 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, CancelMatchCompleteDummy) {
   3897   RestorePrerenderMode restore_prerender_mode;
   3898   PrerenderManager::SetMode(
   3899       PrerenderManager::PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP);
   3900 
   3901   std::vector<FinalStatus> expected_final_status_queue;
   3902   expected_final_status_queue.push_back(FINAL_STATUS_JAVASCRIPT_ALERT);
   3903   expected_final_status_queue.push_back(FINAL_STATUS_CANCELLED);
   3904   ScopedVector<TestPrerender> prerenders =
   3905       PrerenderTestURL("files/prerender/prerender_alert_before_onload.html",
   3906                        expected_final_status_queue, 0);
   3907 
   3908   // Cancel the MatchComplete dummy.
   3909   GetPrerenderManager()->CancelAllPrerenders();
   3910   prerenders[1]->WaitForStop();
   3911 
   3912   // Check the referring page only got one copy of the event.
   3913   EXPECT_FALSE(HadPrerenderEventErrors());
   3914 }
   3915 
   3916 // Checks that a deferred redirect to an image is not loaded until the page is
   3917 // visible. Also test the right histogram events are emitted in this case.
   3918 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredImage) {
   3919   DisableJavascriptCalls();
   3920 
   3921   // The prerender will not completely load until after the swap, so wait for a
   3922   // title change before calling DidPrerenderPass.
   3923   scoped_ptr<TestPrerender> prerender =
   3924       PrerenderTestURL(
   3925           "files/prerender/prerender_deferred_image.html",
   3926           FINAL_STATUS_USED, 0);
   3927   WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle);
   3928   EXPECT_EQ(1, GetPrerenderDomContentLoadedEventCountForLinkNumber(0));
   3929   EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents()));
   3930   EXPECT_EQ(0, prerender->number_of_loads());
   3931   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
   3932   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
   3933   histogram_tester().ExpectTotalCount(
   3934       "Prerender.none_PerceivedPLTMatchedComplete", 0);
   3935   histogram_tester().ExpectTotalCount(
   3936       "Prerender.websame_PrerenderNotSwappedInPLT", 0);
   3937 
   3938   // Swap.
   3939   NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(),
   3940                                          GetActiveWebContents());
   3941   ui_test_utils::NavigateToURLWithDisposition(
   3942       current_browser(), dest_url(), CURRENT_TAB,
   3943       ui_test_utils::BROWSER_TEST_NONE);
   3944   swap_observer.Wait();
   3945 
   3946   // The prerender never observes the final load.
   3947   EXPECT_EQ(0, prerender->number_of_loads());
   3948 
   3949   // Now check DidDisplayPass.
   3950   EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
   3951 
   3952   histogram_tester().ExpectTotalCount(
   3953       "Prerender.websame_PrerenderNotSwappedInPLT", 0);
   3954   histogram_tester().ExpectTotalCount("Prerender.websame_PerceivedPLT", 1);
   3955   histogram_tester().ExpectTotalCount("Prerender.websame_PerceivedPLTMatched",
   3956                                       1);
   3957   histogram_tester().ExpectTotalCount(
   3958       "Prerender.websame_PerceivedPLTMatchedComplete", 1);
   3959 }
   3960 
   3961 // Checks that a deferred redirect to an image is not loaded until the
   3962 // page is visible, even after another redirect.
   3963 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   3964                        PrerenderDeferredImageAfterRedirect) {
   3965   DisableJavascriptCalls();
   3966 
   3967   // The prerender will not completely load until after the swap, so wait for a
   3968   // title change before calling DidPrerenderPass.
   3969   scoped_ptr<TestPrerender> prerender =
   3970       PrerenderTestURL(
   3971           "files/prerender/prerender_deferred_image.html",
   3972           FINAL_STATUS_USED, 0);
   3973   WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle);
   3974   EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents()));
   3975   EXPECT_EQ(0, prerender->number_of_loads());
   3976 
   3977   // Swap.
   3978   NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(),
   3979                                          GetActiveWebContents());
   3980   ui_test_utils::NavigateToURLWithDisposition(
   3981       current_browser(), dest_url(), CURRENT_TAB,
   3982       ui_test_utils::BROWSER_TEST_NONE);
   3983   swap_observer.Wait();
   3984 
   3985   // The prerender never observes the final load.
   3986   EXPECT_EQ(0, prerender->number_of_loads());
   3987 
   3988   // Now check DidDisplayPass.
   3989   EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
   3990 }
   3991 
   3992 // Checks that deferred redirects in the main frame are followed.
   3993 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredMainFrame) {
   3994   DisableJavascriptCalls();
   3995   PrerenderTestURL(
   3996       "files/prerender/image-deferred.png",
   3997       FINAL_STATUS_USED, 1);
   3998   NavigateToDestURL();
   3999 }
   4000 
   4001 // Checks that deferred redirects in the main frame are followed, even
   4002 // with a double-redirect.
   4003 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   4004                        PrerenderDeferredMainFrameAfterRedirect) {
   4005   DisableJavascriptCalls();
   4006   PrerenderTestURL(
   4007       CreateServerRedirect("files/prerender/image-deferred.png"),
   4008       FINAL_STATUS_USED, 1);
   4009   NavigateToDestURL();
   4010 }
   4011 
   4012 // Checks that deferred redirects in a synchronous XHR abort the
   4013 // prerender.
   4014 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredSynchronousXHR) {
   4015   RestorePrerenderMode restore_prerender_mode;
   4016   PrerenderManager::SetMode(
   4017       PrerenderManager::PRERENDER_MODE_EXPERIMENT_MATCH_COMPLETE_GROUP);
   4018   PrerenderTestURL("files/prerender/prerender_deferred_sync_xhr.html",
   4019                    FINAL_STATUS_BAD_DEFERRED_REDIRECT, 0);
   4020   NavigateToDestURL();
   4021 }
   4022 
   4023 // Checks that prerenders are not swapped for navigations with extra headers.
   4024 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderExtraHeadersNoSwap) {
   4025   PrerenderTestURL("files/prerender/prerender_page.html",
   4026                    FINAL_STATUS_APP_TERMINATING, 1);
   4027 
   4028   content::OpenURLParams params(dest_url(), Referrer(), CURRENT_TAB,
   4029                                 ui::PAGE_TRANSITION_TYPED, false);
   4030   params.extra_headers = "X-Custom-Header: 42\r\n";
   4031   NavigateToURLWithParams(params, false);
   4032 }
   4033 
   4034 // Checks that prerenders are not swapped for navigations with browser-initiated
   4035 // POST data.
   4036 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   4037                        PrerenderBrowserInitiatedPostNoSwap) {
   4038   PrerenderTestURL("files/prerender/prerender_page.html",
   4039                    FINAL_STATUS_APP_TERMINATING, 1);
   4040 
   4041   std::string post_data = "DATA";
   4042   content::OpenURLParams params(dest_url(), Referrer(), CURRENT_TAB,
   4043                                 ui::PAGE_TRANSITION_TYPED, false);
   4044   params.uses_post = true;
   4045   params.browser_initiated_post_data =
   4046       base::RefCountedString::TakeString(&post_data);
   4047   NavigateToURLWithParams(params, false);
   4048 }
   4049 
   4050 // Checks that the prerendering of a page is canceled correctly when the
   4051 // prerendered page tries to make a second navigation entry.
   4052 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNewNavigationEntry) {
   4053   PrerenderTestURL("files/prerender/prerender_new_entry.html",
   4054                    FINAL_STATUS_NEW_NAVIGATION_ENTRY,
   4055                    1);
   4056 }
   4057 
   4058 // Attempt a swap-in in a new tab, verifying that session storage namespace
   4059 // merging works.
   4060 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageNewTab) {
   4061   // Mock out some URLs and count the number of requests to one of them. Both
   4062   // prerender_session_storage.html and init_session_storage.html need to be
   4063   // mocked so they are same-origin.
   4064   const GURL kInitURL("http://prerender.test/init_session_storage.html");
   4065   base::FilePath init_file = GetTestPath("init_session_storage.html");
   4066   BrowserThread::PostTask(
   4067       BrowserThread::IO, FROM_HERE,
   4068       base::Bind(&CreateMockInterceptorOnIO, kInitURL, init_file));
   4069 
   4070   const GURL kTestURL("http://prerender.test/prerender_session_storage.html");
   4071   base::FilePath test_file = GetTestPath("prerender_session_storage.html");
   4072   RequestCounter counter;
   4073   BrowserThread::PostTask(
   4074       BrowserThread::IO, FROM_HERE,
   4075       base::Bind(&CreateCountingInterceptorOnIO,
   4076                  kTestURL, test_file, counter.AsWeakPtr()));
   4077 
   4078   PrerenderTestURL(kTestURL, FINAL_STATUS_USED, 1);
   4079 
   4080   // Open a new tab to navigate in.
   4081   ui_test_utils::NavigateToURLWithDisposition(
   4082       current_browser(), kInitURL, NEW_FOREGROUND_TAB,
   4083       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   4084 
   4085   // Now navigate in the new tab. Set expect_swap_to_succeed to false because
   4086   // the swap does not occur synchronously.
   4087   //
   4088   // TODO(davidben): When all swaps become asynchronous, remove the OpenURL
   4089   // return value assertion and let this go through the usual successful-swap
   4090   // codepath.
   4091   NavigateToDestURLWithDisposition(CURRENT_TAB, false);
   4092 
   4093   // Verify DidDisplayPass manually since the previous call skipped it.
   4094   EXPECT_TRUE(DidDisplayPass(
   4095       current_browser()->tab_strip_model()->GetActiveWebContents()));
   4096 
   4097   // Only one request to the test URL started.
   4098   //
   4099   // TODO(davidben): Re-enable this check when the races in attaching the
   4100   // throttle are resolved. http://crbug.com/335835
   4101   // EXPECT_EQ(1, counter.count());
   4102 }
   4103 
   4104 // Attempt a swap-in in a new tab, verifying that session storage namespace
   4105 // merging works. Unlike the above test, the swap is for a navigation that would
   4106 // normally be cross-process.
   4107 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageNewTabCrossProcess) {
   4108   base::FilePath test_data_dir;
   4109   ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
   4110 
   4111   // Mock out some URLs and count the number of requests to one of them. Both
   4112   // prerender_session_storage.html and init_session_storage.html need to be
   4113   // mocked so they are same-origin.
   4114   const GURL kInitURL("http://prerender.test/init_session_storage.html");
   4115   base::FilePath init_file = GetTestPath("init_session_storage.html");
   4116   BrowserThread::PostTask(
   4117       BrowserThread::IO, FROM_HERE,
   4118       base::Bind(&CreateMockInterceptorOnIO, kInitURL, init_file));
   4119 
   4120   const GURL kTestURL("http://prerender.test/prerender_session_storage.html");
   4121   base::FilePath test_file = GetTestPath("prerender_session_storage.html");
   4122   RequestCounter counter;
   4123   BrowserThread::PostTask(
   4124       BrowserThread::IO, FROM_HERE,
   4125       base::Bind(&CreateCountingInterceptorOnIO,
   4126                  kTestURL, test_file, counter.AsWeakPtr()));
   4127 
   4128   PrerenderTestURL(kTestURL, FINAL_STATUS_USED, 1);
   4129 
   4130   // Open a new tab to navigate in.
   4131   ui_test_utils::NavigateToURLWithDisposition(
   4132       current_browser(), kInitURL, NEW_FOREGROUND_TAB,
   4133       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   4134 
   4135   // Navigate to about:blank so the next navigation is cross-process.
   4136   ui_test_utils::NavigateToURL(current_browser(), GURL(url::kAboutBlankURL));
   4137 
   4138   // Now navigate in the new tab. Set expect_swap_to_succeed to false because
   4139   // the swap does not occur synchronously.
   4140   //
   4141   // TODO(davidben): When all swaps become asynchronous, remove the OpenURL
   4142   // return value assertion and let this go through the usual successful-swap
   4143   // codepath.
   4144   NavigateToDestURLWithDisposition(CURRENT_TAB, false);
   4145 
   4146   // Verify DidDisplayPass manually since the previous call skipped it.
   4147   EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
   4148 
   4149   // Only one request to the test URL started.
   4150   //
   4151   // TODO(davidben): Re-enable this check when the races in attaching the
   4152   // throttle are resolved. http://crbug.com/335835
   4153   // EXPECT_EQ(1, counter.count());
   4154 }
   4155 
   4156 // Verify that session storage conflicts don't merge.
   4157 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSessionStorageConflict) {
   4158   PrerenderTestURL("files/prerender/prerender_session_storage_conflict.html",
   4159                    FINAL_STATUS_APP_TERMINATING, 1);
   4160 
   4161   // Open a new tab to navigate in.
   4162   ui_test_utils::NavigateToURLWithDisposition(
   4163       current_browser(),
   4164       test_server()->GetURL("files/prerender/init_session_storage.html"),
   4165       NEW_FOREGROUND_TAB,
   4166       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   4167 
   4168   // Now navigate in the new tab.
   4169   NavigateToDestURLWithDisposition(CURRENT_TAB, false);
   4170 
   4171   // Verify DidDisplayPass in the new tab.
   4172   EXPECT_TRUE(DidDisplayPass(GetActiveWebContents()));
   4173 }
   4174 
   4175 // Checks that prerenders honor |should_replace_current_entry|.
   4176 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReplaceCurrentEntry) {
   4177   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   4178 
   4179   content::OpenURLParams params(dest_url(), Referrer(), CURRENT_TAB,
   4180                                 ui::PAGE_TRANSITION_TYPED, false);
   4181   params.should_replace_current_entry = true;
   4182   NavigateToURLWithParams(params, false);
   4183 
   4184   const NavigationController& controller =
   4185       GetActiveWebContents()->GetController();
   4186   // First entry is about:blank, second is prerender_page.html.
   4187   EXPECT_TRUE(controller.GetPendingEntry() == NULL);
   4188   EXPECT_EQ(2, controller.GetEntryCount());
   4189   EXPECT_EQ(GURL(url::kAboutBlankURL), controller.GetEntryAtIndex(0)->GetURL());
   4190   EXPECT_EQ(dest_url(), controller.GetEntryAtIndex(1)->GetURL());
   4191 }
   4192 
   4193 // Checks prerender does not hit DCHECKs and behaves properly if two pending
   4194 // swaps occur in a row.
   4195 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDoublePendingSwap) {
   4196   GetPrerenderManager()->mutable_config().max_link_concurrency = 2;
   4197   GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2;
   4198 
   4199   GURL url1 = test_server()->GetURL("files/prerender/prerender_page.html?1");
   4200   scoped_ptr<TestPrerender> prerender1 =
   4201       PrerenderTestURL(url1, FINAL_STATUS_APP_TERMINATING, 1);
   4202 
   4203   GURL url2 = test_server()->GetURL("files/prerender/prerender_page.html?2");
   4204   scoped_ptr<TestPrerender> prerender2 = ExpectPrerender(FINAL_STATUS_USED);
   4205   AddPrerender(url2, 1);
   4206   prerender2->WaitForStart();
   4207   prerender2->WaitForLoads(1);
   4208 
   4209   // There's no reason the second prerender can't be used, but the swap races
   4210   // with didStartProvisionalLoad and didFailProvisionalLoad from the previous
   4211   // navigation. The current logic will conservatively fail to swap under such
   4212   // races. However, if the renderer is slow enough, it's possible for the
   4213   // prerender to still be used, so don't program in either expectation.
   4214   ASSERT_TRUE(prerender2->contents());
   4215   prerender2->contents()->set_skip_final_checks(true);
   4216 
   4217   // Open a new tab to navigate in.
   4218   ui_test_utils::NavigateToURLWithDisposition(
   4219       current_browser(),
   4220       GURL(url::kAboutBlankURL),
   4221       NEW_FOREGROUND_TAB,
   4222       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   4223 
   4224   // Fire off two navigations, without running the event loop between them.
   4225   NavigationOrSwapObserver swap_observer(
   4226       current_browser()->tab_strip_model(),
   4227       GetActiveWebContents(), 2);
   4228   current_browser()->OpenURL(OpenURLParams(
   4229       url1, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
   4230   current_browser()->OpenURL(OpenURLParams(
   4231       url2, Referrer(), CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false));
   4232   swap_observer.Wait();
   4233 
   4234   // The WebContents should be on url2. There may be 2 or 3 entries, depending
   4235   // on whether the first one managed to complete.
   4236   //
   4237   // TODO(davidben): When http://crbug.com/335835 is fixed, the 3 entry case
   4238   // shouldn't be possible because it's throttled by the pending swap that
   4239   // cannot complete.
   4240   const NavigationController& controller =
   4241       GetActiveWebContents()->GetController();
   4242   EXPECT_TRUE(controller.GetPendingEntry() == NULL);
   4243   EXPECT_LE(2, controller.GetEntryCount());
   4244   EXPECT_GE(3, controller.GetEntryCount());
   4245   EXPECT_EQ(GURL(url::kAboutBlankURL), controller.GetEntryAtIndex(0)->GetURL());
   4246   EXPECT_EQ(url2, controller.GetEntryAtIndex(
   4247       controller.GetEntryCount() - 1)->GetURL());
   4248 }
   4249 
   4250 // Verify that pending swaps get aborted on new navigations.
   4251 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   4252                        PrerenderPendingSwapNewNavigation) {
   4253   PrerenderManager::HangSessionStorageMergesForTesting();
   4254 
   4255   PrerenderTestURL("files/prerender/prerender_page.html",
   4256                    FINAL_STATUS_APP_TERMINATING, 1);
   4257 
   4258   // Open a new tab to navigate in.
   4259   ui_test_utils::NavigateToURLWithDisposition(
   4260       current_browser(),
   4261       GURL(url::kAboutBlankURL),
   4262       NEW_FOREGROUND_TAB,
   4263       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
   4264 
   4265   // Navigate to the URL. Wait for DidStartLoading, just so it's definitely
   4266   // progressed somewhere.
   4267   content::WindowedNotificationObserver page_load_observer(
   4268       content::NOTIFICATION_LOAD_START,
   4269       content::Source<NavigationController>(
   4270           &GetActiveWebContents()->GetController()));
   4271   current_browser()->OpenURL(OpenURLParams(
   4272       dest_url(), Referrer(), CURRENT_TAB,
   4273       ui::PAGE_TRANSITION_TYPED, false));
   4274   page_load_observer.Wait();
   4275 
   4276   // Navigate somewhere else. This should succeed and abort the pending swap.
   4277   TestNavigationObserver nav_observer(GetActiveWebContents());
   4278   current_browser()->OpenURL(OpenURLParams(GURL(url::kAboutBlankURL),
   4279                                            Referrer(),
   4280                                            CURRENT_TAB,
   4281                                            ui::PAGE_TRANSITION_TYPED,
   4282                                            false));
   4283   nav_observer.Wait();
   4284 }
   4285 
   4286 // Checks that <a ping> requests are not dropped in prerender.
   4287 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPing) {
   4288   // Count hits to a certain URL.
   4289   const GURL kPingURL("http://prerender.test/ping");
   4290   base::FilePath empty_file = ui_test_utils::GetTestFilePath(
   4291       base::FilePath(), base::FilePath(FILE_PATH_LITERAL("empty.html")));
   4292   RequestCounter ping_counter;
   4293   BrowserThread::PostTask(
   4294       BrowserThread::IO, FROM_HERE,
   4295       base::Bind(&CreateCountingInterceptorOnIO,
   4296                  kPingURL, empty_file, ping_counter.AsWeakPtr()));
   4297 
   4298   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   4299   OpenDestURLViaClickPing(kPingURL);
   4300 
   4301   ping_counter.WaitForCount(1);
   4302 }
   4303 
   4304 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPPLTNormalNavigation) {
   4305   GURL url = test_server()->GetURL("files/prerender/prerender_page.html");
   4306   ui_test_utils::NavigateToURL(current_browser(), url);
   4307   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLT", 1);
   4308   histogram_tester().ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0);
   4309   histogram_tester().ExpectTotalCount(
   4310       "Prerender.none_PerceivedPLTMatchedComplete", 0);
   4311 }
   4312 
   4313 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   4314                        PrerenderCookieChangeConflictTest) {
   4315   NavigateStraightToURL(
   4316       "files/prerender/prerender_cookie.html?set=1&key=c&value=1");
   4317 
   4318   GURL url = test_server()->GetURL(
   4319       "files/prerender/prerender_cookie.html?set=1&key=c&value=2");
   4320 
   4321   scoped_ptr<TestPrerender> prerender =
   4322       ExpectPrerender(FINAL_STATUS_COOKIE_CONFLICT);
   4323   AddPrerender(url, 1);
   4324   prerender->WaitForStart();
   4325   prerender->WaitForLoads(1);
   4326   // Ensure that in the prerendered page, querying the cookie again
   4327   // via javascript yields the same value that was set during load.
   4328   EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents()));
   4329 
   4330   // The prerender has loaded. Ensure that the change is not visible
   4331   // to visible tabs.
   4332   std::string value;
   4333   RunJSReturningString("GetCookie('c')", &value);
   4334   ASSERT_EQ(value, "1");
   4335 
   4336   // Make a conflicting cookie change, which should cancel the prerender.
   4337   RunJS("SetCookie('c', '3')");
   4338   prerender->WaitForStop();
   4339 }
   4340 
   4341 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCookieChangeUseTest) {
   4342   // Permit 2 concurrent prerenders.
   4343   GetPrerenderManager()->mutable_config().max_link_concurrency = 2;
   4344   GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2;
   4345 
   4346   // Go to a first URL setting the cookie to value "1".
   4347   NavigateStraightToURL(
   4348       "files/prerender/prerender_cookie.html?set=1&key=c&value=1");
   4349 
   4350   // Prerender a URL setting the cookie to value "2".
   4351   GURL url = test_server()->GetURL(
   4352       "files/prerender/prerender_cookie.html?set=1&key=c&value=2");
   4353 
   4354   scoped_ptr<TestPrerender> prerender1 = ExpectPrerender(FINAL_STATUS_USED);
   4355   AddPrerender(url, 1);
   4356   prerender1->WaitForStart();
   4357   prerender1->WaitForLoads(1);
   4358 
   4359   // Launch a second prerender, setting the cookie to value "3".
   4360   scoped_ptr<TestPrerender> prerender2 =
   4361       ExpectPrerender(FINAL_STATUS_COOKIE_CONFLICT);
   4362   AddPrerender(test_server()->GetURL(
   4363       "files/prerender/prerender_cookie.html?set=1&key=c&value=3"), 1);
   4364   prerender2->WaitForStart();
   4365   prerender2->WaitForLoads(1);
   4366 
   4367   // Both prerenders have loaded. Ensure that the visible tab is still
   4368   // unchanged and cannot see their changes.
   4369   // to visible tabs.
   4370   std::string value;
   4371   RunJSReturningString("GetCookie('c')", &value);
   4372   ASSERT_EQ(value, "1");
   4373 
   4374   // Navigate to the prerendered URL. The first prerender should be swapped in,
   4375   // and the changes should now be visible. The second prerender should
   4376   // be cancelled due to the conflict.
   4377   ui_test_utils::NavigateToURLWithDisposition(
   4378       current_browser(),
   4379       url,
   4380       CURRENT_TAB,
   4381       ui_test_utils::BROWSER_TEST_NONE);
   4382   RunJSReturningString("GetCookie('c')", &value);
   4383   ASSERT_EQ(value, "2");
   4384   prerender2->WaitForStop();
   4385 }
   4386 
   4387 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   4388                        PrerenderCookieChangeConflictHTTPHeaderTest) {
   4389   NavigateStraightToURL(
   4390       "files/prerender/prerender_cookie.html?set=1&key=c&value=1");
   4391 
   4392   GURL url = test_server()->GetURL("set-cookie?c=2");
   4393   scoped_ptr<TestPrerender> prerender =
   4394       ExpectPrerender(FINAL_STATUS_COOKIE_CONFLICT);
   4395   AddPrerender(url, 1);
   4396   prerender->WaitForStart();
   4397   prerender->WaitForLoads(1);
   4398 
   4399   // The prerender has loaded. Ensure that the change is not visible
   4400   // to visible tabs.
   4401   std::string value;
   4402   RunJSReturningString("GetCookie('c')", &value);
   4403   ASSERT_EQ(value, "1");
   4404 
   4405   // Make a conflicting cookie change, which should cancel the prerender.
   4406   RunJS("SetCookie('c', '3')");
   4407   prerender->WaitForStop();
   4408 }
   4409 
   4410 // Checks that a prerender which calls window.close() on itself is aborted.
   4411 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderWindowClose) {
   4412   DisableLoadEventCheck();
   4413   PrerenderTestURL("files/prerender/prerender_window_close.html",
   4414                    FINAL_STATUS_CLOSED, 0);
   4415 }
   4416 
   4417 class PrerenderIncognitoBrowserTest : public PrerenderBrowserTest {
   4418  public:
   4419   virtual void SetUpOnMainThread() OVERRIDE {
   4420     Profile* normal_profile = current_browser()->profile();
   4421     set_browser(ui_test_utils::OpenURLOffTheRecord(
   4422         normal_profile, GURL("about:blank")));
   4423     PrerenderBrowserTest::SetUpOnMainThread();
   4424   }
   4425 };
   4426 
   4427 // Checks that prerendering works in incognito mode.
   4428 IN_PROC_BROWSER_TEST_F(PrerenderIncognitoBrowserTest, PrerenderIncognito) {
   4429   PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
   4430   NavigateToDestURL();
   4431 }
   4432 
   4433 // Checks that prerenders are aborted when an incognito profile is closed.
   4434 IN_PROC_BROWSER_TEST_F(PrerenderIncognitoBrowserTest,
   4435                        PrerenderIncognitoClosed) {
   4436   scoped_ptr<TestPrerender> prerender =
   4437       PrerenderTestURL("files/prerender/prerender_page.html",
   4438                        FINAL_STATUS_PROFILE_DESTROYED, 1);
   4439   current_browser()->window()->Close();
   4440   prerender->WaitForStop();
   4441 }
   4442 
   4443 class PrerenderOmniboxBrowserTest : public PrerenderBrowserTest {
   4444  public:
   4445   LocationBar* GetLocationBar() {
   4446     return current_browser()->window()->GetLocationBar();
   4447   }
   4448 
   4449   OmniboxView* GetOmniboxView() {
   4450     return GetLocationBar()->GetOmniboxView();
   4451   }
   4452 
   4453   void WaitForAutocompleteDone(OmniboxView* omnibox_view) {
   4454     AutocompleteController* controller =
   4455         omnibox_view->model()->popup_model()->autocomplete_controller();
   4456     while (!controller->done()) {
   4457       content::WindowedNotificationObserver ready_observer(
   4458           chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY,
   4459           content::Source<AutocompleteController>(controller));
   4460       ready_observer.Wait();
   4461     }
   4462   }
   4463 
   4464   predictors::AutocompleteActionPredictor* GetAutocompleteActionPredictor() {
   4465     Profile* profile = current_browser()->profile();
   4466     return predictors::AutocompleteActionPredictorFactory::GetForProfile(
   4467         profile);
   4468   }
   4469 
   4470   scoped_ptr<TestPrerender> StartOmniboxPrerender(
   4471       const GURL& url,
   4472       FinalStatus expected_final_status) {
   4473     scoped_ptr<TestPrerender> prerender =
   4474         ExpectPrerender(expected_final_status);
   4475     WebContents* web_contents = GetActiveWebContents();
   4476     GetAutocompleteActionPredictor()->StartPrerendering(
   4477         url,
   4478         web_contents->GetController().GetSessionStorageNamespaceMap(),
   4479         gfx::Size(50, 50));
   4480     prerender->WaitForStart();
   4481     return prerender.Pass();
   4482   }
   4483 };
   4484 
   4485 // Checks that closing the omnibox popup cancels an omnibox prerender.
   4486 // http://crbug.com/395152
   4487 IN_PROC_BROWSER_TEST_F(PrerenderOmniboxBrowserTest,
   4488                        DISABLED_PrerenderOmniboxCancel) {
   4489   // Ensure the cookie store has been loaded.
   4490   if (!GetPrerenderManager()->cookie_store_loaded()) {
   4491     base::RunLoop loop;
   4492     GetPrerenderManager()->set_on_cookie_store_loaded_cb_for_testing(
   4493         loop.QuitClosure());
   4494     loop.Run();
   4495   }
   4496 
   4497   // Fake an omnibox prerender.
   4498   scoped_ptr<TestPrerender> prerender = StartOmniboxPrerender(
   4499       test_server()->GetURL("files/empty.html"),
   4500       FINAL_STATUS_CANCELLED);
   4501 
   4502   // Revert the location bar. This should cancel the prerender.
   4503   GetLocationBar()->Revert();
   4504   prerender->WaitForStop();
   4505 }
   4506 
   4507 // Checks that accepting omnibox input abandons an omnibox prerender.
   4508 // http://crbug.com/394592
   4509 IN_PROC_BROWSER_TEST_F(PrerenderOmniboxBrowserTest,
   4510                        DISABLED_PrerenderOmniboxAbandon) {
   4511   // Set the abandon timeout to something high so it does not introduce
   4512   // flakiness if the prerender times out before the test completes.
   4513   GetPrerenderManager()->mutable_config().abandon_time_to_live =
   4514       base::TimeDelta::FromDays(999);
   4515 
   4516   // Ensure the cookie store has been loaded.
   4517   if (!GetPrerenderManager()->cookie_store_loaded()) {
   4518     base::RunLoop loop;
   4519     GetPrerenderManager()->set_on_cookie_store_loaded_cb_for_testing(
   4520         loop.QuitClosure());
   4521     loop.Run();
   4522   }
   4523 
   4524   // Enter a URL into the Omnibox.
   4525   OmniboxView* omnibox_view = GetOmniboxView();
   4526   omnibox_view->OnBeforePossibleChange();
   4527   omnibox_view->SetUserText(
   4528       base::UTF8ToUTF16(test_server()->GetURL("files/empty.html?1").spec()));
   4529   omnibox_view->OnAfterPossibleChange();
   4530   WaitForAutocompleteDone(omnibox_view);
   4531 
   4532   // Fake an omnibox prerender for a different URL.
   4533   scoped_ptr<TestPrerender> prerender = StartOmniboxPrerender(
   4534       test_server()->GetURL("files/empty.html?2"),
   4535       FINAL_STATUS_APP_TERMINATING);
   4536 
   4537   // The final status may be either FINAL_STATUS_APP_TERMINATING or
   4538   // FINAL_STATUS_CANCELLED. Although closing the omnibox will not cancel an
   4539   // abandoned prerender, the AutocompleteActionPredictor will cancel the
   4540   // predictor on destruction.
   4541   prerender->contents()->set_skip_final_checks(true);
   4542 
   4543   // Navigate to the URL entered.
   4544   omnibox_view->model()->AcceptInput(CURRENT_TAB, false);
   4545 
   4546   // Prerender should be running, but abandoned.
   4547   EXPECT_TRUE(
   4548       GetAutocompleteActionPredictor()->IsPrerenderAbandonedForTesting());
   4549 }
   4550 
   4551 // Prefetch should be allowed depending on preference and network type.
   4552 // This test is for the bsae case: no Finch overrides should never disable.
   4553 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   4554                        LocalPredictorDisableWorksBaseCase) {
   4555   TestShouldDisableLocalPredictorPreferenceNetworkMatrix(
   4556       false /*preference_wifi_network_wifi*/,
   4557       false /*preference_wifi_network_4g*/,
   4558       false /*preference_always_network_wifi*/,
   4559       false /*preference_always_network_4g*/,
   4560       false /*preference_never_network_wifi*/,
   4561       false /*preference_never_network_4g*/);
   4562 }
   4563 
   4564 // Prefetch should be allowed depending on preference and network type.
   4565 // LocalPredictorOnCellularOnly should disable all wifi cases.
   4566 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   4567                        LocalPredictorDisableWorksCellularOnly) {
   4568   CreateTestFieldTrial("PrerenderLocalPredictorSpec",
   4569                        "LocalPredictorOnCellularOnly=Enabled");
   4570   TestShouldDisableLocalPredictorPreferenceNetworkMatrix(
   4571       true /*preference_wifi_network_wifi*/,
   4572       false /*preference_wifi_network_4g*/,
   4573       true /*preference_always_network_wifi*/,
   4574       false /*preference_always_network_4g*/,
   4575       true /*preference_never_network_wifi*/,
   4576       false /*preference_never_network_4g*/);
   4577 }
   4578 
   4579 // Prefetch should be allowed depending on preference and network type.
   4580 // LocalPredictorNetworkPredictionEnabledOnly should disable whenever
   4581 // network predictions will not be exercised.
   4582 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   4583                        LocalPredictorDisableWorksNetworkPredictionEnableOnly) {
   4584   CreateTestFieldTrial("PrerenderLocalPredictorSpec",
   4585                        "LocalPredictorNetworkPredictionEnabledOnly=Enabled");
   4586   TestShouldDisableLocalPredictorPreferenceNetworkMatrix(
   4587       false /*preference_wifi_network_wifi*/,
   4588       true /*preference_wifi_network_4g*/,
   4589       false /*preference_always_network_wifi*/,
   4590       false /*preference_always_network_4g*/,
   4591       true /*preference_never_network_wifi*/,
   4592       true /*preference_never_network_4g*/);
   4593 }
   4594 
   4595 // Prefetch should be allowed depending on preference and network type.
   4596 // If LocalPredictorNetworkPredictionEnabledOnly and
   4597 // LocalPredictorOnCellularOnly are both selected, we must disable whenever
   4598 // network predictions are not exercised, or when we are on wifi.
   4599 IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
   4600                        LocalPredictorDisableWorksBothOptions) {
   4601   CreateTestFieldTrial("PrerenderLocalPredictorSpec",
   4602                        "LocalPredictorOnCellularOnly=Enabled:"
   4603                        "LocalPredictorNetworkPredictionEnabledOnly=Enabled");
   4604   TestShouldDisableLocalPredictorPreferenceNetworkMatrix(
   4605       true /*preference_wifi_network_wifi*/,
   4606       true /*preference_wifi_network_4g*/,
   4607       true /*preference_always_network_wifi*/,
   4608       false /*preference_always_network_4g*/,
   4609       true /*preference_never_network_wifi*/,
   4610       true /*preference_never_network_4g*/);
   4611 }
   4612 
   4613 }  // namespace prerender
   4614