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