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