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