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