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