prerender_browsertest.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/command_line.h"
9#include "base/path_service.h"
10#include "base/prefs/pref_service.h"
11#include "base/string_util.h"
12#include "base/stringprintf.h"
13#include "base/test/test_timeouts.h"
14#include "base/utf_string_conversions.h"
15#include "base/values.h"
16#include "chrome/browser/browsing_data/browsing_data_helper.h"
17#include "chrome/browser/browsing_data/browsing_data_remover.h"
18#include "chrome/browser/content_settings/host_content_settings_map.h"
19#include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
20#include "chrome/browser/extensions/extension_apitest.h"
21#include "chrome/browser/favicon/favicon_tab_helper.h"
22#include "chrome/browser/prerender/prerender_contents.h"
23#include "chrome/browser/prerender/prerender_handle.h"
24#include "chrome/browser/prerender/prerender_link_manager.h"
25#include "chrome/browser/prerender/prerender_link_manager_factory.h"
26#include "chrome/browser/prerender/prerender_manager.h"
27#include "chrome/browser/prerender/prerender_manager_factory.h"
28#include "chrome/browser/profiles/profile.h"
29#include "chrome/browser/safe_browsing/database_manager.h"
30#include "chrome/browser/safe_browsing/safe_browsing_service.h"
31#include "chrome/browser/safe_browsing/safe_browsing_util.h"
32#include "chrome/browser/task_manager/task_manager.h"
33#include "chrome/browser/task_manager/task_manager_browsertest_util.h"
34#include "chrome/browser/ui/browser.h"
35#include "chrome/browser/ui/browser_commands.h"
36#include "chrome/browser/ui/browser_finder.h"
37#include "chrome/browser/ui/browser_window.h"
38#include "chrome/browser/ui/tabs/tab_strip_model.h"
39#include "chrome/common/chrome_notification_types.h"
40#include "chrome/common/chrome_paths.h"
41#include "chrome/common/chrome_switches.h"
42#include "chrome/common/pref_names.h"
43#include "chrome/test/base/in_process_browser_test.h"
44#include "chrome/test/base/ui_test_utils.h"
45#include "content/public/browser/browser_message_filter.h"
46#include "content/public/browser/devtools_agent_host.h"
47#include "content/public/browser/devtools_client_host.h"
48#include "content/public/browser/devtools_manager.h"
49#include "content/public/browser/notification_service.h"
50#include "content/public/browser/render_process_host.h"
51#include "content/public/browser/render_view_host.h"
52#include "content/public/browser/web_contents.h"
53#include "content/public/common/url_constants.h"
54#include "content/public/test/browser_test_utils.h"
55#include "content/public/test/test_navigation_observer.h"
56#include "content/public/test/test_utils.h"
57#include "googleurl/src/gurl.h"
58#include "grit/generated_resources.h"
59#include "net/dns/mock_host_resolver.h"
60#include "net/url_request/url_request_context.h"
61#include "net/url_request/url_request_context_getter.h"
62#include "ui/base/l10n/l10n_util.h"
63
64using content::BrowserThread;
65using content::DevToolsAgentHost;
66using content::DevToolsClientHost;
67using content::DevToolsManager;
68using content::NavigationController;
69using content::OpenURLParams;
70using content::Referrer;
71using content::RenderViewHost;
72using content::RenderWidgetHost;
73using content::WebContents;
74
75// Prerender tests work as follows:
76//
77// A page with a prefetch link to the test page is loaded.  Once prerendered,
78// its Javascript function DidPrerenderPass() is called, which returns true if
79// the page behaves as expected when prerendered.
80//
81// The prerendered page is then displayed on a tab.  The Javascript function
82// DidDisplayPass() is called, and returns true if the page behaved as it
83// should while being displayed.
84
85namespace prerender {
86
87namespace {
88
89// Constants used in the test HTML files.
90static const char* kReadyTitle = "READY";
91static const char* kPassTitle = "PASS";
92
93std::string CreateClientRedirect(const std::string& dest_url) {
94  const char* const kClientRedirectBase = "client-redirect?";
95  return kClientRedirectBase + dest_url;
96}
97
98std::string CreateServerRedirect(const std::string& dest_url) {
99  const char* const kServerRedirectBase = "server-redirect?";
100  return kServerRedirectBase + dest_url;
101}
102
103// Clears the specified data using BrowsingDataRemover.
104void ClearBrowsingData(Browser* browser, int remove_mask) {
105  BrowsingDataRemover* remover =
106      BrowsingDataRemover::CreateForUnboundedRange(browser->profile());
107  remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
108  // BrowsingDataRemover deletes itself.
109}
110
111void CancelAllPrerenders(PrerenderManager* prerender_manager) {
112  prerender_manager->CancelAllPrerenders();
113}
114
115// Returns true if and only if the final status is one in which the prerendered
116// page should prerender correctly. The page still may not be used.
117bool ShouldRenderPrerenderedPageCorrectly(FinalStatus status) {
118  switch (status) {
119    case FINAL_STATUS_USED:
120    case FINAL_STATUS_WINDOW_OPENER:
121    case FINAL_STATUS_APP_TERMINATING:
122    case FINAL_STATUS_CACHE_OR_HISTORY_CLEARED:
123    // We'll crash the renderer after it's loaded.
124    case FINAL_STATUS_RENDERER_CRASHED:
125    case FINAL_STATUS_CANCELLED:
126    case FINAL_STATUS_DEVTOOLS_ATTACHED:
127      return true;
128    default:
129      return false;
130  }
131}
132
133// Waits for the destruction of a RenderProcessHost's IPC channel.
134// Used to make sure the PrerenderLinkManager's OnChannelClosed function has
135// been called, before checking its state.
136class ChannelDestructionWatcher {
137 public:
138  ChannelDestructionWatcher() : channel_destroyed_(false),
139                                waiting_for_channel_destruction_(false) {
140  }
141
142  ~ChannelDestructionWatcher() {
143  }
144
145  void WatchChannel(content::RenderProcessHost* host) {
146    host->GetChannel()->AddFilter(new DestructionMessageFilter(this));
147  }
148
149  void WaitForChannelClose() {
150    ASSERT_FALSE(waiting_for_channel_destruction_);
151
152    if (channel_destroyed_)
153      return;
154    waiting_for_channel_destruction_ = true;
155    content::RunMessageLoop();
156
157    EXPECT_FALSE(waiting_for_channel_destruction_);
158    EXPECT_TRUE(channel_destroyed_);
159  }
160
161 private:
162  // When destroyed, calls ChannelDestructionWatcher::OnChannelDestroyed.
163  // Ignores all messages.
164  class DestructionMessageFilter : public content::BrowserMessageFilter {
165   public:
166     explicit DestructionMessageFilter(ChannelDestructionWatcher* watcher)
167         : watcher_(watcher) {
168    }
169
170   private:
171    virtual ~DestructionMessageFilter() {
172      content::BrowserThread::PostTask(
173          content::BrowserThread::UI, FROM_HERE,
174          base::Bind(&ChannelDestructionWatcher::OnChannelDestroyed,
175                     base::Unretained(watcher_)));
176    }
177
178    virtual bool OnMessageReceived(const IPC::Message& message,
179                                   bool* message_was_ok) OVERRIDE {
180      return false;
181    }
182
183    ChannelDestructionWatcher* watcher_;
184
185    DISALLOW_COPY_AND_ASSIGN(DestructionMessageFilter);
186  };
187
188  void OnChannelDestroyed() {
189    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
190
191    EXPECT_FALSE(channel_destroyed_);
192    channel_destroyed_ = true;
193    if (waiting_for_channel_destruction_) {
194      waiting_for_channel_destruction_ = false;
195      base::MessageLoop::current()->Quit();
196    }
197  }
198
199  bool channel_destroyed_;
200  bool waiting_for_channel_destruction_;
201
202  DISALLOW_COPY_AND_ASSIGN(ChannelDestructionWatcher);
203};
204
205// PrerenderContents that stops the UI message loop on DidStopLoading().
206class TestPrerenderContents : public PrerenderContents {
207 public:
208  TestPrerenderContents(
209      PrerenderManager* prerender_manager,
210      Profile* profile,
211      const GURL& url,
212      const content::Referrer& referrer,
213      Origin origin,
214      int expected_number_of_loads,
215      FinalStatus expected_final_status,
216      bool prerender_should_wait_for_ready_title)
217      : PrerenderContents(prerender_manager, profile, url,
218                          referrer, origin, PrerenderManager::kNoExperiment),
219        number_of_loads_(0),
220        expected_number_of_loads_(expected_number_of_loads),
221        expected_final_status_(expected_final_status),
222        new_render_view_host_(NULL),
223        was_hidden_(false),
224        was_shown_(false),
225        should_be_shown_(expected_final_status == FINAL_STATUS_USED),
226        quit_message_loop_on_destruction_(
227            expected_final_status != FINAL_STATUS_APP_TERMINATING &&
228            expected_final_status != FINAL_STATUS_MAX),
229        expected_pending_prerenders_(0),
230        prerender_should_wait_for_ready_title_(
231            prerender_should_wait_for_ready_title) {
232    if (expected_number_of_loads == 0)
233      base::MessageLoopForUI::current()->Quit();
234  }
235
236  virtual ~TestPrerenderContents() {
237    if (expected_final_status_ == FINAL_STATUS_MAX) {
238      EXPECT_EQ(match_complete_status(), MATCH_COMPLETE_REPLACEMENT);
239    } else {
240      EXPECT_EQ(expected_final_status_, final_status()) <<
241          " when testing URL " << prerender_url().path() <<
242          " (Expected: " << NameFromFinalStatus(expected_final_status_) <<
243          ", Actual: " << NameFromFinalStatus(final_status()) << ")";
244    }
245    // Prerendering RenderViewHosts should be hidden before the first
246    // navigation, so this should be happen for every PrerenderContents for
247    // which a RenderViewHost is created, regardless of whether or not it's
248    // used.
249    if (new_render_view_host_)
250      EXPECT_TRUE(was_hidden_);
251
252    // A used PrerenderContents will only be destroyed when we swap out
253    // WebContents, at the end of a navigation caused by a call to
254    // NavigateToURLImpl().
255    if (final_status() == FINAL_STATUS_USED)
256      EXPECT_TRUE(new_render_view_host_);
257
258    EXPECT_EQ(should_be_shown_, was_shown_);
259
260    // When the PrerenderContents is destroyed, quit the UI message loop.
261    // This happens on navigation to used prerendered pages, and soon
262    // after cancellation of unused prerendered pages.
263    if (quit_message_loop_on_destruction_) {
264      // The message loop may not be running if this is swapped in
265      // synchronously on a Navigation.
266      base::MessageLoop* loop = base::MessageLoopForUI::current();
267      if (loop->is_running())
268        loop->Quit();
269    }
270  }
271
272  virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE {
273    // On quit, it's possible to end up here when render processes are closed
274    // before the PrerenderManager is destroyed.  As a result, it's possible to
275    // get either FINAL_STATUS_APP_TERMINATING or FINAL_STATUS_RENDERER_CRASHED
276    // on quit.
277    //
278    // It's also possible for this to be called after we've been notified of
279    // app termination, but before we've been deleted, which is why the second
280    // check is needed.
281    if (expected_final_status_ == FINAL_STATUS_APP_TERMINATING &&
282        final_status() != expected_final_status_) {
283      expected_final_status_ = FINAL_STATUS_RENDERER_CRASHED;
284    }
285
286    PrerenderContents::RenderViewGone(status);
287  }
288
289  virtual bool AddAliasURL(const GURL& url) OVERRIDE {
290    // Prevent FINAL_STATUS_UNSUPPORTED_SCHEME when navigating to about:crash in
291    // the PrerenderRendererCrash test.
292    if (url.spec() != content::kChromeUICrashURL)
293      return PrerenderContents::AddAliasURL(url);
294    return true;
295  }
296
297  virtual void DidStopLoading(RenderViewHost* render_view_host) OVERRIDE {
298    PrerenderContents::DidStopLoading(render_view_host);
299    ++number_of_loads_;
300    if (ShouldRenderPrerenderedPageCorrectly(expected_final_status_) &&
301        number_of_loads_ == expected_number_of_loads_) {
302      base::MessageLoopForUI::current()->Quit();
303    }
304  }
305
306  virtual void AddPendingPrerender(
307      scoped_ptr<PendingPrerenderInfo> pending_prerender_info) OVERRIDE {
308    PrerenderContents::AddPendingPrerender(pending_prerender_info.Pass());
309    if (expected_pending_prerenders_ > 0 &&
310        pending_prerender_count() == expected_pending_prerenders_) {
311      base::MessageLoop::current()->Quit();
312    }
313  }
314
315  virtual WebContents* CreateWebContents(
316      content::SessionStorageNamespace* session_storage_namespace) OVERRIDE {
317    WebContents* web_contents = PrerenderContents::CreateWebContents(
318        session_storage_namespace);
319    string16 ready_title = ASCIIToUTF16(kReadyTitle);
320    if (prerender_should_wait_for_ready_title_)
321      ready_title_watcher_.reset(new content::TitleWatcher(
322          web_contents, ready_title));
323    return web_contents;
324  }
325
326  void WaitForPrerenderToHaveReadyTitleIfRequired() {
327    if (ready_title_watcher_.get()) {
328      string16 ready_title = ASCIIToUTF16(kReadyTitle);
329      ASSERT_EQ(ready_title, ready_title_watcher_->WaitAndGetTitle());
330    }
331  }
332
333  // Waits until the prerender has |expected_pending_prerenders| pending
334  // prerenders.
335  void WaitForPendingPrerenders(size_t expected_pending_prerenders) {
336    if (pending_prerender_count() < expected_pending_prerenders) {
337      expected_pending_prerenders_ = expected_pending_prerenders;
338      content::RunMessageLoop();
339      expected_pending_prerenders_ = 0;
340    }
341
342    EXPECT_EQ(expected_pending_prerenders, pending_prerender_count());
343  }
344
345  // For tests that open the prerender in a new background tab, the RenderView
346  // will not have been made visible when the PrerenderContents is destroyed
347  // even though it is used.
348  void set_should_be_shown(bool value) { should_be_shown_ = value; }
349
350  int number_of_loads() const { return number_of_loads_; }
351
352  FinalStatus expected_final_status() const { return expected_final_status_; }
353
354  bool quit_message_loop_on_destruction() const {
355    return quit_message_loop_on_destruction_;
356  }
357
358 private:
359  virtual void OnRenderViewHostCreated(
360      RenderViewHost* new_render_view_host) OVERRIDE {
361    // Used to make sure the RenderViewHost is hidden and, if used,
362    // subsequently shown.
363    notification_registrar().Add(
364        this,
365        content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
366        content::Source<RenderWidgetHost>(new_render_view_host));
367
368    new_render_view_host_ = new_render_view_host;
369
370    PrerenderContents::OnRenderViewHostCreated(new_render_view_host);
371  }
372
373  virtual void Observe(int type,
374                       const content::NotificationSource& source,
375                       const content::NotificationDetails& details) OVERRIDE {
376    if (type ==
377        content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED) {
378      EXPECT_EQ(new_render_view_host_,
379                content::Source<RenderWidgetHost>(source).ptr());
380      bool is_visible = *content::Details<bool>(details).ptr();
381
382      if (!is_visible) {
383        was_hidden_ = true;
384      } else if (is_visible && was_hidden_) {
385        // Once hidden, a prerendered RenderViewHost should only be shown after
386        // being removed from the PrerenderContents for display.
387        EXPECT_FALSE(GetRenderViewHost());
388        was_shown_ = true;
389      }
390      return;
391    }
392    PrerenderContents::Observe(type, source, details);
393  }
394
395  int number_of_loads_;
396  int expected_number_of_loads_;
397  FinalStatus expected_final_status_;
398
399  // The RenderViewHost created for the prerender, if any.
400  RenderViewHost* new_render_view_host_;
401  // Set to true when the prerendering RenderWidget is hidden.
402  bool was_hidden_;
403  // Set to true when the prerendering RenderWidget is shown, after having been
404  // hidden.
405  bool was_shown_;
406  // Expected final value of was_shown_.  Defaults to true for
407  // FINAL_STATUS_USED, and false otherwise.
408  bool should_be_shown_;
409
410  // If true, quits message loop on destruction of |this|.
411  bool quit_message_loop_on_destruction_;
412
413  // Total number of pending prerenders we're currently waiting for.  Zero
414  // indicates we currently aren't waiting for any.
415  size_t expected_pending_prerenders_;
416
417  // If true, before calling DidPrerenderPass, will wait for the title of the
418  // prerendered page to turn to "READY".
419  bool prerender_should_wait_for_ready_title_;
420  scoped_ptr<content::TitleWatcher> ready_title_watcher_;
421};
422
423// PrerenderManager that uses TestPrerenderContents.
424class WaitForLoadPrerenderContentsFactory : public PrerenderContents::Factory {
425 public:
426  WaitForLoadPrerenderContentsFactory(
427      int expected_number_of_loads,
428      const std::deque<FinalStatus>& expected_final_status_queue,
429      bool prerender_should_wait_for_ready_title)
430      : expected_number_of_loads_(expected_number_of_loads),
431        expected_final_status_queue_(expected_final_status_queue),
432        prerender_should_wait_for_ready_title_(
433            prerender_should_wait_for_ready_title) {
434    VLOG(1) << "Factory created with queue length " <<
435               expected_final_status_queue_.size();
436  }
437
438  virtual PrerenderContents* CreatePrerenderContents(
439      PrerenderManager* prerender_manager,
440      Profile* profile,
441      const GURL& url,
442      const content::Referrer& referrer,
443      Origin origin,
444      uint8 experiment_id) OVERRIDE {
445    FinalStatus expected_final_status = FINAL_STATUS_MAX;
446    if (!expected_final_status_queue_.empty()) {
447      expected_final_status = expected_final_status_queue_.front();
448      expected_final_status_queue_.pop_front();
449    }
450    VLOG(1) << "Creating prerender contents for " << url.path() <<
451               " with expected final status " << expected_final_status;
452    VLOG(1) << expected_final_status_queue_.size() << " left in the queue.";
453    return new TestPrerenderContents(prerender_manager,
454                                     profile, url, referrer, origin,
455                                     expected_number_of_loads_,
456                                     expected_final_status,
457                                     prerender_should_wait_for_ready_title_);
458  }
459
460 private:
461  int expected_number_of_loads_;
462  std::deque<FinalStatus> expected_final_status_queue_;
463  bool prerender_should_wait_for_ready_title_;
464};
465
466#if defined(FULL_SAFE_BROWSING)
467// A SafeBrowsingDatabaseManager implementation that returns a fixed result for
468// a given URL.
469class FakeSafeBrowsingDatabaseManager :  public SafeBrowsingDatabaseManager {
470 public:
471  explicit FakeSafeBrowsingDatabaseManager(SafeBrowsingService* service)
472      : SafeBrowsingDatabaseManager(service),
473        threat_type_(SB_THREAT_TYPE_SAFE) { }
474
475  // Called on the IO thread to check if the given url is safe or not.  If we
476  // can synchronously determine that the url is safe, CheckUrl returns true.
477  // Otherwise it returns false, and "client" is called asynchronously with the
478  // result when it is ready.
479  // Returns true, indicating a SAFE result, unless the URL is the fixed URL
480  // specified by the user, and the user-specified result is not SAFE
481  // (in which that result will be communicated back via a call into the
482  // client, and false will be returned).
483  // Overrides SafeBrowsingService::CheckBrowseUrl.
484  virtual bool CheckBrowseUrl(const GURL& gurl, Client* client) OVERRIDE {
485    if (gurl != url_ || threat_type_ == SB_THREAT_TYPE_SAFE)
486      return true;
487
488    BrowserThread::PostTask(
489        BrowserThread::IO, FROM_HERE,
490        base::Bind(&FakeSafeBrowsingDatabaseManager::OnCheckBrowseURLDone,
491                   this, gurl, client));
492    return false;
493  }
494
495  void SetThreatTypeForUrl(const GURL& url, SBThreatType threat_type) {
496    url_ = url;
497    threat_type_ = threat_type;
498  }
499
500 private:
501  virtual ~FakeSafeBrowsingDatabaseManager() {}
502
503  void OnCheckBrowseURLDone(const GURL& gurl, Client* client) {
504    SafeBrowsingDatabaseManager::SafeBrowsingCheck sb_check(
505        std::vector<GURL>(1, gurl),
506        std::vector<SBFullHash>(),
507        client,
508        safe_browsing_util::MALWARE);
509    sb_check.url_results[0] = threat_type_;
510    client->OnSafeBrowsingResult(sb_check);
511  }
512
513  GURL url_;
514  SBThreatType threat_type_;
515  DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingDatabaseManager);
516};
517
518class FakeSafeBrowsingService : public SafeBrowsingService {
519 public:
520  FakeSafeBrowsingService() { }
521
522  // Returned pointer has the same lifespan as the database_manager_ refcounted
523  // object.
524  FakeSafeBrowsingDatabaseManager* fake_database_manager() {
525    return fake_database_manager_;
526  }
527
528 protected:
529  virtual ~FakeSafeBrowsingService() { }
530
531  virtual SafeBrowsingDatabaseManager* CreateDatabaseManager() OVERRIDE {
532    fake_database_manager_ = new FakeSafeBrowsingDatabaseManager(this);
533    return fake_database_manager_;
534  }
535
536 private:
537  FakeSafeBrowsingDatabaseManager* fake_database_manager_;
538
539  DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
540};
541
542// Factory that creates FakeSafeBrowsingService instances.
543class TestSafeBrowsingServiceFactory : public SafeBrowsingServiceFactory {
544 public:
545  TestSafeBrowsingServiceFactory() :
546      most_recent_service_(NULL) { }
547  virtual ~TestSafeBrowsingServiceFactory() { }
548
549  virtual SafeBrowsingService* CreateSafeBrowsingService() OVERRIDE {
550    most_recent_service_ =  new FakeSafeBrowsingService();
551    return most_recent_service_;
552  }
553
554  FakeSafeBrowsingService* most_recent_service() const {
555    return most_recent_service_;
556  }
557
558 private:
559  FakeSafeBrowsingService* most_recent_service_;
560};
561#endif
562
563class FakeDevToolsClientHost : public DevToolsClientHost {
564 public:
565  FakeDevToolsClientHost() {}
566  virtual ~FakeDevToolsClientHost() {}
567  virtual void InspectedContentsClosing() OVERRIDE {}
568  virtual void DispatchOnInspectorFrontend(const std::string& msg) OVERRIDE {}
569  virtual void ReplacedWithAnotherClient() OVERRIDE {}
570};
571
572class RestorePrerenderMode {
573 public:
574  RestorePrerenderMode() : prev_mode_(PrerenderManager::GetMode()) {
575  }
576
577  ~RestorePrerenderMode() { PrerenderManager::SetMode(prev_mode_); }
578 private:
579  PrerenderManager::PrerenderManagerMode prev_mode_;
580};
581
582}  // namespace
583
584class PrerenderBrowserTest : virtual public InProcessBrowserTest {
585 public:
586  PrerenderBrowserTest()
587      : autostart_test_server_(true),
588        prerender_contents_factory_(NULL),
589#if defined(FULL_SAFE_BROWSING)
590        safe_browsing_factory_(new TestSafeBrowsingServiceFactory()),
591#endif
592        use_https_src_server_(false),
593        call_javascript_(true),
594        loader_path_("files/prerender/prerender_loader.html"),
595        explicitly_set_browser_(NULL) {}
596
597  virtual ~PrerenderBrowserTest() {}
598
599  content::SessionStorageNamespace* GetSessionStorageNamespace() const {
600    WebContents* web_contents =
601        current_browser()->tab_strip_model()->GetActiveWebContents();
602    if (!web_contents)
603      return NULL;
604    return web_contents->GetController().GetDefaultSessionStorageNamespace();
605  }
606
607  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
608#if defined(FULL_SAFE_BROWSING)
609    SafeBrowsingService::RegisterFactory(safe_browsing_factory_.get());
610#endif
611  }
612
613  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
614    command_line->AppendSwitchASCII(switches::kPrerenderMode,
615                                    switches::kPrerenderModeSwitchValueEnabled);
616#if defined(OS_MACOSX)
617    // The plugins directory isn't read by default on the Mac, so it needs to be
618    // explicitly registered.
619    base::FilePath app_dir;
620    PathService::Get(chrome::DIR_APP, &app_dir);
621    command_line->AppendSwitchPath(
622        switches::kExtraPluginDir,
623        app_dir.Append(FILE_PATH_LITERAL("plugins")));
624#endif
625    command_line->AppendSwitch(switches::kAlwaysAuthorizePlugins);
626  }
627
628  virtual void SetUpOnMainThread() OVERRIDE {
629    current_browser()->profile()->GetPrefs()->SetBoolean(
630        prefs::kPromptForDownload, false);
631    IncreasePrerenderMemory();
632    if (autostart_test_server_)
633      ASSERT_TRUE(test_server()->Start());
634  }
635
636  // Overload for a single expected final status
637  void PrerenderTestURL(const std::string& html_file,
638                        FinalStatus expected_final_status,
639                        int expected_number_of_loads) {
640    PrerenderTestURL(html_file,
641                     expected_final_status,
642                     expected_number_of_loads,
643                     false);
644  }
645
646  void PrerenderTestURL(const std::string& html_file,
647                        FinalStatus expected_final_status,
648                        int expected_number_of_loads,
649                        bool prerender_should_wait_for_ready_title) {
650    std::deque<FinalStatus> expected_final_status_queue(1,
651                                                        expected_final_status);
652    PrerenderTestURL(html_file,
653                     expected_final_status_queue,
654                     expected_number_of_loads,
655                     prerender_should_wait_for_ready_title);
656  }
657
658  void PrerenderTestURL(
659      const std::string& html_file,
660      const std::deque<FinalStatus>& expected_final_status_queue,
661      int expected_number_of_loads,
662      bool prerender_should_wait_for_ready_title) {
663    GURL url = test_server()->GetURL(html_file);
664    PrerenderTestURLImpl(url, url,
665                         expected_final_status_queue,
666                         expected_number_of_loads,
667                         prerender_should_wait_for_ready_title);
668  }
669
670  void PrerenderTestURL(
671      const std::string& html_file,
672      const std::deque<FinalStatus>& expected_final_status_queue,
673      int expected_number_of_loads) {
674    PrerenderTestURL(html_file, expected_final_status_queue,
675                     expected_number_of_loads, false);
676  }
677
678  void PrerenderTestURL(
679      const GURL& url,
680      FinalStatus expected_final_status,
681      int expected_number_of_loads) {
682    std::deque<FinalStatus> expected_final_status_queue(1,
683                                                        expected_final_status);
684    PrerenderTestURLImpl(url, url,
685                         expected_final_status_queue,
686                         expected_number_of_loads,
687                         false);
688  }
689
690  void PrerenderTestURL(
691      const GURL& prerender_url,
692      const GURL& destination_url,
693      FinalStatus expected_final_status,
694      int expected_number_of_loads) {
695    std::deque<FinalStatus> expected_final_status_queue(1,
696                                                        expected_final_status);
697    PrerenderTestURLImpl(prerender_url, destination_url,
698                         expected_final_status_queue,
699                         expected_number_of_loads,
700                         false);
701  }
702
703  void NavigateToDestURL() const {
704    NavigateToDestURLWithDisposition(CURRENT_TAB);
705  }
706
707  // Opens the url in a new tab, with no opener.
708  void NavigateToDestURLWithDisposition(
709      WindowOpenDisposition disposition) const {
710    NavigateToURLImpl(dest_url_, disposition);
711  }
712
713  void OpenDestURLViaClick() const {
714    OpenDestURLWithJSImpl("Click()");
715  }
716
717  void OpenDestURLViaClickTarget() const {
718    OpenDestURLWithJSImpl("ClickTarget()");
719  }
720
721  void OpenDestURLViaClickNewWindow() const {
722    OpenDestURLWithJSImpl("ShiftClick()");
723  }
724
725  void OpenDestURLViaClickNewForegroundTab() const {
726#if defined(OS_MACOSX)
727    OpenDestURLWithJSImpl("MetaShiftClick()");
728#else
729    OpenDestURLWithJSImpl("CtrlShiftClick()");
730#endif
731  }
732
733  void OpenDestURLViaClickNewBackgroundTab() const {
734    TestPrerenderContents* prerender_contents = GetPrerenderContents();
735    ASSERT_TRUE(prerender_contents != NULL);
736    prerender_contents->set_should_be_shown(false);
737#if defined(OS_MACOSX)
738    OpenDestURLWithJSImpl("MetaClick()");
739#else
740    OpenDestURLWithJSImpl("CtrlClick()");
741#endif
742  }
743
744  void OpenDestURLViaWindowOpen() const {
745    OpenDestURLWithJSImpl("WindowOpen()");
746  }
747
748  void RemoveLinkElement(int i) const {
749    current_browser()->tab_strip_model()->GetActiveWebContents()->
750        GetRenderViewHost()->ExecuteJavascriptInWebFrame(
751            string16(),
752            ASCIIToUTF16(base::StringPrintf("RemoveLinkElement(%d)", i)));
753  }
754
755  void ClickToNextPageAfterPrerender() {
756    content::WindowedNotificationObserver new_page_observer(
757        content::NOTIFICATION_NAV_ENTRY_COMMITTED,
758        content::NotificationService::AllSources());
759    RenderViewHost* render_view_host = current_browser()->tab_strip_model()->
760        GetActiveWebContents()->GetRenderViewHost();
761    render_view_host->ExecuteJavascriptInWebFrame(
762        string16(),
763        ASCIIToUTF16("ClickOpenLink()"));
764    new_page_observer.Wait();
765  }
766
767  void NavigateToNextPageAfterPrerender() const {
768    ui_test_utils::NavigateToURL(
769        current_browser(),
770        test_server()->GetURL("files/prerender/prerender_page.html"));
771  }
772
773  void NavigateToDestUrlAndWaitForPassTitle() {
774    string16 expected_title = ASCIIToUTF16(kPassTitle);
775    content::TitleWatcher title_watcher(
776        GetPrerenderContents()->prerender_contents(),
777        expected_title);
778    NavigateToDestURL();
779    EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
780  }
781
782  // Called after the prerendered page has been navigated to and then away from.
783  // Navigates back through the history to the prerendered page.
784  void GoBackToPrerender() {
785    content::WindowedNotificationObserver back_nav_observer(
786        content::NOTIFICATION_NAV_ENTRY_COMMITTED,
787        content::NotificationService::AllSources());
788    chrome::GoBack(current_browser(), CURRENT_TAB);
789    back_nav_observer.Wait();
790    bool original_prerender_page = false;
791    ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
792        current_browser()->tab_strip_model()->GetActiveWebContents(),
793        "window.domAutomationController.send(IsOriginalPrerenderPage())",
794        &original_prerender_page));
795    EXPECT_TRUE(original_prerender_page);
796  }
797
798  // Goes back to the page that was active before the prerender was swapped
799  // in. This must be called when the prerendered page is the current page
800  // in the active tab.
801  void GoBackToPageBeforePrerender() {
802    WebContents* tab =
803        current_browser()->tab_strip_model()->GetActiveWebContents();
804    ASSERT_TRUE(tab);
805    EXPECT_FALSE(tab->IsLoading());
806    content::WindowedNotificationObserver back_nav_observer(
807        content::NOTIFICATION_LOAD_STOP,
808        content::Source<NavigationController>(&tab->GetController()));
809    chrome::GoBack(current_browser(), CURRENT_TAB);
810    back_nav_observer.Wait();
811    bool js_result;
812    ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
813        tab,
814        "window.domAutomationController.send(DidBackToOriginalPagePass())",
815        &js_result));
816    EXPECT_TRUE(js_result);
817  }
818
819  void NavigateToURL(const std::string& dest_html_file) const {
820    GURL dest_url = test_server()->GetURL(dest_html_file);
821    NavigateToURLImpl(dest_url, CURRENT_TAB);
822  }
823
824  bool UrlIsInPrerenderManager(const std::string& html_file) const {
825    return UrlIsInPrerenderManager(test_server()->GetURL(html_file));
826  }
827
828  bool UrlIsInPrerenderManager(const GURL& url) const {
829    return GetPrerenderManager()->FindPrerenderData(
830        url, GetSessionStorageNamespace()) != NULL;
831  }
832
833  void set_use_https_src(bool use_https_src_server) {
834    use_https_src_server_ = use_https_src_server;
835  }
836
837  void DisableJavascriptCalls() {
838    call_javascript_ = false;
839  }
840
841  TaskManagerModel* GetModel() const {
842    return TaskManager::GetInstance()->model();
843  }
844
845  PrerenderManager* GetPrerenderManager() const {
846    PrerenderManager* prerender_manager =
847        PrerenderManagerFactory::GetForProfile(current_browser()->profile());
848    return prerender_manager;
849  }
850
851  const PrerenderLinkManager* GetPrerenderLinkManager() const {
852    PrerenderLinkManager* prerender_link_manager =
853        PrerenderLinkManagerFactory::GetForProfile(
854            current_browser()->profile());
855    return prerender_link_manager;
856  }
857
858  bool DidReceivePrerenderStartEventForLinkNumber(int index) const {
859    bool received_prerender_started;
860    std::string expression = base::StringPrintf(
861        "window.domAutomationController.send(Boolean("
862            "receivedPrerenderStartEvents[%d]))", index);
863
864    CHECK(content::ExecuteScriptAndExtractBool(
865        current_browser()->tab_strip_model()->GetActiveWebContents(),
866        expression,
867        &received_prerender_started));
868    return received_prerender_started;
869  }
870
871  bool DidReceivePrerenderLoadEventForLinkNumber(int index) const {
872    bool received_prerender_loaded;
873    std::string expression = base::StringPrintf(
874        "window.domAutomationController.send(Boolean("
875            "receivedPrerenderLoadEvents[%d]))", index);
876
877    CHECK(content::ExecuteScriptAndExtractBool(
878        current_browser()->tab_strip_model()->GetActiveWebContents(),
879        expression,
880        &received_prerender_loaded));
881    return received_prerender_loaded;
882  }
883
884  bool DidReceivePrerenderStopEventForLinkNumber(int index) const {
885    bool received_prerender_stopped;
886    std::string expression = base::StringPrintf(
887        "window.domAutomationController.send(Boolean("
888            "receivedPrerenderStopEvents[%d]))", index);
889
890    CHECK(content::ExecuteScriptAndExtractBool(
891        current_browser()->tab_strip_model()->GetActiveWebContents(),
892        expression,
893        &received_prerender_stopped));
894    return received_prerender_stopped;
895  }
896
897  bool HadPrerenderEventErrors() const {
898    bool had_prerender_event_errors;
899    CHECK(content::ExecuteScriptAndExtractBool(
900        current_browser()->tab_strip_model()->GetActiveWebContents(),
901        "window.domAutomationController.send(Boolean("
902        "    hadPrerenderEventErrors))",
903        &had_prerender_event_errors));
904    return had_prerender_event_errors;
905  }
906
907  // Asserting on this can result in flaky tests.  PrerenderHandles are
908  // removed from the PrerenderLinkManager when the prerender is canceled from
909  // the browser, when the prerenders are cancelled from the renderer process,
910  // or the channel for the renderer process is closed on the IO thread.  In the
911  // last case, the code must be careful to wait for the channel to close, as it
912  // is done asynchronously after swapping out the old process.  See
913  // ChannelDestructionWatcher.
914  bool IsEmptyPrerenderLinkManager() const {
915    return GetPrerenderLinkManager()->IsEmpty();
916  }
917
918  // Returns length of |prerender_manager_|'s history, or -1 on failure.
919  int GetHistoryLength() const {
920    scoped_ptr<DictionaryValue> prerender_dict(
921        static_cast<DictionaryValue*>(GetPrerenderManager()->GetAsValue()));
922    if (!prerender_dict.get())
923      return -1;
924    ListValue* history_list;
925    if (!prerender_dict->GetList("history", &history_list))
926      return -1;
927    return static_cast<int>(history_list->GetSize());
928  }
929
930#if defined(FULL_SAFE_BROWSING)
931  FakeSafeBrowsingDatabaseManager* GetFakeSafeBrowsingDatabaseManager() {
932    return safe_browsing_factory_->most_recent_service()->
933        fake_database_manager();
934  }
935#endif
936
937  TestPrerenderContents* GetPrerenderContentsFor(const GURL& url) const {
938    PrerenderManager::PrerenderData* prerender_data =
939        GetPrerenderManager()->FindPrerenderData(
940            url, GetSessionStorageNamespace());
941    return static_cast<TestPrerenderContents*>(
942        prerender_data ? prerender_data->contents() : NULL);
943  }
944
945  TestPrerenderContents* GetPrerenderContents() const {
946    return GetPrerenderContentsFor(dest_url_);
947  }
948
949  void set_loader_path(const std::string& path) {
950    loader_path_ = path;
951  }
952
953  void set_loader_query_and_fragment(const std::string& query_and_fragment) {
954    loader_query_and_fragment_ = query_and_fragment;
955  }
956
957  GURL GetCrossDomainTestUrl(const std::string& path) {
958    static const std::string secondary_domain = "www.foo.com";
959    host_resolver()->AddRule(secondary_domain, "127.0.0.1");
960    std::string url_str(base::StringPrintf(
961        "http://%s:%d/%s",
962        secondary_domain.c_str(),
963        test_server()->host_port_pair().port(),
964        path.c_str()));
965    return GURL(url_str);
966  }
967
968  void set_browser(Browser* browser) {
969    explicitly_set_browser_ = browser;
970  }
971
972  Browser* current_browser() const {
973    return explicitly_set_browser_ ? explicitly_set_browser_ : browser();
974  }
975
976  void IncreasePrerenderMemory() {
977    // Increase the memory allowed in a prerendered page above normal settings.
978    // Debug build bots occasionally run against the default limit, and tests
979    // were failing because the prerender was canceled due to memory exhaustion.
980    // http://crbug.com/93076
981    GetPrerenderManager()->mutable_config().max_bytes = 1000 * 1024 * 1024;
982  }
983
984 protected:
985  bool autostart_test_server_;
986
987 private:
988  void PrerenderTestURLImpl(
989      const GURL& prerender_url,
990      const GURL& destination_url,
991      const std::deque<FinalStatus>& expected_final_status_queue,
992      int expected_number_of_loads,
993      bool prerender_should_wait_for_ready_title) {
994    dest_url_ = destination_url;
995
996    std::vector<net::SpawnedTestServer::StringPair> replacement_text;
997    replacement_text.push_back(
998        make_pair("REPLACE_WITH_PRERENDER_URL", prerender_url.spec()));
999    replacement_text.push_back(
1000        make_pair("REPLACE_WITH_DESTINATION_URL", destination_url.spec()));
1001    std::string replacement_path;
1002    ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
1003        loader_path_,
1004        replacement_text,
1005        &replacement_path));
1006
1007    const net::SpawnedTestServer* src_server = test_server();
1008    scoped_ptr<net::SpawnedTestServer> https_src_server;
1009    if (use_https_src_server_) {
1010      https_src_server.reset(
1011          new net::SpawnedTestServer(
1012              net::SpawnedTestServer::TYPE_HTTPS,
1013              net::SpawnedTestServer::kLocalhost,
1014              base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
1015      ASSERT_TRUE(https_src_server->Start());
1016      src_server = https_src_server.get();
1017    }
1018    GURL loader_url = src_server->GetURL(replacement_path +
1019                                         loader_query_and_fragment_);
1020
1021    PrerenderManager* prerender_manager = GetPrerenderManager();
1022    ASSERT_TRUE(prerender_manager);
1023    prerender_manager->mutable_config().rate_limit_enabled = false;
1024    prerender_manager->mutable_config().https_allowed = true;
1025    ASSERT_TRUE(prerender_contents_factory_ == NULL);
1026    prerender_contents_factory_ =
1027        new WaitForLoadPrerenderContentsFactory(
1028            expected_number_of_loads,
1029            expected_final_status_queue,
1030            prerender_should_wait_for_ready_title);
1031    prerender_manager->SetPrerenderContentsFactory(
1032        prerender_contents_factory_);
1033    FinalStatus expected_final_status = expected_final_status_queue.front();
1034
1035    // We construct launch_nav_observer so that we can be certain our loader
1036    // page has finished loading before continuing. This prevents ambiguous
1037    // NOTIFICATION_LOAD_STOP events from making tests flaky.
1038    WebContents* web_contents =
1039        current_browser()->tab_strip_model()->GetActiveWebContents();
1040    content::WindowedNotificationObserver loader_nav_observer(
1041        content::NOTIFICATION_LOAD_STOP,
1042        content::Source<NavigationController>(
1043            &web_contents->GetController()));
1044
1045    // ui_test_utils::NavigateToURL uses its own observer and message loop.
1046    // Since the test needs to wait until the prerendered page has stopped
1047    // loading, rather than the page directly navigated to, need to
1048    // handle browser navigation directly.
1049    current_browser()->OpenURL(OpenURLParams(
1050        loader_url, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED,
1051        false));
1052
1053    content::RunMessageLoop();
1054    // Now that we've run the prerender until it stopped loading, we can now
1055    // also make sure the launcher has finished loading.
1056    loader_nav_observer.Wait();
1057
1058    TestPrerenderContents* prerender_contents = GetPrerenderContents();
1059
1060    if (ShouldRenderPrerenderedPageCorrectly(expected_final_status)) {
1061      ASSERT_NE(static_cast<PrerenderContents*>(NULL), prerender_contents);
1062      EXPECT_EQ(FINAL_STATUS_MAX, prerender_contents->final_status());
1063
1064      if (call_javascript_ && expected_number_of_loads > 0) {
1065        // Wait for the prerendered page to change title to signal it is ready
1066        // if required.
1067        prerender_contents->WaitForPrerenderToHaveReadyTitleIfRequired();
1068
1069        // Check if page behaves as expected while in prerendered state.
1070        bool prerender_test_result = false;
1071        ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1072            prerender_contents->GetRenderViewHostMutable(),
1073            "window.domAutomationController.send(DidPrerenderPass())",
1074            &prerender_test_result));
1075        EXPECT_TRUE(prerender_test_result);
1076      }
1077    } else {
1078      // In the failure case, we should have removed |dest_url_| from the
1079      // prerender_manager.  We ignore dummy PrerenderContents (as indicated
1080      // by not having started), and PrerenderContents that are expected to
1081      // be left in the manager until the test finishes.
1082      EXPECT_TRUE(prerender_contents == NULL ||
1083                  !prerender_contents->prerendering_has_started());
1084    }
1085  }
1086
1087  void NavigateToURLImpl(const GURL& dest_url,
1088                         WindowOpenDisposition disposition) const {
1089    ASSERT_NE(static_cast<PrerenderManager*>(NULL), GetPrerenderManager());
1090    // Make sure in navigating we have a URL to use in the PrerenderManager.
1091    ASSERT_NE(static_cast<PrerenderContents*>(NULL), GetPrerenderContents());
1092
1093    // If opening the page in a background tab, it won't be shown when swapped
1094    // in.
1095    if (disposition == NEW_BACKGROUND_TAB)
1096      GetPrerenderContents()->set_should_be_shown(false);
1097
1098    scoped_ptr<content::WindowedNotificationObserver> page_load_observer;
1099    WebContents* web_contents = NULL;
1100
1101    if (GetPrerenderContents()->prerender_contents()) {
1102      // In the case of zero loads, need to wait for the page load to complete
1103      // before running any Javascript.
1104      web_contents = GetPrerenderContents()->prerender_contents();
1105      if (GetPrerenderContents()->number_of_loads() == 0) {
1106        page_load_observer.reset(
1107            new content::WindowedNotificationObserver(
1108                content::NOTIFICATION_LOAD_STOP,
1109                content::Source<NavigationController>(
1110                    &web_contents->GetController())));
1111      }
1112    }
1113
1114    // Navigate to the prerendered URL, but don't run the message loop. Browser
1115    // issued navigations to prerendered pages will synchronously swap in the
1116    // prerendered page.
1117    ui_test_utils::NavigateToURLWithDisposition(
1118        current_browser(), dest_url, disposition,
1119        ui_test_utils::BROWSER_TEST_NONE);
1120
1121    // Make sure the PrerenderContents found earlier was used or removed.
1122    EXPECT_EQ(static_cast<PrerenderContents*>(NULL), GetPrerenderContents());
1123
1124    if (call_javascript_ && web_contents) {
1125      if (page_load_observer.get())
1126        page_load_observer->Wait();
1127
1128      bool display_test_result = false;
1129      ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1130          web_contents,
1131          "window.domAutomationController.send(DidDisplayPass())",
1132          &display_test_result));
1133      EXPECT_TRUE(display_test_result);
1134    }
1135  }
1136
1137  // Opens the prerendered page using javascript functions in the
1138  // loader page. |javascript_function_name| should be a 0 argument function
1139  // which is invoked.
1140  void OpenDestURLWithJSImpl(const std::string& javascript_function_name)
1141      const {
1142    TestPrerenderContents* prerender_contents = GetPrerenderContents();
1143    ASSERT_NE(static_cast<PrerenderContents*>(NULL), prerender_contents);
1144
1145    RenderViewHost* render_view_host = current_browser()->tab_strip_model()->
1146        GetActiveWebContents()->GetRenderViewHost();
1147
1148    render_view_host->ExecuteJavascriptInWebFrame(
1149        string16(), ASCIIToUTF16(javascript_function_name));
1150
1151    if (prerender_contents->quit_message_loop_on_destruction()) {
1152      // Run message loop until the prerender contents is destroyed.
1153      content::RunMessageLoop();
1154    } else {
1155      // We don't expect to pick up a running prerender, so instead
1156      // observe one navigation.
1157      content::TestNavigationObserver observer(
1158          content::NotificationService::AllSources(), 1);
1159      base::RunLoop run_loop;
1160      observer.WaitForObservation(
1161          base::Bind(&content::RunThisRunLoop,
1162                     base::Unretained(&run_loop)),
1163          content::GetQuitTaskForRunLoop(&run_loop));
1164    }
1165  }
1166
1167  WaitForLoadPrerenderContentsFactory* prerender_contents_factory_;
1168#if defined(FULL_SAFE_BROWSING)
1169  scoped_ptr<TestSafeBrowsingServiceFactory> safe_browsing_factory_;
1170#endif
1171  GURL dest_url_;
1172  bool use_https_src_server_;
1173  bool call_javascript_;
1174  std::string loader_path_;
1175  std::string loader_query_and_fragment_;
1176  Browser* explicitly_set_browser_;
1177};
1178
1179// Checks that a page is correctly prerendered in the case of a
1180// <link rel=prerender> tag and then loaded into a tab in response to a
1181// navigation.
1182IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPage) {
1183  PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
1184
1185  ChannelDestructionWatcher channel_close_watcher;
1186  channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
1187      GetActiveWebContents()->GetRenderProcessHost());
1188  NavigateToDestURL();
1189  channel_close_watcher.WaitForChannelClose();
1190
1191  ASSERT_TRUE(IsEmptyPrerenderLinkManager());
1192}
1193
1194// Checks that pending prerenders launch and receive proper event treatment.
1195// Disabled due to http://crbug.com/167792
1196IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderPagePending) {
1197  std::deque<FinalStatus> expected_final_status_queue;
1198  expected_final_status_queue.push_back(FINAL_STATUS_USED);
1199  expected_final_status_queue.push_back(FINAL_STATUS_USED);
1200  PrerenderTestURL("files/prerender/prerender_page_pending.html",
1201                   expected_final_status_queue, 1);
1202
1203  ChannelDestructionWatcher first_channel_close_watcher;
1204
1205  first_channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
1206      GetActiveWebContents()->GetRenderProcessHost());
1207  NavigateToDestURL();
1208  // NavigateToDestURL doesn't run a message loop. Normally that's fine, but in
1209  // this case, we need the pending prerenders to start.
1210  content::RunMessageLoop();
1211  first_channel_close_watcher.WaitForChannelClose();
1212
1213  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1214  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1215  EXPECT_FALSE(HadPrerenderEventErrors());
1216
1217  const GURL prerender_page_url =
1218      test_server()->GetURL("files/prerender/prerender_page.html");
1219  EXPECT_FALSE(IsEmptyPrerenderLinkManager());
1220  EXPECT_NE(static_cast<TestPrerenderContents*>(NULL),
1221            GetPrerenderContentsFor(prerender_page_url));
1222
1223  // Now navigate to our target page.
1224  ChannelDestructionWatcher second_channel_close_watcher;
1225  second_channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
1226      GetActiveWebContents()->GetRenderProcessHost());
1227  ui_test_utils::NavigateToURLWithDisposition(
1228      current_browser(), prerender_page_url, CURRENT_TAB,
1229      ui_test_utils::BROWSER_TEST_NONE);
1230  second_channel_close_watcher.WaitForChannelClose();
1231
1232  EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1233}
1234
1235// Checks that pending prerenders which are canceled before they are launched
1236// never get started.
1237IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageRemovesPending) {
1238  PrerenderTestURL("files/prerender/prerender_page_removes_pending.html",
1239                   FINAL_STATUS_USED, 1);
1240
1241  ChannelDestructionWatcher channel_close_watcher;
1242  channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
1243      GetActiveWebContents()->GetRenderProcessHost());
1244  NavigateToDestURL();
1245  channel_close_watcher.WaitForChannelClose();
1246
1247  EXPECT_FALSE(DidReceivePrerenderStartEventForLinkNumber(1));
1248  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1249  EXPECT_FALSE(HadPrerenderEventErrors());
1250  // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
1251  // calls did a thread/process hop to the renderer which insured pending
1252  // renderer events have arrived.
1253  ASSERT_TRUE(IsEmptyPrerenderLinkManager());
1254}
1255
1256// Flaky, http://crbug.com/167340.
1257IN_PROC_BROWSER_TEST_F(
1258    PrerenderBrowserTest, DISABLED_PrerenderPageRemovingLink) {
1259  set_loader_path("files/prerender/prerender_loader_removing_links.html");
1260  set_loader_query_and_fragment("?links_to_insert=1");
1261  PrerenderTestURL("files/prerender/prerender_page.html",
1262                   FINAL_STATUS_CANCELLED, 1);
1263  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1264  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1265
1266  // No ChannelDestructionWatcher is needed here, since prerenders in the
1267  // PrerenderLinkManager should be deleted by removing the links, rather than
1268  // shutting down the renderer process.
1269  RemoveLinkElement(0);
1270  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1271  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1272  EXPECT_FALSE(HadPrerenderEventErrors());
1273  // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
1274  // calls did a thread/process hop to the renderer which insured pending
1275  // renderer events have arrived.
1276  EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1277}
1278
1279// Flaky, http://crbug.com/167340.
1280IN_PROC_BROWSER_TEST_F(
1281    PrerenderBrowserTest, DISABLED_PrerenderPageRemovingLinkWithTwoLinks) {
1282  GetPrerenderManager()->mutable_config().max_link_concurrency = 2;
1283  GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2;
1284
1285  set_loader_path("files/prerender/prerender_loader_removing_links.html");
1286  set_loader_query_and_fragment("?links_to_insert=2");
1287  PrerenderTestURL("files/prerender/prerender_page.html",
1288                   FINAL_STATUS_CANCELLED, 1);
1289  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1290  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1291  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
1292  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1293
1294  RemoveLinkElement(0);
1295  RemoveLinkElement(1);
1296  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1297  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1298  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
1299  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1300  EXPECT_FALSE(HadPrerenderEventErrors());
1301  // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
1302  // calls did a thread/process hop to the renderer which insured pending
1303  // renderer events have arrived.
1304  EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1305}
1306
1307#if defined(OS_WIN)
1308// TODO(gavinp): Fails on XP Rel - http://crbug.com/128841
1309#define MAYBE_PrerenderPageRemovingLinkWithTwoLinksRemovingOne \
1310    DISABLED_PrerenderPageRemovingLinkWithTwoLinksRemovingOne
1311#else
1312#define MAYBE_PrerenderPageRemovingLinkWithTwoLinksRemovingOne \
1313    PrerenderPageRemovingLinkWithTwoLinksRemovingOne
1314#endif  // defined(OS_WIN)
1315IN_PROC_BROWSER_TEST_F(
1316    PrerenderBrowserTest,
1317    MAYBE_PrerenderPageRemovingLinkWithTwoLinksRemovingOne) {
1318  GetPrerenderManager()->mutable_config().max_link_concurrency = 2;
1319  GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2;
1320  set_loader_path("files/prerender/prerender_loader_removing_links.html");
1321  set_loader_query_and_fragment("?links_to_insert=2");
1322  PrerenderTestURL("files/prerender/prerender_page.html",
1323                   FINAL_STATUS_USED, 1);
1324  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1325  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1326  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
1327  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1328
1329  RemoveLinkElement(0);
1330  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
1331  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
1332  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1));
1333  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1));
1334  EXPECT_FALSE(HadPrerenderEventErrors());
1335  // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive*
1336  // calls did a thread/process hop to the renderer which insured pending
1337  // renderer events have arrived.
1338  EXPECT_FALSE(IsEmptyPrerenderLinkManager());
1339
1340  ChannelDestructionWatcher channel_close_watcher;
1341  channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
1342      GetActiveWebContents()->GetRenderProcessHost());
1343  NavigateToDestURL();
1344  channel_close_watcher.WaitForChannelClose();
1345
1346  EXPECT_TRUE(IsEmptyPrerenderLinkManager());
1347}
1348
1349// Checks that prerendering works in incognito mode.
1350IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderIncognito) {
1351  Profile* normal_profile = current_browser()->profile();
1352  set_browser(
1353      ui_test_utils::OpenURLOffTheRecord(normal_profile, GURL("about:blank")));
1354  // Increase memory expectations on the incognito PrerenderManager.
1355  IncreasePrerenderMemory();
1356  PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
1357  NavigateToDestURL();
1358}
1359
1360// Checks that the visibility API works.
1361IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderVisibility) {
1362  PrerenderTestURL("files/prerender/prerender_visibility.html",
1363                   FINAL_STATUS_USED,
1364                   1);
1365  NavigateToDestURL();
1366}
1367
1368// Checks that the visibility API works when the prerender is quickly opened
1369// in a new tab before it stops loading.
1370IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderVisibilityQuickSwitch) {
1371  PrerenderTestURL("files/prerender/prerender_visibility_quick.html",
1372                   FINAL_STATUS_USED, 0);
1373  NavigateToDestURL();
1374}
1375
1376// Checks that the prerendering of a page is canceled correctly when a
1377// Javascript alert is called.
1378IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertBeforeOnload) {
1379  PrerenderTestURL("files/prerender/prerender_alert_before_onload.html",
1380                   FINAL_STATUS_JAVASCRIPT_ALERT,
1381                   1);
1382}
1383
1384// Checks that the prerendering of a page is canceled correctly when a
1385// Javascript alert is called.
1386IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertAfterOnload) {
1387  PrerenderTestURL("files/prerender/prerender_alert_after_onload.html",
1388                   FINAL_STATUS_JAVASCRIPT_ALERT,
1389                   1);
1390}
1391
1392// Checks that plugins are not loaded while a page is being preloaded, but
1393// are loaded when the page is displayed.
1394#if defined(USE_AURA)
1395// http://crbug.com/103496
1396#define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin
1397#elif defined(OS_MACOSX)
1398// http://crbug.com/100514
1399#define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin
1400#else
1401#define MAYBE_PrerenderDelayLoadPlugin PrerenderDelayLoadPlugin
1402#endif
1403IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MAYBE_PrerenderDelayLoadPlugin) {
1404  PrerenderTestURL("files/prerender/plugin_delay_load.html",
1405                   FINAL_STATUS_USED,
1406                   1);
1407  NavigateToDestURL();
1408}
1409
1410// Checks that plugins are not loaded on prerendering pages when click-to-play
1411// is enabled.
1412IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickToPlay) {
1413  // Enable click-to-play.
1414  HostContentSettingsMap* content_settings_map =
1415      current_browser()->profile()->GetHostContentSettingsMap();
1416  content_settings_map->SetDefaultContentSetting(
1417      CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_ASK);
1418
1419  PrerenderTestURL("files/prerender/prerender_plugin_click_to_play.html",
1420                   FINAL_STATUS_USED,
1421                   1);
1422  NavigateToDestURL();
1423}
1424
1425// Checks that we don't load a NaCl plugin when NaCl is disabled.
1426IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNaClPluginDisabled) {
1427  PrerenderTestURL("files/prerender/prerender_plugin_nacl_disabled.html",
1428                   FINAL_STATUS_USED,
1429                   1);
1430  NavigateToDestURL();
1431
1432
1433  // Run this check again.  When we try to load aa ppapi plugin, the
1434  // "loadstart" event is asynchronously posted to a message loop.
1435  // It's possible that earlier call could have been run before the
1436  // the "loadstart" event was posted.
1437  // TODO(mmenke):  While this should reliably fail on regressions, the
1438  //                reliability depends on the specifics of ppapi plugin
1439  //                loading.  It would be great if we could avoid that.
1440  WebContents* web_contents =
1441      browser()->tab_strip_model()->GetActiveWebContents();
1442  bool display_test_result = false;
1443  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
1444      web_contents,
1445      "window.domAutomationController.send(DidDisplayPass())",
1446      &display_test_result));
1447  EXPECT_TRUE(display_test_result);
1448}
1449
1450// Checks that plugins in an iframe are not loaded while a page is
1451// being preloaded, but are loaded when the page is displayed.
1452#if defined(USE_AURA)
1453// http://crbug.com/103496
1454#define MAYBE_PrerenderIframeDelayLoadPlugin \
1455        DISABLED_PrerenderIframeDelayLoadPlugin
1456#elif defined(OS_MACOSX)
1457// http://crbug.com/100514
1458#define MAYBE_PrerenderIframeDelayLoadPlugin \
1459        DISABLED_PrerenderIframeDelayLoadPlugin
1460#else
1461#define MAYBE_PrerenderIframeDelayLoadPlugin PrerenderIframeDelayLoadPlugin
1462#endif
1463IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1464                       MAYBE_PrerenderIframeDelayLoadPlugin) {
1465  PrerenderTestURL("files/prerender/prerender_iframe_plugin_delay_load.html",
1466                   FINAL_STATUS_USED,
1467                   1);
1468  NavigateToDestURL();
1469}
1470
1471// Renders a page that contains a prerender link to a page that contains an
1472// iframe with a source that requires http authentication. This should not
1473// prerender successfully.
1474IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHttpAuthentication) {
1475  PrerenderTestURL("files/prerender/prerender_http_auth_container.html",
1476                   FINAL_STATUS_AUTH_NEEDED,
1477                   1);
1478}
1479
1480// Checks that client-issued redirects work with prerendering.
1481// This version navigates to the page which issues the redirection, rather
1482// than the final destination page.
1483IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1484                       PrerenderClientRedirectNavigateToFirst) {
1485  PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"),
1486                   FINAL_STATUS_USED,
1487                   2);
1488  NavigateToDestURL();
1489}
1490
1491// Checks that client-issued redirects work with prerendering.
1492// This version navigates to the final destination page, rather than the
1493// page which does the redirection.
1494IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1495                       PrerenderClientRedirectNavigateToSecond) {
1496  PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"),
1497                   FINAL_STATUS_USED,
1498                   2);
1499  NavigateToURL("files/prerender/prerender_page.html");
1500}
1501
1502// Checks that client-issued redirects work with prerendering.
1503// This version navigates to the final destination page, rather than the
1504// page which does the redirection via a mouse click.
1505IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1506                       PrerenderClientRedirectNavigateToSecondViaClick) {
1507  GURL prerender_url = test_server()->GetURL(
1508      CreateClientRedirect("files/prerender/prerender_page.html"));
1509  GURL destination_url = test_server()->GetURL(
1510      "files/prerender/prerender_page.html");
1511  PrerenderTestURL(prerender_url, destination_url, FINAL_STATUS_USED, 2);
1512  OpenDestURLViaClick();
1513}
1514
1515// Checks that a prerender for an https will prevent a prerender from happening.
1516IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHttps) {
1517  net::SpawnedTestServer https_server(
1518      net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
1519      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1520  ASSERT_TRUE(https_server.Start());
1521  GURL https_url = https_server.GetURL("files/prerender/prerender_page.html");
1522  PrerenderTestURL(https_url,
1523                   FINAL_STATUS_USED,
1524                   1);
1525  NavigateToDestURL();
1526}
1527
1528// Checks that client-issued redirects to an https page will cancel prerenders.
1529IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClientRedirectToHttps) {
1530  net::SpawnedTestServer https_server(
1531      net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
1532      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1533  ASSERT_TRUE(https_server.Start());
1534  GURL https_url = https_server.GetURL("files/prerender/prerender_page.html");
1535  PrerenderTestURL(CreateClientRedirect(https_url.spec()),
1536                   FINAL_STATUS_USED,
1537                   2);
1538  NavigateToDestURL();
1539}
1540
1541// Checks that client-issued redirects within an iframe in a prerendered
1542// page will not count as an "alias" for the prerendered page.
1543IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClientRedirectInIframe) {
1544  std::string redirect_path = CreateClientRedirect(
1545      "/files/prerender/prerender_embedded_content.html");
1546  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
1547  replacement_text.push_back(
1548      std::make_pair("REPLACE_WITH_URL", "/" + redirect_path));
1549  std::string replacement_path;
1550  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
1551      "files/prerender/prerender_with_iframe.html",
1552      replacement_text,
1553      &replacement_path));
1554  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 2);
1555  EXPECT_FALSE(UrlIsInPrerenderManager(
1556      "files/prerender/prerender_embedded_content.html"));
1557  NavigateToDestURL();
1558}
1559
1560// Checks that client-issued redirects within an iframe in a prerendered
1561// page to an https page will not cancel the prerender, nor will it
1562// count as an "alias" for the prerendered page.
1563IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1564                       PrerenderClientRedirectToHttpsInIframe) {
1565  net::SpawnedTestServer https_server(
1566      net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
1567      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1568  ASSERT_TRUE(https_server.Start());
1569  GURL https_url = https_server.GetURL("files/prerender/prerender_page.html");
1570  std::string redirect_path = CreateClientRedirect(https_url.spec());
1571  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
1572  replacement_text.push_back(
1573      std::make_pair("REPLACE_WITH_URL", "/" + redirect_path));
1574  std::string replacement_path;
1575  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
1576      "files/prerender/prerender_with_iframe.html",
1577      replacement_text,
1578      &replacement_path));
1579  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 2);
1580  EXPECT_FALSE(UrlIsInPrerenderManager(https_url));
1581  NavigateToDestURL();
1582}
1583
1584// Checks that server-issued redirects work with prerendering.
1585// This version navigates to the page which issues the redirection, rather
1586// than the final destination page.
1587IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1588                       PrerenderServerRedirectNavigateToFirst) {
1589  PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"),
1590                   FINAL_STATUS_USED,
1591                   1);
1592  NavigateToDestURL();
1593}
1594
1595// Checks that server-issued redirects work with prerendering.
1596// This version navigates to the final destination page, rather than the
1597// page which does the redirection.
1598IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1599                       PrerenderServerRedirectNavigateToSecond) {
1600  PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"),
1601                   FINAL_STATUS_USED,
1602                   1);
1603  NavigateToURL("files/prerender/prerender_page.html");
1604}
1605
1606// Checks that server-issued redirects work with prerendering.
1607// This version navigates to the final destination page, rather than the
1608// page which does the redirection via a mouse click.
1609IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1610                       PrerenderServerRedirectNavigateToSecondViaClick) {
1611  GURL prerender_url = test_server()->GetURL(
1612      CreateServerRedirect("files/prerender/prerender_page.html"));
1613  GURL destination_url = test_server()->GetURL(
1614      "files/prerender/prerender_page.html");
1615  PrerenderTestURL(prerender_url, destination_url, FINAL_STATUS_USED, 1);
1616  OpenDestURLViaClick();
1617}
1618
1619// Checks that server-issued redirects from an http to an https
1620// location will cancel prerendering.
1621IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1622                       PrerenderServerRedirectToHttps) {
1623  net::SpawnedTestServer https_server(
1624      net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
1625      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1626  ASSERT_TRUE(https_server.Start());
1627  GURL https_url = https_server.GetURL("files/prerender/prerender_page.html");
1628  PrerenderTestURL(CreateServerRedirect(https_url.spec()),
1629                   FINAL_STATUS_USED,
1630                   1);
1631  NavigateToDestURL();
1632}
1633
1634// Checks that server-issued redirects within an iframe in a prerendered
1635// page will not count as an "alias" for the prerendered page.
1636IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderServerRedirectInIframe) {
1637  std::string redirect_path = CreateServerRedirect(
1638      "/files/prerender/prerender_embedded_content.html");
1639  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
1640  replacement_text.push_back(
1641      std::make_pair("REPLACE_WITH_URL", "/" + redirect_path));
1642  std::string replacement_path;
1643  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
1644      "files/prerender/prerender_with_iframe.html",
1645      replacement_text,
1646      &replacement_path));
1647  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
1648  EXPECT_FALSE(UrlIsInPrerenderManager(
1649      "files/prerender/prerender_embedded_content.html"));
1650  NavigateToDestURL();
1651}
1652
1653// Checks that server-issued redirects within an iframe in a prerendered
1654// page to an https page will not cancel the prerender, nor will it
1655// count as an "alias" for the prerendered page.
1656IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1657                       PrerenderServerRedirectToHttpsInIframe) {
1658  net::SpawnedTestServer https_server(
1659      net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost,
1660      base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1661  ASSERT_TRUE(https_server.Start());
1662  GURL https_url = https_server.GetURL("files/prerender/prerender_page.html");
1663  std::string redirect_path = CreateServerRedirect(https_url.spec());
1664  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
1665  replacement_text.push_back(
1666      std::make_pair("REPLACE_WITH_URL", "/" + redirect_path));
1667  std::string replacement_path;
1668  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
1669      "files/prerender/prerender_with_iframe.html",
1670      replacement_text,
1671      &replacement_path));
1672  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
1673  EXPECT_FALSE(UrlIsInPrerenderManager(https_url));
1674  NavigateToDestURL();
1675}
1676
1677// Prerenders a page that contains an automatic download triggered through an
1678// iframe. This should not prerender successfully.
1679IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDownloadIframe) {
1680  PrerenderTestURL("files/prerender/prerender_download_iframe.html",
1681                   FINAL_STATUS_DOWNLOAD,
1682                   1);
1683}
1684
1685// Prerenders a page that contains an automatic download triggered through
1686// Javascript changing the window.location. This should not prerender
1687// successfully
1688IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDownloadLocation) {
1689  PrerenderTestURL(CreateClientRedirect("files/download-test1.lib"),
1690                   FINAL_STATUS_DOWNLOAD,
1691                   1);
1692}
1693
1694// Prerenders a page that contains an automatic download triggered through a
1695// client-issued redirect. This should not prerender successfully.
1696IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDownloadClientRedirect) {
1697  PrerenderTestURL("files/prerender/prerender_download_refresh.html",
1698                   FINAL_STATUS_DOWNLOAD,
1699                   1);
1700}
1701
1702// Checks that the referrer is set when prerendering.
1703IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReferrer) {
1704  PrerenderTestURL("files/prerender/prerender_referrer.html",
1705                   FINAL_STATUS_USED,
1706                   1);
1707  NavigateToDestURL();
1708}
1709
1710// Checks that the referrer is not set when prerendering and the source page is
1711// HTTPS.
1712IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNoSSLReferrer) {
1713  set_use_https_src(true);
1714  PrerenderTestURL("files/prerender/prerender_no_referrer.html",
1715                   FINAL_STATUS_USED,
1716                   1);
1717  NavigateToDestURL();
1718}
1719
1720// Checks that popups on a prerendered page cause cancellation.
1721IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPopup) {
1722  PrerenderTestURL("files/prerender/prerender_popup.html",
1723                   FINAL_STATUS_CREATE_NEW_WINDOW,
1724                   1);
1725}
1726
1727// Checks that registering a protocol handler causes cancellation.
1728IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderRegisterProtocolHandler) {
1729  PrerenderTestURL("files/prerender/prerender_register_protocol_handler.html",
1730                   FINAL_STATUS_REGISTER_PROTOCOL_HANDLER,
1731                   1);
1732}
1733
1734// Checks that renderers using excessive memory will be terminated.
1735IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderExcessiveMemory) {
1736  ASSERT_TRUE(GetPrerenderManager());
1737  GetPrerenderManager()->mutable_config().max_bytes = 30 * 1024 * 1024;
1738  PrerenderTestURL("files/prerender/prerender_excessive_memory.html",
1739                   FINAL_STATUS_MEMORY_LIMIT_EXCEEDED,
1740                   1);
1741}
1742
1743// Checks shutdown code while a prerender is active.
1744IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderQuickQuit) {
1745  PrerenderTestURL("files/prerender/prerender_page.html",
1746                   FINAL_STATUS_APP_TERMINATING,
1747                   0);
1748}
1749
1750// TODO(gavinp,sreeram): Fix http://crbug.com/145248 and deflake this test.
1751// Checks that we don't prerender in an infinite loop.
1752IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderInfiniteLoop) {
1753  const char* const kHtmlFileA = "files/prerender/prerender_infinite_a.html";
1754  const char* const kHtmlFileB = "files/prerender/prerender_infinite_b.html";
1755
1756  std::deque<FinalStatus> expected_final_status_queue;
1757  expected_final_status_queue.push_back(FINAL_STATUS_USED);
1758  expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING);
1759
1760  PrerenderTestURL(kHtmlFileA, expected_final_status_queue, 1);
1761  ASSERT_TRUE(GetPrerenderContents());
1762  GetPrerenderContents()->WaitForPendingPrerenders(1u);
1763
1764  // Next url should be in pending list but not an active entry.
1765  EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB));
1766
1767  NavigateToDestURL();
1768
1769  // Make sure the PrerenderContents for the next url is now in the manager
1770  // and not pending.
1771  EXPECT_TRUE(UrlIsInPrerenderManager(kHtmlFileB));
1772}
1773
1774// TODO(gavinp,sreeram): Fix http://crbug.com/145248 and deflake this test.
1775// Checks that we don't prerender in an infinite loop and multiple links are
1776// handled correctly.
1777IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1778                       DISABLED_PrerenderInfiniteLoopMultiple) {
1779  const char* const kHtmlFileA =
1780      "files/prerender/prerender_infinite_a_multiple.html";
1781  const char* const kHtmlFileB =
1782      "files/prerender/prerender_infinite_b_multiple.html";
1783  const char* const kHtmlFileC =
1784      "files/prerender/prerender_infinite_c_multiple.html";
1785
1786  // This test is conceptually simplest if concurrency is at two, since we
1787  // don't have to worry about which of kHtmlFileB or kHtmlFileC gets evicted.
1788  GetPrerenderManager()->mutable_config().max_link_concurrency = 2;
1789  GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2;
1790
1791  std::deque<FinalStatus> expected_final_status_queue;
1792  expected_final_status_queue.push_back(FINAL_STATUS_USED);
1793  expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING);
1794  expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING);
1795
1796  PrerenderTestURL(kHtmlFileA, expected_final_status_queue, 1);
1797  ASSERT_TRUE(GetPrerenderContents());
1798  GetPrerenderContents()->WaitForPendingPrerenders(2u);
1799
1800  // Next url should be in pending list but not an active entry.
1801  EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB));
1802  EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileC));
1803
1804  NavigateToDestURL();
1805
1806  // Make sure the PrerenderContents for the next urls are now in the manager
1807  // and not pending. One and only one of the URLs (the last seen) should be the
1808  // active entry.
1809  bool url_b_is_active_prerender = UrlIsInPrerenderManager(kHtmlFileB);
1810  bool url_c_is_active_prerender = UrlIsInPrerenderManager(kHtmlFileC);
1811  EXPECT_TRUE(url_b_is_active_prerender && url_c_is_active_prerender);
1812}
1813
1814// See crbug.com/131836.
1815IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderTaskManager) {
1816  // Show the task manager. This populates the model.
1817  chrome::OpenTaskManager(current_browser(), false);
1818  // Wait for the model of task manager to start.
1819  TaskManagerBrowserTestUtil::WaitForWebResourceChange(1);
1820
1821  // Start with two resources.
1822  PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
1823
1824  // One of the resources that has a WebContents associated with it should have
1825  // the Prerender prefix.
1826  const string16 prefix =
1827      l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRERENDER_PREFIX, string16());
1828  string16 prerender_title;
1829  int num_prerender_tabs = 0;
1830
1831  const TaskManagerModel* model = GetModel();
1832  for (int i = 0; i < model->ResourceCount(); ++i) {
1833    if (model->GetResourceWebContents(i)) {
1834      prerender_title = model->GetResourceTitle(i);
1835      if (StartsWith(prerender_title, prefix, true))
1836        ++num_prerender_tabs;
1837    }
1838  }
1839  EXPECT_EQ(1, num_prerender_tabs);
1840  const string16 prerender_page_title = prerender_title.substr(prefix.length());
1841
1842  NavigateToDestURL();
1843
1844  // There should be no tabs with the Prerender prefix.
1845  const string16 tab_prefix =
1846      l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX, string16());
1847  num_prerender_tabs = 0;
1848  int num_tabs_with_prerender_page_title = 0;
1849  for (int i = 0; i < model->ResourceCount(); ++i) {
1850    if (model->GetResourceWebContents(i)) {
1851      string16 tab_title = model->GetResourceTitle(i);
1852      if (StartsWith(tab_title, prefix, true)) {
1853        ++num_prerender_tabs;
1854      } else {
1855        EXPECT_TRUE(StartsWith(tab_title, tab_prefix, true));
1856
1857        // The prerender tab should now be a normal tab but the title should be
1858        // the same. Depending on timing, there may be more than one of these.
1859        const string16 tab_page_title = tab_title.substr(tab_prefix.length());
1860        if (prerender_page_title.compare(tab_page_title) == 0)
1861          ++num_tabs_with_prerender_page_title;
1862      }
1863    }
1864  }
1865  EXPECT_EQ(0, num_prerender_tabs);
1866
1867  // We may have deleted the prerender tab, but the swapped in tab should be
1868  // active.
1869  EXPECT_GE(num_tabs_with_prerender_page_title, 1);
1870  EXPECT_LE(num_tabs_with_prerender_page_title, 2);
1871}
1872
1873// Checks that audio loads are deferred on prerendering.
1874// Times out under AddressSanitizer, see http://crbug.com/108402
1875#if defined(ADDRESS_SANITIZER)
1876#define MAYBE_PrerenderHTML5Audio DISABLED_PrerenderHTML5Audio
1877#else
1878#define MAYBE_PrerenderHTML5Audio PrerenderHTML5Audio
1879#endif
1880IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MAYBE_PrerenderHTML5Audio) {
1881  PrerenderTestURL("files/prerender/prerender_html5_audio.html",
1882                  FINAL_STATUS_USED,
1883                  1);
1884  NavigateToDestUrlAndWaitForPassTitle();
1885}
1886
1887// Checks that audio loads are deferred on prerendering and played back when
1888// the prerender is swapped in if autoplay is set.
1889// Periodically fails on chrome-os.  See http://crbug.com/145263
1890#if defined(OS_CHROMEOS)
1891#define MAYBE_PrerenderHTML5AudioAutoplay DISABLED_PrerenderHTML5AudioAutoplay
1892#else
1893#define MAYBE_PrerenderHTML5AudioAutoplay PrerenderHTML5AudioAutoplay
1894#endif
1895IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1896                       MAYBE_PrerenderHTML5AudioAutoplay) {
1897  PrerenderTestURL("files/prerender/prerender_html5_audio_autoplay.html",
1898                   FINAL_STATUS_USED,
1899                   1);
1900  NavigateToDestUrlAndWaitForPassTitle();
1901}
1902
1903// Checks that audio loads are deferred on prerendering and played back when
1904// the prerender is swapped in if js starts playing.
1905IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5AudioJsplay) {
1906  PrerenderTestURL("files/prerender/prerender_html5_audio_jsplay.html",
1907                   FINAL_STATUS_USED,
1908                   1);
1909  NavigateToDestUrlAndWaitForPassTitle();
1910}
1911
1912// Checks that video loads are deferred on prerendering.
1913IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5Video) {
1914  PrerenderTestURL("files/prerender/prerender_html5_video.html",
1915                   FINAL_STATUS_USED,
1916                   1);
1917  NavigateToDestUrlAndWaitForPassTitle();
1918}
1919
1920// Checks that video tags inserted by javascript are deferred and played
1921// correctly on swap in.
1922IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5VideoJs) {
1923  PrerenderTestURL("files/prerender/prerender_html5_video_script.html",
1924                   FINAL_STATUS_USED,
1925                   1);
1926  NavigateToDestUrlAndWaitForPassTitle();
1927}
1928
1929// Checks for correct network events by using a busy sleep the javascript.
1930IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5VideoNetwork) {
1931  PrerenderTestURL("files/prerender/prerender_html5_video_network.html",
1932                   FINAL_STATUS_USED,
1933                   1,
1934                   true);
1935  NavigateToDestUrlAndWaitForPassTitle();
1936}
1937
1938// Checks that scripts can retrieve the correct window size while prerendering.
1939#if defined(TOOLKIT_VIEWS)
1940// TODO(beng): Widget hierarchy split causes this to fail http://crbug.com/82363
1941IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderWindowSize) {
1942#else
1943IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderWindowSize) {
1944#endif
1945  PrerenderTestURL("files/prerender/prerender_size.html",
1946                   FINAL_STATUS_USED,
1947                   1);
1948  NavigateToDestURL();
1949}
1950
1951#if defined(OS_CHROMEOS)
1952// Flakily times out: http://crbug.com/171546
1953#define MAYBE_PrerenderRendererCrash DISABLED_PrerenderRendererCrash
1954#else
1955#define MAYBE_PrerenderRendererCrash PrerenderRendererCrash
1956#endif
1957
1958// Checks that prerenderers will terminate when the RenderView crashes.
1959IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MAYBE_PrerenderRendererCrash) {
1960  PrerenderTestURL("files/prerender/prerender_page.html",
1961                   FINAL_STATUS_RENDERER_CRASHED,
1962                   1);
1963
1964  // Navigate to about:crash and then wait for the renderer to crash.
1965  ASSERT_TRUE(GetPrerenderContents());
1966  ASSERT_TRUE(GetPrerenderContents()->prerender_contents());
1967  GetPrerenderContents()->prerender_contents()->GetController().
1968      LoadURL(
1969          GURL(content::kChromeUICrashURL),
1970          content::Referrer(),
1971          content::PAGE_TRANSITION_TYPED,
1972          std::string());
1973  content::RunMessageLoop();
1974}
1975
1976IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1977                       PrerenderPageWithFragment) {
1978  PrerenderTestURL("files/prerender/prerender_page.html#fragment",
1979                   FINAL_STATUS_USED,
1980                   1);
1981
1982  ChannelDestructionWatcher channel_close_watcher;
1983  channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
1984      GetActiveWebContents()->GetRenderProcessHost());
1985  NavigateToDestURL();
1986  channel_close_watcher.WaitForChannelClose();
1987
1988  ASSERT_TRUE(IsEmptyPrerenderLinkManager());
1989}
1990
1991// Checks that we correctly use a prerendered page when navigating to a
1992// fragment.
1993// DISABLED: http://crbug.com/84154
1994IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
1995                       DISABLED_PrerenderPageNavigateFragment) {
1996  PrerenderTestURL("files/prerender/no_prerender_page.html",
1997                   FINAL_STATUS_APP_TERMINATING,
1998                   1);
1999  NavigateToURL("files/prerender/no_prerender_page.html#fragment");
2000}
2001
2002// Checks that we correctly use a prerendered page when we prerender a fragment
2003// but navigate to the main page.
2004// http://crbug.com/83901
2005IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2006                       DISABLED_PrerenderFragmentNavigatePage) {
2007  PrerenderTestURL("files/prerender/no_prerender_page.html#fragment",
2008                   FINAL_STATUS_APP_TERMINATING,
2009                   1);
2010  NavigateToURL("files/prerender/no_prerender_page.html");
2011}
2012
2013// Checks that we correctly use a prerendered page when we prerender a fragment
2014// but navigate to a different fragment on the same page.
2015// DISABLED: http://crbug.com/84154
2016IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2017                       DISABLED_PrerenderFragmentNavigateFragment) {
2018  PrerenderTestURL("files/prerender/no_prerender_page.html#other_fragment",
2019                   FINAL_STATUS_APP_TERMINATING,
2020                   1);
2021  NavigateToURL("files/prerender/no_prerender_page.html#fragment");
2022}
2023
2024// Checks that we correctly use a prerendered page when the page uses a client
2025// redirect to refresh from a fragment on the same page.
2026// http://crbug.com/83901
2027IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2028                       DISABLED_PrerenderClientRedirectFromFragment) {
2029  PrerenderTestURL(
2030      CreateClientRedirect("files/prerender/no_prerender_page.html#fragment"),
2031      FINAL_STATUS_APP_TERMINATING,
2032      2);
2033  NavigateToURL("files/prerender/no_prerender_page.html");
2034}
2035
2036// Checks that we correctly use a prerendered page when the page uses a client
2037// redirect to refresh to a fragment on the same page.
2038// DISABLED: http://crbug.com/84154
2039IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2040                       DISABLED_PrerenderClientRedirectToFragment) {
2041  PrerenderTestURL(
2042      CreateClientRedirect("files/prerender/no_prerender_page.html"),
2043      FINAL_STATUS_APP_TERMINATING,
2044      2);
2045  NavigateToURL("files/prerender/no_prerender_page.html#fragment");
2046}
2047
2048// Checks that we correctly use a prerendered page when the page uses JS to set
2049// the window.location.hash to a fragment on the same page.
2050IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2051                       PrerenderPageChangeFragmentLocationHash) {
2052  PrerenderTestURL("files/prerender/prerender_fragment_location_hash.html",
2053                   FINAL_STATUS_USED,
2054                   1);
2055  NavigateToURL("files/prerender/prerender_fragment_location_hash.html");
2056}
2057
2058// Checks that prerendering a PNG works correctly.
2059IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderImagePng) {
2060  DisableJavascriptCalls();
2061  PrerenderTestURL("files/prerender/image.png", FINAL_STATUS_USED, 1);
2062  NavigateToDestURL();
2063}
2064
2065// Checks that prerendering a JPG works correctly.
2066IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderImageJpeg) {
2067  DisableJavascriptCalls();
2068  PrerenderTestURL("files/prerender/image.jpeg", FINAL_STATUS_USED, 1);
2069  NavigateToDestURL();
2070}
2071
2072// Checks that a prerender of a CRX will result in a cancellation due to
2073// download.
2074IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCrx) {
2075  PrerenderTestURL("files/prerender/extension.crx", FINAL_STATUS_DOWNLOAD, 1);
2076}
2077
2078// Checks that xhr GET requests allow prerenders.
2079IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrGet) {
2080  PrerenderTestURL("files/prerender/prerender_xhr_get.html",
2081                   FINAL_STATUS_USED,
2082                   1);
2083  NavigateToDestURL();
2084}
2085
2086// Checks that xhr HEAD requests allow prerenders.
2087IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrHead) {
2088  PrerenderTestURL("files/prerender/prerender_xhr_head.html",
2089                   FINAL_STATUS_USED,
2090                   1);
2091  NavigateToDestURL();
2092}
2093
2094// Checks that xhr OPTIONS requests allow prerenders.
2095IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrOptions) {
2096  PrerenderTestURL("files/prerender/prerender_xhr_options.html",
2097                   FINAL_STATUS_USED,
2098                   1);
2099  NavigateToDestURL();
2100}
2101
2102// Checks that xhr TRACE requests allow prerenders.
2103IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrTrace) {
2104  PrerenderTestURL("files/prerender/prerender_xhr_trace.html",
2105                   FINAL_STATUS_USED,
2106                   1);
2107  NavigateToDestURL();
2108}
2109
2110// Checks that xhr POST requests allow prerenders.
2111IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrPost) {
2112  PrerenderTestURL("files/prerender/prerender_xhr_post.html",
2113                   FINAL_STATUS_USED,
2114                   1);
2115  NavigateToDestURL();
2116}
2117
2118// Checks that xhr PUT cancels prerenders.
2119IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrPut) {
2120  PrerenderTestURL("files/prerender/prerender_xhr_put.html",
2121                   FINAL_STATUS_INVALID_HTTP_METHOD,
2122                   1);
2123}
2124
2125// Checks that xhr DELETE cancels prerenders.
2126IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrDelete) {
2127  PrerenderTestURL("files/prerender/prerender_xhr_delete.html",
2128                   FINAL_STATUS_INVALID_HTTP_METHOD,
2129                   1);
2130}
2131
2132// Checks that a top-level page which would trigger an SSL error is canceled.
2133IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorTopLevel) {
2134  net::SpawnedTestServer::SSLOptions ssl_options;
2135  ssl_options.server_certificate =
2136      net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
2137    net::SpawnedTestServer https_server(
2138        net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
2139        base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2140  ASSERT_TRUE(https_server.Start());
2141  GURL https_url = https_server.GetURL("files/prerender/prerender_page.html");
2142  PrerenderTestURL(https_url,
2143                   FINAL_STATUS_SSL_ERROR,
2144                   1);
2145}
2146
2147// Checks that an SSL error that comes from a subresource does not cancel
2148// the page. Non-main-frame requests are simply cancelled if they run into
2149// an SSL problem.
2150IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorSubresource) {
2151  net::SpawnedTestServer::SSLOptions ssl_options;
2152  ssl_options.server_certificate =
2153      net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
2154    net::SpawnedTestServer https_server(
2155        net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
2156        base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2157  ASSERT_TRUE(https_server.Start());
2158  GURL https_url = https_server.GetURL("files/prerender/image.jpeg");
2159  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
2160  replacement_text.push_back(
2161      std::make_pair("REPLACE_WITH_IMAGE_URL", https_url.spec()));
2162  std::string replacement_path;
2163  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2164      "files/prerender/prerender_with_image.html",
2165      replacement_text,
2166      &replacement_path));
2167  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
2168  NavigateToDestURL();
2169}
2170
2171// Checks that an SSL error that comes from an iframe does not cancel
2172// the page. Non-main-frame requests are simply cancelled if they run into
2173// an SSL problem.
2174IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorIframe) {
2175  net::SpawnedTestServer::SSLOptions ssl_options;
2176  ssl_options.server_certificate =
2177      net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME;
2178    net::SpawnedTestServer https_server(
2179        net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
2180        base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2181  ASSERT_TRUE(https_server.Start());
2182  GURL https_url = https_server.GetURL(
2183      "files/prerender/prerender_embedded_content.html");
2184  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
2185  replacement_text.push_back(
2186      std::make_pair("REPLACE_WITH_URL", https_url.spec()));
2187  std::string replacement_path;
2188  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2189      "files/prerender/prerender_with_iframe.html",
2190      replacement_text,
2191      &replacement_path));
2192  PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1);
2193  NavigateToDestURL();
2194}
2195
2196// Checks that we cancel correctly when window.print() is called.
2197IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPrint) {
2198  PrerenderTestURL("files/prerender/prerender_print.html",
2199                   FINAL_STATUS_WINDOW_PRINT,
2200                   1);
2201}
2202
2203// Checks that if a page is opened in a new window by javascript and both the
2204// pages are in the same domain, the prerendered page is not used.
2205IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2206                       PrerenderSameDomainWindowOpenerWindowOpen) {
2207  PrerenderTestURL("files/prerender/prerender_page.html",
2208                   FINAL_STATUS_APP_TERMINATING,
2209                   1);
2210  OpenDestURLViaWindowOpen();
2211}
2212
2213// Checks that if a page is opened due to click on a href with target="_blank"
2214// and both pages are in the same domain the prerendered page is not used.
2215IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2216                       PrerenderSameDomainWindowOpenerClickTarget) {
2217  PrerenderTestURL("files/prerender/prerender_page.html",
2218                   FINAL_STATUS_APP_TERMINATING,
2219                   1);
2220  OpenDestURLViaClickTarget();
2221}
2222
2223// Checks that a top-level page which would normally request an SSL client
2224// certificate will never be seen since it's an https top-level resource.
2225IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLClientCertTopLevel) {
2226  net::SpawnedTestServer::SSLOptions ssl_options;
2227  ssl_options.request_client_certificate = true;
2228    net::SpawnedTestServer https_server(
2229        net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
2230        base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2231  ASSERT_TRUE(https_server.Start());
2232  GURL https_url = https_server.GetURL("files/prerender/prerender_page.html");
2233  PrerenderTestURL(https_url, FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED, 1);
2234}
2235
2236// Checks that an SSL Client Certificate request that originates from a
2237// subresource will cancel the prerendered page.
2238IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2239                       PrerenderSSLClientCertSubresource) {
2240  net::SpawnedTestServer::SSLOptions ssl_options;
2241  ssl_options.request_client_certificate = true;
2242    net::SpawnedTestServer https_server(
2243        net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
2244        base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2245  ASSERT_TRUE(https_server.Start());
2246  GURL https_url = https_server.GetURL("files/prerender/image.jpeg");
2247  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
2248  replacement_text.push_back(
2249      std::make_pair("REPLACE_WITH_IMAGE_URL", https_url.spec()));
2250  std::string replacement_path;
2251  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2252      "files/prerender/prerender_with_image.html",
2253      replacement_text,
2254      &replacement_path));
2255  PrerenderTestURL(replacement_path,
2256                   FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED,
2257                   1);
2258}
2259
2260// Checks that an SSL Client Certificate request that originates from an
2261// iframe will cancel the prerendered page.
2262IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLClientCertIframe) {
2263  net::SpawnedTestServer::SSLOptions ssl_options;
2264  ssl_options.request_client_certificate = true;
2265    net::SpawnedTestServer https_server(
2266        net::SpawnedTestServer::TYPE_HTTPS, ssl_options,
2267        base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
2268  ASSERT_TRUE(https_server.Start());
2269  GURL https_url = https_server.GetURL(
2270      "files/prerender/prerender_embedded_content.html");
2271  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
2272  replacement_text.push_back(
2273      std::make_pair("REPLACE_WITH_URL", https_url.spec()));
2274  std::string replacement_path;
2275  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2276      "files/prerender/prerender_with_iframe.html",
2277      replacement_text,
2278      &replacement_path));
2279  PrerenderTestURL(replacement_path,
2280                   FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED,
2281                   1);
2282}
2283
2284#if defined(FULL_SAFE_BROWSING)
2285// Ensures that we do not prerender pages with a safe browsing
2286// interstitial.
2287IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSafeBrowsingTopLevel) {
2288  GURL url = test_server()->GetURL("files/prerender/prerender_page.html");
2289  GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
2290      url, SB_THREAT_TYPE_URL_MALWARE);
2291  PrerenderTestURL("files/prerender/prerender_page.html",
2292                   FINAL_STATUS_SAFE_BROWSING, 1);
2293}
2294
2295// Ensures that server redirects to a malware page will cancel prerenders.
2296IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2297                       PrerenderSafeBrowsingServerRedirect) {
2298  GURL url = test_server()->GetURL("files/prerender/prerender_page.html");
2299  GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
2300      url, SB_THREAT_TYPE_URL_MALWARE);
2301  PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"),
2302                   FINAL_STATUS_SAFE_BROWSING,
2303                   1);
2304}
2305
2306// Ensures that client redirects to a malware page will cancel prerenders.
2307IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2308                       PrerenderSafeBrowsingClientRedirect) {
2309  GURL url = test_server()->GetURL("files/prerender/prerender_page.html");
2310  GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
2311      url, SB_THREAT_TYPE_URL_MALWARE);
2312  PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"),
2313                   FINAL_STATUS_SAFE_BROWSING,
2314                   1);
2315}
2316
2317// Ensures that we do not prerender pages which have a malware subresource.
2318IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSafeBrowsingSubresource) {
2319  GURL image_url = test_server()->GetURL("files/prerender/image.jpeg");
2320  GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
2321      image_url, SB_THREAT_TYPE_URL_MALWARE);
2322  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
2323  replacement_text.push_back(
2324      std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
2325  std::string replacement_path;
2326  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2327      "files/prerender/prerender_with_image.html",
2328      replacement_text,
2329      &replacement_path));
2330  PrerenderTestURL(replacement_path,
2331                   FINAL_STATUS_SAFE_BROWSING,
2332                   1);
2333}
2334
2335// Ensures that we do not prerender pages which have a malware iframe.
2336IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSafeBrowsingIframe) {
2337  GURL iframe_url = test_server()->GetURL(
2338      "files/prerender/prerender_embedded_content.html");
2339  GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl(
2340      iframe_url, SB_THREAT_TYPE_URL_MALWARE);
2341  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
2342  replacement_text.push_back(
2343      std::make_pair("REPLACE_WITH_URL", iframe_url.spec()));
2344  std::string replacement_path;
2345  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2346      "files/prerender/prerender_with_iframe.html",
2347      replacement_text,
2348      &replacement_path));
2349  PrerenderTestURL(replacement_path,
2350                   FINAL_STATUS_SAFE_BROWSING,
2351                   1);
2352}
2353
2354#endif
2355
2356// Checks that a local storage read will not cause prerender to fail.
2357IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderLocalStorageRead) {
2358  PrerenderTestURL("files/prerender/prerender_localstorage_read.html",
2359                   FINAL_STATUS_USED,
2360                   1);
2361  NavigateToDestURL();
2362}
2363
2364// Checks that a local storage write will not cause prerender to fail.
2365IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderLocalStorageWrite) {
2366  PrerenderTestURL("files/prerender/prerender_localstorage_write.html",
2367                   FINAL_STATUS_USED,
2368                   1);
2369  NavigateToDestURL();
2370}
2371
2372// Checks that the favicon is properly loaded on prerender.
2373IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderFavicon) {
2374  PrerenderTestURL("files/prerender/prerender_favicon.html",
2375                   FINAL_STATUS_USED,
2376                   1);
2377  TestPrerenderContents* prerender_contents = GetPrerenderContents();
2378  ASSERT_TRUE(prerender_contents != NULL);
2379  content::WindowedNotificationObserver favicon_update_watcher(
2380      chrome::NOTIFICATION_FAVICON_UPDATED,
2381      content::Source<WebContents>(prerender_contents->prerender_contents()));
2382  NavigateToDestURL();
2383  favicon_update_watcher.Wait();
2384}
2385
2386// Checks that when a prerendered page is swapped in to a referring page, the
2387// unload handlers on the referring page are executed.
2388// Fails about 50% on CrOS, 5-10% on linux, win, mac. http://crbug.com/128986
2389IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderUnload) {
2390  set_loader_path("files/prerender/prerender_loader_with_unload.html");
2391  PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
2392  string16 expected_title = ASCIIToUTF16("Unloaded");
2393  content::TitleWatcher title_watcher(
2394      current_browser()->tab_strip_model()->GetActiveWebContents(),
2395      expected_title);
2396  NavigateToDestURL();
2397  EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
2398}
2399
2400// Checks that when the history is cleared, prerendering is cancelled and
2401// prerendering history is cleared.
2402IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClearHistory) {
2403  PrerenderTestURL("files/prerender/prerender_page.html",
2404                   FINAL_STATUS_CACHE_OR_HISTORY_CLEARED,
2405                   1);
2406
2407  // Post a task to clear the history, and run the message loop until it
2408  // destroys the prerender.
2409  base::MessageLoop::current()->PostTask(
2410      FROM_HERE,
2411      base::Bind(&ClearBrowsingData, current_browser(),
2412                 BrowsingDataRemover::REMOVE_HISTORY));
2413  content::RunMessageLoop();
2414
2415  // Make sure prerender history was cleared.
2416  EXPECT_EQ(0, GetHistoryLength());
2417}
2418
2419// Checks that when the cache is cleared, prerenders are cancelled but
2420// prerendering history is not cleared.
2421IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClearCache) {
2422  PrerenderTestURL("files/prerender/prerender_page.html",
2423                   FINAL_STATUS_CACHE_OR_HISTORY_CLEARED,
2424                   1);
2425
2426  // Post a task to clear the cache, and run the message loop until it
2427  // destroys the prerender.
2428  base::MessageLoop::current()->PostTask(FROM_HERE,
2429      base::Bind(&ClearBrowsingData, current_browser(),
2430                 BrowsingDataRemover::REMOVE_CACHE));
2431  content::RunMessageLoop();
2432
2433  // Make sure prerender history was not cleared.  Not a vital behavior, but
2434  // used to compare with PrerenderClearHistory test.
2435  EXPECT_EQ(1, GetHistoryLength());
2436}
2437
2438IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelAll) {
2439  PrerenderTestURL("files/prerender/prerender_page.html",
2440                   FINAL_STATUS_CANCELLED,
2441                   1);
2442  // Post a task to cancel all the prerenders.
2443  base::MessageLoop::current()->PostTask(
2444      FROM_HERE, base::Bind(&CancelAllPrerenders, GetPrerenderManager()));
2445  content::RunMessageLoop();
2446  EXPECT_TRUE(GetPrerenderContents() == NULL);
2447}
2448
2449IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderEvents) {
2450  PrerenderTestURL("files/prerender/prerender_page.html",
2451                   FINAL_STATUS_CANCELLED, 1);
2452  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
2453  EXPECT_TRUE(DidReceivePrerenderLoadEventForLinkNumber(0));
2454  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
2455
2456  base::MessageLoop::current()->PostTask(
2457      FROM_HERE, base::Bind(&CancelAllPrerenders, GetPrerenderManager()));
2458  content::RunMessageLoop();
2459
2460  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
2461  EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(0));
2462  EXPECT_FALSE(HadPrerenderEventErrors());
2463}
2464
2465// Cancels the prerender of a page with its own prerender.  The second prerender
2466// should never be started.
2467IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2468                       PrerenderCancelPrerenderWithPrerender) {
2469  PrerenderTestURL("files/prerender/prerender_infinite_a.html",
2470                   FINAL_STATUS_CANCELLED,
2471                   1);
2472  // Post a task to cancel all the prerenders.
2473  base::MessageLoop::current()->PostTask(
2474      FROM_HERE, base::Bind(&CancelAllPrerenders, GetPrerenderManager()));
2475  content::RunMessageLoop();
2476  EXPECT_TRUE(GetPrerenderContents() == NULL);
2477}
2478
2479// PrerenderBrowserTest.PrerenderEventsNoLoad may pass flakily on regression,
2480// so please be aggressive about filing bugs when this test is failing.
2481IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderEventsNoLoad) {
2482  // This should be canceled.
2483  PrerenderTestURL("files/prerender/prerender_http_auth_container.html",
2484                   FINAL_STATUS_AUTH_NEEDED,
2485                   1);
2486  EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0));
2487  EXPECT_FALSE(DidReceivePrerenderLoadEventForLinkNumber(0));
2488  EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0));
2489  EXPECT_FALSE(HadPrerenderEventErrors());
2490}
2491
2492// Prerendering and history tests.
2493// The prerendered page is navigated to in several ways [navigate via
2494// omnibox, click on link, key-modified click to open in background tab, etc],
2495// followed by a navigation to another page from the prerendered page, followed
2496// by a back navigation.
2497
2498IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNavigateClickGoBack) {
2499  PrerenderTestURL("files/prerender/prerender_page_with_link.html",
2500                   FINAL_STATUS_USED,
2501                   1);
2502  NavigateToDestURL();
2503  ClickToNextPageAfterPrerender();
2504  GoBackToPrerender();
2505}
2506
2507// Disabled due to timeouts on commit queue.
2508// http://crbug.com/121130
2509IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2510                       DISABLED_PrerenderNavigateNavigateGoBack) {
2511  PrerenderTestURL("files/prerender/prerender_page_with_link.html",
2512                   FINAL_STATUS_USED,
2513                   1);
2514  NavigateToDestURL();
2515  NavigateToNextPageAfterPrerender();
2516  GoBackToPrerender();
2517}
2518
2519IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickClickGoBack) {
2520  PrerenderTestURL("files/prerender/prerender_page_with_link.html",
2521                   FINAL_STATUS_USED,
2522                   1);
2523  OpenDestURLViaClick();
2524  ClickToNextPageAfterPrerender();
2525  GoBackToPrerender();
2526}
2527
2528// Disabled due to timeouts on commit queue.
2529// http://crbug.com/121130
2530IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2531                       DISABLED_PrerenderClickNavigateGoBack) {
2532  PrerenderTestURL("files/prerender/prerender_page_with_link.html",
2533                   FINAL_STATUS_USED,
2534                   1);
2535  OpenDestURLViaClick();
2536  NavigateToNextPageAfterPrerender();
2537  GoBackToPrerender();
2538}
2539
2540IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewWindow) {
2541  PrerenderTestURL("files/prerender/prerender_page_with_link.html",
2542                   FINAL_STATUS_APP_TERMINATING,
2543                   1);
2544  OpenDestURLViaClickNewWindow();
2545}
2546
2547IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewForegroundTab) {
2548  PrerenderTestURL("files/prerender/prerender_page_with_link.html",
2549                   FINAL_STATUS_APP_TERMINATING,
2550                   1);
2551  OpenDestURLViaClickNewForegroundTab();
2552}
2553
2554IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewBackgroundTab) {
2555  PrerenderTestURL("files/prerender/prerender_page_with_link.html",
2556                   FINAL_STATUS_APP_TERMINATING,
2557                   1);
2558  OpenDestURLViaClickNewBackgroundTab();
2559}
2560
2561IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2562                       NavigateToPrerenderedPageWhenDevToolsAttached) {
2563  DisableJavascriptCalls();
2564  WebContents* web_contents =
2565      current_browser()->tab_strip_model()->GetActiveWebContents();
2566  scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetOrCreateFor(
2567      web_contents->GetRenderViewHost()));
2568  DevToolsManager* manager = DevToolsManager::GetInstance();
2569  FakeDevToolsClientHost client_host;
2570  manager->RegisterDevToolsClientHostFor(agent, &client_host);
2571  const char* url = "files/prerender/prerender_page.html";
2572  PrerenderTestURL(url, FINAL_STATUS_DEVTOOLS_ATTACHED, 1);
2573  NavigateToURL(url);
2574  manager->ClientHostClosing(&client_host);
2575}
2576
2577// Validate that the sessionStorage namespace remains the same when swapping
2578// in a prerendered page.
2579IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSessionStorage) {
2580  set_loader_path("files/prerender/prerender_loader_with_session_storage.html");
2581  PrerenderTestURL(GetCrossDomainTestUrl("files/prerender/prerender_page.html"),
2582                   FINAL_STATUS_USED,
2583                   1);
2584  NavigateToDestURL();
2585  GoBackToPageBeforePrerender();
2586}
2587
2588#if defined(OS_MACOSX)
2589// http://crbug.com/142535 - Times out on Chrome Mac release builder
2590#define MAYBE_ControlGroup DISABLED_ControlGroup
2591#else
2592#define MAYBE_ControlGroup ControlGroup
2593#endif
2594// Checks that the control group works.  A JS alert cannot be detected in the
2595// control group.
2596IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MAYBE_ControlGroup) {
2597  RestorePrerenderMode restore_prerender_mode;
2598  PrerenderManager::SetMode(
2599      PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP);
2600  PrerenderTestURL("files/prerender/prerender_alert_before_onload.html",
2601                   FINAL_STATUS_WOULD_HAVE_BEEN_USED, 0);
2602  NavigateToDestURL();
2603}
2604
2605// Make sure that the MatchComplete dummy works in the normal case.  Once
2606// a prerender is cancelled because of a script, a dummy must be created to
2607// account for the MatchComplete case, and it must have a final status of
2608// FINAL_STATUS_WOULD_HAVE_BEEN_USED.
2609#if defined(OS_MACOSX)
2610// http://crbug.com/142912 - Times out on Chrome Mac release builder
2611#define MAYBE_MatchCompleteDummy DISABLED_MatchCompleteDummy
2612#else
2613#define MAYBE_MatchCompleteDummy MatchCompleteDummy
2614#endif
2615IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MAYBE_MatchCompleteDummy) {
2616  std::deque<FinalStatus> expected_final_status_queue;
2617  expected_final_status_queue.push_back(FINAL_STATUS_JAVASCRIPT_ALERT);
2618  expected_final_status_queue.push_back(FINAL_STATUS_WOULD_HAVE_BEEN_USED);
2619  PrerenderTestURL("files/prerender/prerender_alert_before_onload.html",
2620                   expected_final_status_queue, 1);
2621  NavigateToDestURL();
2622}
2623
2624class PrerenderBrowserTestWithNaCl : public PrerenderBrowserTest {
2625 public:
2626  PrerenderBrowserTestWithNaCl() {}
2627  virtual ~PrerenderBrowserTestWithNaCl() {}
2628
2629  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
2630    PrerenderBrowserTest::SetUpCommandLine(command_line);
2631    command_line->AppendSwitch(switches::kEnableNaCl);
2632  }
2633};
2634
2635// Check that NaCl plugins work when enabled, with prerendering.
2636IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithNaCl,
2637                       PrerenderNaClPluginEnabled) {
2638  PrerenderTestURL("files/prerender/prerender_plugin_nacl_enabled.html",
2639                   FINAL_STATUS_USED,
2640                   1);
2641  NavigateToDestURL();
2642
2643  // To avoid any chance of a race, we have to let the script send its response
2644  // asynchronously.
2645  WebContents* web_contents =
2646      browser()->tab_strip_model()->GetActiveWebContents();
2647  bool display_test_result = false;
2648  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents,
2649                                                   "DidDisplayReallyPass()",
2650                                                   &display_test_result));
2651  ASSERT_TRUE(display_test_result);
2652}
2653
2654// Checks that the referrer policy is used when prerendering.
2655IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReferrerPolicy) {
2656  set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html");
2657  PrerenderTestURL("files/prerender/prerender_referrer_policy.html",
2658                   FINAL_STATUS_USED,
2659                   1);
2660  NavigateToDestURL();
2661}
2662
2663// Checks that the referrer policy is used when prerendering on HTTPS.
2664IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLReferrerPolicy) {
2665  set_use_https_src(true);
2666  set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html");
2667  PrerenderTestURL("files/prerender/prerender_referrer_policy.html",
2668                   FINAL_STATUS_USED,
2669                   1);
2670  NavigateToDestURL();
2671}
2672
2673// Test interaction of the webNavigation and tabs API with prerender.
2674class PrerenderBrowserTestWithExtensions : public PrerenderBrowserTest,
2675                                           public ExtensionApiTest {
2676 public:
2677  PrerenderBrowserTestWithExtensions() {
2678    autostart_test_server_ = false;
2679  }
2680  virtual ~PrerenderBrowserTestWithExtensions() {}
2681
2682  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
2683    PrerenderBrowserTest::SetUpCommandLine(command_line);
2684    ExtensionApiTest::SetUpCommandLine(command_line);
2685  }
2686
2687  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
2688    PrerenderBrowserTest::SetUpInProcessBrowserTestFixture();
2689    ExtensionApiTest::SetUpInProcessBrowserTestFixture();
2690  }
2691
2692  virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
2693    PrerenderBrowserTest::TearDownInProcessBrowserTestFixture();
2694    ExtensionApiTest::TearDownInProcessBrowserTestFixture();
2695  }
2696
2697  virtual void SetUpOnMainThread() OVERRIDE {
2698    PrerenderBrowserTest::SetUpOnMainThread();
2699  }
2700};
2701
2702IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, WebNavigation) {
2703  ASSERT_TRUE(StartTestServer());
2704  extensions::FrameNavigationState::set_allow_extension_scheme(true);
2705
2706  CommandLine::ForCurrentProcess()->AppendSwitch(
2707      switches::kAllowLegacyExtensionManifests);
2708
2709  // Wait for the extension to set itself up and return control to us.
2710  ASSERT_TRUE(
2711      RunExtensionSubtest("webnavigation", "test_prerender.html")) << message_;
2712
2713  ResultCatcher catcher;
2714
2715  PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
2716
2717  ChannelDestructionWatcher channel_close_watcher;
2718  channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
2719      GetActiveWebContents()->GetRenderProcessHost());
2720  NavigateToDestURL();
2721  channel_close_watcher.WaitForChannelClose();
2722
2723  ASSERT_TRUE(IsEmptyPrerenderLinkManager());
2724  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
2725}
2726
2727// Fails often on Windows dbg bots. http://crbug.com/177163
2728#if defined(OS_WIN)
2729#define MAYBE_TabsApi DISABLED_TabsApi
2730#else
2731#define MAYBE_TabsApi TabsApi
2732#endif  // defined(OS_WIN)
2733IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, MAYBE_TabsApi) {
2734  ASSERT_TRUE(StartTestServer());
2735  extensions::FrameNavigationState::set_allow_extension_scheme(true);
2736
2737  // Wait for the extension to set itself up and return control to us.
2738  ASSERT_TRUE(RunExtensionSubtest("tabs/on_replaced", "on_replaced.html"))
2739      << message_;
2740
2741  ResultCatcher catcher;
2742
2743  PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1);
2744
2745  ChannelDestructionWatcher channel_close_watcher;
2746  channel_close_watcher.WatchChannel(browser()->tab_strip_model()->
2747      GetActiveWebContents()->GetRenderProcessHost());
2748  NavigateToDestURL();
2749  channel_close_watcher.WaitForChannelClose();
2750
2751  ASSERT_TRUE(IsEmptyPrerenderLinkManager());
2752  ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
2753}
2754
2755// Checks that non-http/https subresource cancels the prerender.
2756IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2757                       PrerenderCancelSubresourceUnsupportedScheme) {
2758  GURL image_url = GURL("invalidscheme://www.google.com/test.jpg");
2759  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
2760  replacement_text.push_back(
2761      std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
2762  std::string replacement_path;
2763  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2764      "files/prerender/prerender_with_image.html",
2765      replacement_text,
2766      &replacement_path));
2767  PrerenderTestURL(replacement_path, FINAL_STATUS_UNSUPPORTED_SCHEME, 1);
2768  NavigateToDestURL();
2769}
2770
2771// Checks that non-http/https subresource cancels the prerender on redirect.
2772IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2773                       PrerenderCancelSubresourceRedirectUnsupportedScheme) {
2774  GURL image_url = test_server()->GetURL(
2775      CreateServerRedirect("invalidscheme://www.google.com/test.jpg"));
2776  std::vector<net::SpawnedTestServer::StringPair> replacement_text;
2777  replacement_text.push_back(
2778      std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec()));
2779  std::string replacement_path;
2780  ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements(
2781      "files/prerender/prerender_with_image.html",
2782      replacement_text,
2783      &replacement_path));
2784  PrerenderTestURL(replacement_path, FINAL_STATUS_UNSUPPORTED_SCHEME, 1);
2785  NavigateToDestURL();
2786}
2787
2788// Checks that non-http/https main page redirects cancel the prerender.
2789IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
2790                       PrerenderCancelMainFrameRedirectUnsupportedScheme) {
2791  GURL url = test_server()->GetURL(
2792      CreateServerRedirect("invalidscheme://www.google.com/test.html"));
2793  PrerenderTestURL(url, FINAL_STATUS_UNSUPPORTED_SCHEME, 1);
2794  NavigateToDestURL();
2795}
2796
2797}  // namespace prerender
2798