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