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