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