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