prerender_browsertest.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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 case FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE: 170 return false; 171 default: 172 return true; 173 } 174} 175 176// Convenience function to wait for a title. Handles the case when the 177// WebContents already has the expected title. 178void WaitForASCIITitle(WebContents* web_contents, 179 const char* expected_title_ascii) { 180 base::string16 expected_title = base::ASCIIToUTF16(expected_title_ascii); 181 if (web_contents->GetTitle() == expected_title) 182 return; 183 content::TitleWatcher title_watcher(web_contents, expected_title); 184 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); 185} 186 187// Waits for the destruction of a RenderProcessHost's IPC channel. 188// Used to make sure the PrerenderLinkManager's OnChannelClosed function has 189// been called, before checking its state. 190class ChannelDestructionWatcher { 191 public: 192 ChannelDestructionWatcher() : channel_destroyed_(false) { 193 } 194 195 ~ChannelDestructionWatcher() { 196 } 197 198 void WatchChannel(content::RenderProcessHost* host) { 199 host->AddFilter(new DestructionMessageFilter(this)); 200 } 201 202 void WaitForChannelClose() { 203 run_loop_.Run(); 204 EXPECT_TRUE(channel_destroyed_); 205 } 206 207 private: 208 // When destroyed, calls ChannelDestructionWatcher::OnChannelDestroyed. 209 // Ignores all messages. 210 class DestructionMessageFilter : public content::BrowserMessageFilter { 211 public: 212 explicit DestructionMessageFilter(ChannelDestructionWatcher* watcher) 213 : BrowserMessageFilter(0), 214 watcher_(watcher) { 215 } 216 217 private: 218 virtual ~DestructionMessageFilter() { 219 content::BrowserThread::PostTask( 220 content::BrowserThread::UI, FROM_HERE, 221 base::Bind(&ChannelDestructionWatcher::OnChannelDestroyed, 222 base::Unretained(watcher_))); 223 } 224 225 virtual bool OnMessageReceived(const IPC::Message& message) 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 // Navigates to a URL, unrelated to prerendering 1128 void NavigateStraightToURL(const std::string dest_html_file) { 1129 ui_test_utils::NavigateToURL(current_browser(), 1130 test_server()->GetURL(dest_html_file)); 1131 } 1132 1133 void NavigateToDestURL() const { 1134 NavigateToDestURLWithDisposition(CURRENT_TAB, true); 1135 } 1136 1137 // Opens the url in a new tab, with no opener. 1138 void NavigateToDestURLWithDisposition( 1139 WindowOpenDisposition disposition, 1140 bool expect_swap_to_succeed) const { 1141 NavigateToURLWithParams( 1142 content::OpenURLParams(dest_url_, Referrer(), disposition, 1143 content::PAGE_TRANSITION_TYPED, false), 1144 expect_swap_to_succeed); 1145 } 1146 1147 void NavigateToURL(const std::string& dest_html_file) const { 1148 NavigateToURLWithDisposition(dest_html_file, CURRENT_TAB, true); 1149 } 1150 1151 void NavigateToURLWithDisposition(const std::string& dest_html_file, 1152 WindowOpenDisposition disposition, 1153 bool expect_swap_to_succeed) const { 1154 GURL dest_url = test_server()->GetURL(dest_html_file); 1155 NavigateToURLWithDisposition(dest_url, disposition, expect_swap_to_succeed); 1156 } 1157 1158 void NavigateToURLWithDisposition(const GURL& dest_url, 1159 WindowOpenDisposition disposition, 1160 bool expect_swap_to_succeed) const { 1161 NavigateToURLWithParams( 1162 content::OpenURLParams(dest_url, Referrer(), disposition, 1163 content::PAGE_TRANSITION_TYPED, false), 1164 expect_swap_to_succeed); 1165 } 1166 1167 void NavigateToURLWithParams(const content::OpenURLParams& params, 1168 bool expect_swap_to_succeed) const { 1169 NavigateToURLImpl(params, expect_swap_to_succeed); 1170 } 1171 1172 void OpenDestURLViaClick() const { 1173 OpenURLViaClick(dest_url_); 1174 } 1175 1176 void OpenURLViaClick(const GURL& url) const { 1177 OpenURLWithJSImpl("Click", url, GURL(), false); 1178 } 1179 1180 void OpenDestURLViaClickTarget() const { 1181 OpenURLWithJSImpl("ClickTarget", dest_url_, GURL(), true); 1182 } 1183 1184 void OpenDestURLViaClickPing(const GURL& ping_url) const { 1185 OpenURLWithJSImpl("ClickPing", dest_url_, ping_url, false); 1186 } 1187 1188 void OpenDestURLViaClickNewWindow() const { 1189 OpenURLWithJSImpl("ShiftClick", dest_url_, GURL(), true); 1190 } 1191 1192 void OpenDestURLViaClickNewForegroundTab() const { 1193#if defined(OS_MACOSX) 1194 OpenURLWithJSImpl("MetaShiftClick", dest_url_, GURL(), true); 1195#else 1196 OpenURLWithJSImpl("CtrlShiftClick", dest_url_, GURL(), true); 1197#endif 1198 } 1199 1200 void OpenDestURLViaClickNewBackgroundTab() const { 1201#if defined(OS_MACOSX) 1202 OpenURLWithJSImpl("MetaClick", dest_url_, GURL(), true); 1203#else 1204 OpenURLWithJSImpl("CtrlClick", dest_url_, GURL(), true); 1205#endif 1206 } 1207 1208 void OpenDestURLViaWindowOpen() const { 1209 OpenURLViaWindowOpen(dest_url_); 1210 } 1211 1212 void OpenURLViaWindowOpen(const GURL& url) const { 1213 OpenURLWithJSImpl("WindowOpen", url, GURL(), true); 1214 } 1215 1216 void RemoveLinkElement(int i) const { 1217 GetActiveWebContents()->GetMainFrame()->ExecuteJavaScript( 1218 base::ASCIIToUTF16(base::StringPrintf("RemoveLinkElement(%d)", i))); 1219 } 1220 1221 void ClickToNextPageAfterPrerender() { 1222 TestNavigationObserver nav_observer(GetActiveWebContents()); 1223 RenderFrameHost* render_frame_host = GetActiveWebContents()->GetMainFrame(); 1224 render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16("ClickOpenLink()")); 1225 nav_observer.Wait(); 1226 } 1227 1228 void NavigateToNextPageAfterPrerender() const { 1229 ui_test_utils::NavigateToURL( 1230 current_browser(), 1231 test_server()->GetURL("files/prerender/prerender_page.html")); 1232 } 1233 1234 // Called after the prerendered page has been navigated to and then away from. 1235 // Navigates back through the history to the prerendered page. 1236 void GoBackToPrerender() { 1237 TestNavigationObserver back_nav_observer(GetActiveWebContents()); 1238 chrome::GoBack(current_browser(), CURRENT_TAB); 1239 back_nav_observer.Wait(); 1240 bool original_prerender_page = false; 1241 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 1242 GetActiveWebContents(), 1243 "window.domAutomationController.send(IsOriginalPrerenderPage())", 1244 &original_prerender_page)); 1245 EXPECT_TRUE(original_prerender_page); 1246 } 1247 1248 // Goes back to the page that was active before the prerender was swapped 1249 // in. This must be called when the prerendered page is the current page 1250 // in the active tab. 1251 void GoBackToPageBeforePrerender() { 1252 WebContents* tab = GetActiveWebContents(); 1253 ASSERT_TRUE(tab); 1254 EXPECT_FALSE(tab->IsLoading()); 1255 TestNavigationObserver back_nav_observer(tab); 1256 chrome::GoBack(current_browser(), CURRENT_TAB); 1257 back_nav_observer.Wait(); 1258 bool js_result; 1259 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 1260 tab, 1261 "window.domAutomationController.send(DidBackToOriginalPagePass())", 1262 &js_result)); 1263 EXPECT_TRUE(js_result); 1264 } 1265 1266 bool UrlIsInPrerenderManager(const std::string& html_file) const { 1267 return UrlIsInPrerenderManager(test_server()->GetURL(html_file)); 1268 } 1269 1270 bool UrlIsInPrerenderManager(const GURL& url) const { 1271 return GetPrerenderManager()->FindPrerenderData( 1272 url, GetSessionStorageNamespace()) != NULL; 1273 } 1274 1275 void UseHttpsSrcServer() { 1276 if (https_src_server_) 1277 return; 1278 https_src_server_.reset( 1279 new net::SpawnedTestServer( 1280 net::SpawnedTestServer::TYPE_HTTPS, 1281 net::SpawnedTestServer::kLocalhost, 1282 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")))); 1283 CHECK(https_src_server_->Start()); 1284 } 1285 1286 void DisableJavascriptCalls() { 1287 call_javascript_ = false; 1288 } 1289 1290 void DisableLoadEventCheck() { 1291 check_load_events_ = false; 1292 } 1293 1294 TaskManagerModel* GetModel() const { 1295 return TaskManager::GetInstance()->model(); 1296 } 1297 1298 PrerenderManager* GetPrerenderManager() const { 1299 PrerenderManager* prerender_manager = 1300 PrerenderManagerFactory::GetForProfile(current_browser()->profile()); 1301 return prerender_manager; 1302 } 1303 1304 const PrerenderLinkManager* GetPrerenderLinkManager() const { 1305 PrerenderLinkManager* prerender_link_manager = 1306 PrerenderLinkManagerFactory::GetForProfile( 1307 current_browser()->profile()); 1308 return prerender_link_manager; 1309 } 1310 1311 int GetPrerenderEventCount(int index, const std::string& type) const { 1312 int event_count; 1313 std::string expression = base::StringPrintf( 1314 "window.domAutomationController.send(" 1315 " GetPrerenderEventCount(%d, '%s'))", index, type.c_str()); 1316 1317 CHECK(content::ExecuteScriptAndExtractInt( 1318 GetActiveWebContents(), expression, &event_count)); 1319 return event_count; 1320 } 1321 1322 bool DidReceivePrerenderStartEventForLinkNumber(int index) const { 1323 return GetPrerenderEventCount(index, "webkitprerenderstart") > 0; 1324 } 1325 1326 int GetPrerenderLoadEventCountForLinkNumber(int index) const { 1327 return GetPrerenderEventCount(index, "webkitprerenderload"); 1328 } 1329 1330 int GetPrerenderDomContentLoadedEventCountForLinkNumber(int index) const { 1331 return GetPrerenderEventCount(index, "webkitprerenderdomcontentloaded"); 1332 } 1333 1334 bool DidReceivePrerenderStopEventForLinkNumber(int index) const { 1335 return GetPrerenderEventCount(index, "webkitprerenderstop") > 0; 1336 } 1337 1338 void WaitForPrerenderEventCount(int index, 1339 const std::string& type, 1340 int count) const { 1341 int dummy; 1342 std::string expression = base::StringPrintf( 1343 "WaitForPrerenderEventCount(%d, '%s', %d," 1344 " window.domAutomationController.send.bind(" 1345 " window.domAutomationController, 0))", 1346 index, type.c_str(), count); 1347 1348 CHECK(content::ExecuteScriptAndExtractInt( 1349 GetActiveWebContents(), expression, &dummy)); 1350 CHECK_EQ(0, dummy); 1351 } 1352 1353 bool HadPrerenderEventErrors() const { 1354 bool had_prerender_event_errors; 1355 CHECK(content::ExecuteScriptAndExtractBool( 1356 GetActiveWebContents(), 1357 "window.domAutomationController.send(Boolean(" 1358 " hadPrerenderEventErrors))", 1359 &had_prerender_event_errors)); 1360 return had_prerender_event_errors; 1361 } 1362 1363 // Asserting on this can result in flaky tests. PrerenderHandles are 1364 // removed from the PrerenderLinkManager when the prerender is canceled from 1365 // the browser, when the prerenders are cancelled from the renderer process, 1366 // or the channel for the renderer process is closed on the IO thread. In the 1367 // last case, the code must be careful to wait for the channel to close, as it 1368 // is done asynchronously after swapping out the old process. See 1369 // ChannelDestructionWatcher. 1370 bool IsEmptyPrerenderLinkManager() const { 1371 return GetPrerenderLinkManager()->IsEmpty(); 1372 } 1373 1374 size_t GetLinkPrerenderCount() const { 1375 return GetPrerenderLinkManager()->prerenders_.size(); 1376 } 1377 1378 size_t GetRunningLinkPrerenderCount() const { 1379 return GetPrerenderLinkManager()->CountRunningPrerenders(); 1380 } 1381 1382 // Returns length of |prerender_manager_|'s history, or -1 on failure. 1383 int GetHistoryLength() const { 1384 scoped_ptr<base::DictionaryValue> prerender_dict( 1385 static_cast<base::DictionaryValue*>( 1386 GetPrerenderManager()->GetAsValue())); 1387 if (!prerender_dict.get()) 1388 return -1; 1389 base::ListValue* history_list; 1390 if (!prerender_dict->GetList("history", &history_list)) 1391 return -1; 1392 return static_cast<int>(history_list->GetSize()); 1393 } 1394 1395#if defined(FULL_SAFE_BROWSING) 1396 FakeSafeBrowsingDatabaseManager* GetFakeSafeBrowsingDatabaseManager() { 1397 return safe_browsing_factory_->most_recent_service()-> 1398 fake_database_manager(); 1399 } 1400#endif 1401 1402 TestPrerenderContents* GetPrerenderContentsFor(const GURL& url) const { 1403 PrerenderManager::PrerenderData* prerender_data = 1404 GetPrerenderManager()->FindPrerenderData(url, NULL); 1405 return static_cast<TestPrerenderContents*>( 1406 prerender_data ? prerender_data->contents() : NULL); 1407 } 1408 1409 void SetLoaderHostOverride(const std::string& host) { 1410 loader_host_override_ = host; 1411 host_resolver()->AddRule(host, "127.0.0.1"); 1412 } 1413 1414 void set_loader_path(const std::string& path) { 1415 loader_path_ = path; 1416 } 1417 1418 void set_loader_query(const std::string& query) { 1419 loader_query_ = query; 1420 } 1421 1422 GURL GetCrossDomainTestUrl(const std::string& path) { 1423 static const std::string secondary_domain = "www.foo.com"; 1424 host_resolver()->AddRule(secondary_domain, "127.0.0.1"); 1425 std::string url_str(base::StringPrintf( 1426 "http://%s:%d/%s", 1427 secondary_domain.c_str(), 1428 test_server()->host_port_pair().port(), 1429 path.c_str())); 1430 return GURL(url_str); 1431 } 1432 1433 void set_browser(Browser* browser) { 1434 explicitly_set_browser_ = browser; 1435 } 1436 1437 Browser* current_browser() const { 1438 return explicitly_set_browser_ ? explicitly_set_browser_ : browser(); 1439 } 1440 1441 const GURL& dest_url() const { 1442 return dest_url_; 1443 } 1444 1445 void IncreasePrerenderMemory() { 1446 // Increase the memory allowed in a prerendered page above normal settings. 1447 // Debug build bots occasionally run against the default limit, and tests 1448 // were failing because the prerender was canceled due to memory exhaustion. 1449 // http://crbug.com/93076 1450 GetPrerenderManager()->mutable_config().max_bytes = 1000 * 1024 * 1024; 1451 } 1452 1453 bool DidPrerenderPass(WebContents* web_contents) const { 1454 bool prerender_test_result = false; 1455 if (!content::ExecuteScriptAndExtractBool( 1456 web_contents, 1457 "window.domAutomationController.send(DidPrerenderPass())", 1458 &prerender_test_result)) 1459 return false; 1460 return prerender_test_result; 1461 } 1462 1463 bool DidDisplayPass(WebContents* web_contents) const { 1464 bool display_test_result = false; 1465 if (!content::ExecuteScriptAndExtractBool( 1466 web_contents, 1467 "window.domAutomationController.send(DidDisplayPass())", 1468 &display_test_result)) 1469 return false; 1470 return display_test_result; 1471 } 1472 1473 scoped_ptr<TestPrerender> ExpectPrerender(FinalStatus expected_final_status) { 1474 return prerender_contents_factory_->ExpectPrerenderContents( 1475 expected_final_status); 1476 } 1477 1478 void AddPrerender(const GURL& url, int index) { 1479 std::string javascript = base::StringPrintf( 1480 "AddPrerender('%s', %d)", url.spec().c_str(), index); 1481 RenderFrameHost* render_frame_host = GetActiveWebContents()->GetMainFrame(); 1482 render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16(javascript)); 1483 } 1484 1485 // Returns a string for pattern-matching TaskManager tab entries. 1486 base::string16 MatchTaskManagerTab(const char* page_title) { 1487 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_TAB_PREFIX, 1488 base::ASCIIToUTF16(page_title)); 1489 } 1490 1491 // Returns a string for pattern-matching TaskManager prerender entries. 1492 base::string16 MatchTaskManagerPrerender(const char* page_title) { 1493 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PRERENDER_PREFIX, 1494 base::ASCIIToUTF16(page_title)); 1495 } 1496 1497 void RunJSReturningString(const char* js, std::string* result) { 1498 ASSERT_TRUE( 1499 content::ExecuteScriptAndExtractString( 1500 GetActiveWebContents(), 1501 base::StringPrintf("window.domAutomationController.send(%s)", 1502 js).c_str(), 1503 result)); 1504 } 1505 1506 void RunJS(const char* js) { 1507 ASSERT_TRUE(content::ExecuteScript( 1508 GetActiveWebContents(), 1509 base::StringPrintf("window.domAutomationController.send(%s)", 1510 js).c_str())); 1511 } 1512 1513 protected: 1514 bool autostart_test_server_; 1515 1516 private: 1517 // TODO(davidben): Remove this altogether so the tests don't globally assume 1518 // only one prerender. 1519 TestPrerenderContents* GetPrerenderContents() const { 1520 return GetPrerenderContentsFor(dest_url_); 1521 } 1522 1523 ScopedVector<TestPrerender> PrerenderTestURLImpl( 1524 const GURL& prerender_url, 1525 const std::vector<FinalStatus>& expected_final_status_queue, 1526 int expected_number_of_loads) { 1527 dest_url_ = prerender_url; 1528 1529 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 1530 replacement_text.push_back( 1531 make_pair("REPLACE_WITH_PRERENDER_URL", prerender_url.spec())); 1532 std::string replacement_path; 1533 CHECK(net::SpawnedTestServer::GetFilePathWithReplacements( 1534 loader_path_, 1535 replacement_text, 1536 &replacement_path)); 1537 1538 const net::SpawnedTestServer* src_server = test_server(); 1539 if (https_src_server_) 1540 src_server = https_src_server_.get(); 1541 GURL loader_url = src_server->GetURL( 1542 replacement_path + "&" + loader_query_); 1543 1544 GURL::Replacements loader_replacements; 1545 if (!loader_host_override_.empty()) 1546 loader_replacements.SetHostStr(loader_host_override_); 1547 loader_url = loader_url.ReplaceComponents(loader_replacements); 1548 1549 VLOG(1) << "Running test with queue length " << 1550 expected_final_status_queue.size(); 1551 CHECK(!expected_final_status_queue.empty()); 1552 ScopedVector<TestPrerender> prerenders; 1553 for (size_t i = 0; i < expected_final_status_queue.size(); i++) { 1554 prerenders.push_back( 1555 prerender_contents_factory_->ExpectPrerenderContents( 1556 expected_final_status_queue[i]).release()); 1557 } 1558 1559 FinalStatus expected_final_status = expected_final_status_queue.front(); 1560 1561 // Navigate to the loader URL and then wait for the first prerender to be 1562 // created. 1563 ui_test_utils::NavigateToURL(current_browser(), loader_url); 1564 prerenders[0]->WaitForCreate(); 1565 prerenders[0]->WaitForLoads(expected_number_of_loads); 1566 1567 if (ShouldAbortPrerenderBeforeSwap(expected_final_status)) { 1568 // The prerender will abort on its own. Assert it does so correctly. 1569 prerenders[0]->WaitForStop(); 1570 EXPECT_FALSE(prerenders[0]->contents()); 1571 EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(0)); 1572 } else { 1573 // Otherwise, check that it prerendered correctly. 1574 TestPrerenderContents* prerender_contents = prerenders[0]->contents(); 1575 1576 CHECK_NE(static_cast<PrerenderContents*>(NULL), prerender_contents); 1577 EXPECT_EQ(FINAL_STATUS_MAX, prerender_contents->final_status()); 1578 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); 1579 1580 if (call_javascript_) { 1581 // Check if page behaves as expected while in prerendered state. 1582 EXPECT_TRUE(DidPrerenderPass(prerender_contents->prerender_contents())); 1583 } 1584 } 1585 1586 // Test that the referring page received the right start and load events. 1587 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); 1588 if (check_load_events_) { 1589 EXPECT_EQ(expected_number_of_loads, prerenders[0]->number_of_loads()); 1590 EXPECT_EQ(expected_number_of_loads, 1591 GetPrerenderLoadEventCountForLinkNumber(0)); 1592 } 1593 EXPECT_FALSE(HadPrerenderEventErrors()); 1594 1595 return prerenders.Pass(); 1596 } 1597 1598 void NavigateToURLImpl(const content::OpenURLParams& params, 1599 bool expect_swap_to_succeed) const { 1600 ASSERT_NE(static_cast<PrerenderManager*>(NULL), GetPrerenderManager()); 1601 // Make sure in navigating we have a URL to use in the PrerenderManager. 1602 ASSERT_NE(static_cast<PrerenderContents*>(NULL), GetPrerenderContents()); 1603 1604 WebContents* web_contents = GetPrerenderContents()->prerender_contents(); 1605 1606 // Navigate and wait for either the load to finish normally or for a swap to 1607 // occur. 1608 // TODO(davidben): The only handles CURRENT_TAB navigations, which is the 1609 // only case tested or prerendered right now. 1610 CHECK_EQ(CURRENT_TAB, params.disposition); 1611 NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(), 1612 GetActiveWebContents()); 1613 WebContents* target_web_contents = current_browser()->OpenURL(params); 1614 swap_observer.Wait(); 1615 1616 if (web_contents && expect_swap_to_succeed) { 1617 EXPECT_EQ(web_contents, target_web_contents); 1618 if (call_javascript_) 1619 EXPECT_TRUE(DidDisplayPass(web_contents)); 1620 } 1621 } 1622 1623 // Opens the prerendered page using javascript functions in the loader 1624 // page. |javascript_function_name| should be a 0 argument function which is 1625 // invoked. |new_web_contents| is true if the navigation is expected to 1626 // happen in a new WebContents via OpenURL. 1627 void OpenURLWithJSImpl(const std::string& javascript_function_name, 1628 const GURL& url, 1629 const GURL& ping_url, 1630 bool new_web_contents) const { 1631 WebContents* web_contents = GetActiveWebContents(); 1632 RenderFrameHost* render_frame_host = web_contents->GetMainFrame(); 1633 // Extra arguments in JS are ignored. 1634 std::string javascript = base::StringPrintf( 1635 "%s('%s', '%s')", javascript_function_name.c_str(), 1636 url.spec().c_str(), ping_url.spec().c_str()); 1637 1638 if (new_web_contents) { 1639 NewTabNavigationOrSwapObserver observer; 1640 render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16(javascript)); 1641 observer.Wait(); 1642 } else { 1643 NavigationOrSwapObserver observer(current_browser()->tab_strip_model(), 1644 web_contents); 1645 render_frame_host->ExecuteJavaScript(base::ASCIIToUTF16(javascript)); 1646 observer.Wait(); 1647 } 1648 } 1649 1650 TestPrerenderContentsFactory* prerender_contents_factory_; 1651#if defined(FULL_SAFE_BROWSING) 1652 scoped_ptr<TestSafeBrowsingServiceFactory> safe_browsing_factory_; 1653#endif 1654 NeverRunsExternalProtocolHandlerDelegate external_protocol_handler_delegate_; 1655 GURL dest_url_; 1656 scoped_ptr<net::SpawnedTestServer> https_src_server_; 1657 bool call_javascript_; 1658 bool check_load_events_; 1659 std::string loader_host_override_; 1660 std::string loader_path_; 1661 std::string loader_query_; 1662 Browser* explicitly_set_browser_; 1663}; 1664 1665// Checks that a page is correctly prerendered in the case of a 1666// <link rel=prerender> tag and then loaded into a tab in response to a 1667// navigation. 1668IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPage) { 1669 UMAHistogramHelper histograms; 1670 1671 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 1672 EXPECT_EQ(1, GetPrerenderDomContentLoadedEventCountForLinkNumber(0)); 1673 histograms.Fetch(); 1674 histograms.ExpectTotalCount("Prerender.none_PerceivedPLT", 1); 1675 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0); 1676 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0); 1677 histograms.ExpectTotalCount("Prerender.websame_PrerenderNotSwappedInPLT", 1); 1678 1679 ChannelDestructionWatcher channel_close_watcher; 1680 channel_close_watcher.WatchChannel( 1681 GetActiveWebContents()->GetRenderProcessHost()); 1682 NavigateToDestURL(); 1683 channel_close_watcher.WaitForChannelClose(); 1684 1685 histograms.Fetch(); 1686 histograms.ExpectTotalCount("Prerender.websame_PerceivedPLT", 1); 1687 histograms.ExpectTotalCount("Prerender.websame_PerceivedPLTMatched", 1); 1688 histograms.ExpectTotalCount( 1689 "Prerender.websame_PerceivedPLTMatchedComplete", 1); 1690 1691 ASSERT_TRUE(IsEmptyPrerenderLinkManager()); 1692} 1693 1694// Checks that cross-domain prerenders emit the correct histograms. 1695IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageCrossDomain) { 1696 UMAHistogramHelper histograms; 1697 1698 PrerenderTestURL(GetCrossDomainTestUrl("files/prerender/prerender_page.html"), 1699 FINAL_STATUS_USED, 1); 1700 histograms.Fetch(); 1701 histograms.ExpectTotalCount("Prerender.none_PerceivedPLT", 1); 1702 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0); 1703 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0); 1704 histograms.ExpectTotalCount("Prerender.webcross_PrerenderNotSwappedInPLT", 1); 1705 1706 NavigateToDestURL(); 1707 histograms.Fetch(); 1708 histograms.ExpectTotalCount("Prerender.webcross_PerceivedPLT", 1); 1709 histograms.ExpectTotalCount("Prerender.webcross_PerceivedPLTMatched", 1); 1710 histograms.ExpectTotalCount( 1711 "Prerender.webcross_PerceivedPLTMatchedComplete", 1); 1712} 1713 1714// Checks that pending prerenders launch and receive proper event treatment. 1715IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPagePending) { 1716 scoped_ptr<TestPrerender> prerender = 1717 PrerenderTestURL("files/prerender/prerender_page_pending.html", 1718 FINAL_STATUS_USED, 1); 1719 1720 // Navigate to the prerender. 1721 scoped_ptr<TestPrerender> prerender2 = ExpectPrerender(FINAL_STATUS_USED); 1722 NavigateToDestURL(); 1723 // Abort early if the original prerender didn't swap, so as not to hang. 1724 ASSERT_FALSE(prerender->contents()); 1725 1726 // Wait for the new prerender to be ready. 1727 prerender2->WaitForStart(); 1728 prerender2->WaitForLoads(1); 1729 1730 const GURL prerender_page_url = 1731 test_server()->GetURL("files/prerender/prerender_page.html"); 1732 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 1733 EXPECT_NE(static_cast<TestPrerenderContents*>(NULL), 1734 GetPrerenderContentsFor(prerender_page_url)); 1735 1736 // Now navigate to our target page. 1737 NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(), 1738 GetActiveWebContents()); 1739 ui_test_utils::NavigateToURLWithDisposition( 1740 current_browser(), prerender_page_url, CURRENT_TAB, 1741 ui_test_utils::BROWSER_TEST_NONE); 1742 swap_observer.Wait(); 1743 1744 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1745} 1746 1747// Checks that pending prerenders which are canceled before they are launched 1748// never get started. 1749IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageRemovesPending) { 1750 PrerenderTestURL("files/prerender/prerender_page_removes_pending.html", 1751 FINAL_STATUS_USED, 1); 1752 1753 ChannelDestructionWatcher channel_close_watcher; 1754 channel_close_watcher.WatchChannel( 1755 GetActiveWebContents()->GetRenderProcessHost()); 1756 NavigateToDestURL(); 1757 channel_close_watcher.WaitForChannelClose(); 1758 1759 EXPECT_FALSE(DidReceivePrerenderStartEventForLinkNumber(1)); 1760 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); 1761 EXPECT_FALSE(HadPrerenderEventErrors()); 1762 // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive* 1763 // calls did a thread/process hop to the renderer which insured pending 1764 // renderer events have arrived. 1765 ASSERT_TRUE(IsEmptyPrerenderLinkManager()); 1766} 1767 1768IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageRemovingLink) { 1769 scoped_ptr<TestPrerender> prerender = 1770 PrerenderTestURL("files/prerender/prerender_page.html", 1771 FINAL_STATUS_CANCELLED, 1); 1772 1773 // No ChannelDestructionWatcher is needed here, since prerenders in the 1774 // PrerenderLinkManager should be deleted by removing the links, rather than 1775 // shutting down the renderer process. 1776 RemoveLinkElement(0); 1777 prerender->WaitForStop(); 1778 1779 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); 1780 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); 1781 EXPECT_FALSE(HadPrerenderEventErrors()); 1782 // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive* 1783 // calls did a thread/process hop to the renderer which insured pending 1784 // renderer events have arrived. 1785 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1786} 1787 1788IN_PROC_BROWSER_TEST_F( 1789 PrerenderBrowserTest, PrerenderPageRemovingLinkWithTwoLinks) { 1790 GetPrerenderManager()->mutable_config().max_link_concurrency = 2; 1791 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2; 1792 1793 set_loader_query("links_to_insert=2"); 1794 scoped_ptr<TestPrerender> prerender = 1795 PrerenderTestURL("files/prerender/prerender_page.html", 1796 FINAL_STATUS_CANCELLED, 1); 1797 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); 1798 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); 1799 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); 1800 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); 1801 1802 RemoveLinkElement(0); 1803 RemoveLinkElement(1); 1804 prerender->WaitForStop(); 1805 1806 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); 1807 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); 1808 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); 1809 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); 1810 EXPECT_FALSE(HadPrerenderEventErrors()); 1811 // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive* 1812 // calls did a thread/process hop to the renderer which insured pending 1813 // renderer events have arrived. 1814 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1815} 1816 1817IN_PROC_BROWSER_TEST_F( 1818 PrerenderBrowserTest, PrerenderPageRemovingLinkWithTwoLinksOneLate) { 1819 GetPrerenderManager()->mutable_config().max_link_concurrency = 2; 1820 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2; 1821 1822 GURL url = test_server()->GetURL("files/prerender/prerender_page.html"); 1823 scoped_ptr<TestPrerender> prerender = 1824 PrerenderTestURL(url, FINAL_STATUS_CANCELLED, 1); 1825 1826 // Add a second prerender for the same link. It reuses the prerender, so only 1827 // the start event fires here. 1828 AddPrerender(url, 1); 1829 WaitForPrerenderEventCount(1, "webkitprerenderstart", 1); 1830 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); 1831 EXPECT_EQ(0, GetPrerenderLoadEventCountForLinkNumber(1)); 1832 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); 1833 1834 RemoveLinkElement(0); 1835 RemoveLinkElement(1); 1836 prerender->WaitForStop(); 1837 1838 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); 1839 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); 1840 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); 1841 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); 1842 EXPECT_FALSE(HadPrerenderEventErrors()); 1843 // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive* 1844 // calls did a thread/process hop to the renderer which insured pending 1845 // renderer events have arrived. 1846 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1847} 1848 1849IN_PROC_BROWSER_TEST_F( 1850 PrerenderBrowserTest, 1851 PrerenderPageRemovingLinkWithTwoLinksRemovingOne) { 1852 GetPrerenderManager()->mutable_config().max_link_concurrency = 2; 1853 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2; 1854 set_loader_query("links_to_insert=2"); 1855 PrerenderTestURL("files/prerender/prerender_page.html", 1856 FINAL_STATUS_USED, 1); 1857 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); 1858 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); 1859 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); 1860 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); 1861 1862 RemoveLinkElement(0); 1863 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); 1864 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(0)); 1865 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(1)); 1866 EXPECT_FALSE(DidReceivePrerenderStopEventForLinkNumber(1)); 1867 EXPECT_FALSE(HadPrerenderEventErrors()); 1868 // IsEmptyPrerenderLinkManager() is not racy because the earlier DidReceive* 1869 // calls did a thread/process hop to the renderer which insured pending 1870 // renderer events have arrived. 1871 EXPECT_FALSE(IsEmptyPrerenderLinkManager()); 1872 1873 ChannelDestructionWatcher channel_close_watcher; 1874 channel_close_watcher.WatchChannel( 1875 GetActiveWebContents()->GetRenderProcessHost()); 1876 NavigateToDestURL(); 1877 channel_close_watcher.WaitForChannelClose(); 1878 1879 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 1880} 1881 1882// Checks that the visibility API works. 1883IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderVisibility) { 1884 PrerenderTestURL("files/prerender/prerender_visibility.html", 1885 FINAL_STATUS_USED, 1886 1); 1887 NavigateToDestURL(); 1888} 1889 1890// Checks that the prerendering of a page is canceled correctly if we try to 1891// swap it in before it commits. 1892IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNoCommitNoSwap) { 1893 // Navigate to a page that triggers a prerender for a URL that never commits. 1894 const GURL kNoCommitUrl("http://never-respond.example.com"); 1895 base::FilePath file(GetTestPath("prerender_page.html")); 1896 1897 base::RunLoop prerender_start_loop; 1898 BrowserThread::PostTask( 1899 BrowserThread::IO, FROM_HERE, 1900 base::Bind(&CreateHangingFirstRequestProtocolHandlerOnIO, 1901 kNoCommitUrl, file, prerender_start_loop.QuitClosure())); 1902 DisableJavascriptCalls(); 1903 PrerenderTestURL(kNoCommitUrl, 1904 FINAL_STATUS_NAVIGATION_UNCOMMITTED, 1905 0); 1906 // Wait for the hanging request to be scheduled. 1907 prerender_start_loop.Run(); 1908 1909 // Navigate to the URL, but assume the contents won't be swapped in. 1910 NavigateToDestURLWithDisposition(CURRENT_TAB, false); 1911} 1912 1913// Checks that client redirects don't add alias URLs until after they commit. 1914IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNoCommitNoSwap2) { 1915 // Navigate to a page that then navigates to a URL that never commits. 1916 const GURL kNoCommitUrl("http://never-respond.example.com"); 1917 base::FilePath file(GetTestPath("prerender_page.html")); 1918 1919 base::RunLoop prerender_start_loop; 1920 BrowserThread::PostTask( 1921 BrowserThread::IO, FROM_HERE, 1922 base::Bind(&CreateHangingFirstRequestProtocolHandlerOnIO, 1923 kNoCommitUrl, file, prerender_start_loop.QuitClosure())); 1924 DisableJavascriptCalls(); 1925 PrerenderTestURL(CreateClientRedirect(kNoCommitUrl.spec()), 1926 FINAL_STATUS_APP_TERMINATING, 1); 1927 // Wait for the hanging request to be scheduled. 1928 prerender_start_loop.Run(); 1929 1930 // Navigating to the second URL should not swap. 1931 NavigateToURLWithDisposition(kNoCommitUrl, CURRENT_TAB, false); 1932} 1933 1934// Checks that the prerendering of a page is canceled correctly when a 1935// Javascript alert is called. 1936IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertBeforeOnload) { 1937 PrerenderTestURL("files/prerender/prerender_alert_before_onload.html", 1938 FINAL_STATUS_JAVASCRIPT_ALERT, 1939 0); 1940} 1941 1942// Checks that the prerendering of a page is canceled correctly when a 1943// Javascript alert is called. 1944IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertAfterOnload) { 1945 PrerenderTestURL("files/prerender/prerender_alert_after_onload.html", 1946 FINAL_STATUS_JAVASCRIPT_ALERT, 1947 1); 1948} 1949 1950// Checks that plugins are not loaded while a page is being preloaded, but 1951// are loaded when the page is displayed. 1952#if defined(USE_AURA) && !defined(OS_WIN) 1953// http://crbug.com/103496 1954#define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin 1955#elif defined(OS_MACOSX) 1956// http://crbug.com/100514 1957#define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin 1958#elif defined(OS_WIN) && defined(ARCH_CPU_X86_64) 1959// TODO(jschuh): Failing plugin tests. crbug.com/244653 1960#define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin 1961#elif defined(OS_LINUX) 1962// http://crbug.com/306715 1963#define MAYBE_PrerenderDelayLoadPlugin DISABLED_PrerenderDelayLoadPlugin 1964#else 1965#define MAYBE_PrerenderDelayLoadPlugin PrerenderDelayLoadPlugin 1966#endif 1967// http://crbug.com/306715 1968IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MAYBE_PrerenderDelayLoadPlugin) { 1969 PrerenderTestURL("files/prerender/plugin_delay_load.html", 1970 FINAL_STATUS_USED, 1971 1); 1972 NavigateToDestURL(); 1973} 1974 1975// Checks that plugins are not loaded on prerendering pages when click-to-play 1976// is enabled. 1977IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickToPlay) { 1978 // Enable click-to-play. 1979 HostContentSettingsMap* content_settings_map = 1980 current_browser()->profile()->GetHostContentSettingsMap(); 1981 content_settings_map->SetDefaultContentSetting( 1982 CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_ASK); 1983 1984 PrerenderTestURL("files/prerender/prerender_plugin_click_to_play.html", 1985 FINAL_STATUS_USED, 1986 1); 1987 NavigateToDestURL(); 1988} 1989 1990// Checks that we don't load a NaCl plugin when NaCl is disabled. 1991IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNaClPluginDisabled) { 1992 PrerenderTestURL("files/prerender/prerender_plugin_nacl_disabled.html", 1993 FINAL_STATUS_USED, 1994 1); 1995 NavigateToDestURL(); 1996 1997 1998 // Run this check again. When we try to load aa ppapi plugin, the 1999 // "loadstart" event is asynchronously posted to a message loop. 2000 // It's possible that earlier call could have been run before the 2001 // the "loadstart" event was posted. 2002 // TODO(mmenke): While this should reliably fail on regressions, the 2003 // reliability depends on the specifics of ppapi plugin 2004 // loading. It would be great if we could avoid that. 2005 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents())); 2006} 2007 2008// Checks that plugins in an iframe are not loaded while a page is 2009// being preloaded, but are loaded when the page is displayed. 2010#if defined(USE_AURA) && !defined(OS_WIN) 2011// http://crbug.com/103496 2012#define MAYBE_PrerenderIframeDelayLoadPlugin \ 2013 DISABLED_PrerenderIframeDelayLoadPlugin 2014#elif defined(OS_MACOSX) 2015// http://crbug.com/100514 2016#define MAYBE_PrerenderIframeDelayLoadPlugin \ 2017 DISABLED_PrerenderIframeDelayLoadPlugin 2018#elif defined(OS_WIN) && defined(ARCH_CPU_X86_64) 2019// TODO(jschuh): Failing plugin tests. crbug.com/244653 2020#define MAYBE_PrerenderIframeDelayLoadPlugin \ 2021 DISABLED_PrerenderIframeDelayLoadPlugin 2022#else 2023#define MAYBE_PrerenderIframeDelayLoadPlugin PrerenderIframeDelayLoadPlugin 2024#endif 2025IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2026 MAYBE_PrerenderIframeDelayLoadPlugin) { 2027 PrerenderTestURL("files/prerender/prerender_iframe_plugin_delay_load.html", 2028 FINAL_STATUS_USED, 2029 1); 2030 NavigateToDestURL(); 2031} 2032 2033// Renders a page that contains a prerender link to a page that contains an 2034// iframe with a source that requires http authentication. This should not 2035// prerender successfully. 2036IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHttpAuthentication) { 2037 PrerenderTestURL("files/prerender/prerender_http_auth_container.html", 2038 FINAL_STATUS_AUTH_NEEDED, 2039 0); 2040} 2041 2042// Checks that client-issued redirects work with prerendering. 2043// This version navigates to the page which issues the redirection, rather 2044// than the final destination page. 2045IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2046 PrerenderClientRedirectNavigateToFirst) { 2047 PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"), 2048 FINAL_STATUS_USED, 2049 2); 2050 NavigateToDestURL(); 2051} 2052 2053// Checks that client-issued redirects work with prerendering. 2054// This version navigates to the final destination page, rather than the 2055// page which does the redirection. 2056IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2057 PrerenderClientRedirectNavigateToSecond) { 2058 PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"), 2059 FINAL_STATUS_USED, 2060 2); 2061 NavigateToURL("files/prerender/prerender_page.html"); 2062} 2063 2064// Checks that redirects with location.replace do not cancel a prerender and 2065// and swap when navigating to the first page. 2066IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2067 PrerenderLocationReplaceNavigateToFirst) { 2068 PrerenderTestURL("files/prerender/prerender_location_replace.html", 2069 FINAL_STATUS_USED, 2070 2); 2071 NavigateToDestURL(); 2072} 2073 2074// Checks that redirects with location.replace do not cancel a prerender and 2075// and swap when navigating to the second. 2076IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2077 PrerenderLocationReplaceNavigateToSecond) { 2078 PrerenderTestURL("files/prerender/prerender_location_replace.html", 2079 FINAL_STATUS_USED, 2080 2); 2081 NavigateToURL("files/prerender/prerender_page.html"); 2082} 2083 2084// Checks that we get the right PPLT histograms for client redirect prerenders 2085// and navigations when the referring page is Google. 2086IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2087 PrerenderLocationReplaceGWSHistograms) { 2088 DisableJavascriptCalls(); 2089 UMAHistogramHelper histograms; 2090 2091 // The loader page should look like Google. 2092 const std::string kGoogleDotCom("www.google.com"); 2093 SetLoaderHostOverride(kGoogleDotCom); 2094 set_loader_path("files/prerender/prerender_loader_with_replace_state.html"); 2095 2096 GURL dest_url = GetCrossDomainTestUrl( 2097 "files/prerender/prerender_deferred_image.html"); 2098 2099 GURL prerender_url = test_server()->GetURL( 2100 "files/prerender/prerender_location_replace.html?" + 2101 net::EscapeQueryParamValue(dest_url.spec(), false) + 2102 "#prerender"); 2103 GURL::Replacements replacements; 2104 replacements.SetHostStr(kGoogleDotCom); 2105 prerender_url = prerender_url.ReplaceComponents(replacements); 2106 2107 // The prerender will not completely load until after the swap, so wait for a 2108 // title change before calling DidPrerenderPass. 2109 scoped_ptr<TestPrerender> prerender = 2110 PrerenderTestURL(prerender_url, FINAL_STATUS_USED, 1); 2111 WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle); 2112 EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents())); 2113 EXPECT_EQ(1, prerender->number_of_loads()); 2114 2115 histograms.Fetch(); 2116 histograms.ExpectTotalCount("Prerender.none_PerceivedPLT", 1); 2117 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0); 2118 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0); 2119 // Although there is a client redirect, it is dropped from histograms because 2120 // it is a Google URL. The target page itself does not load until after the 2121 // swap. 2122 histograms.ExpectTotalCount("Prerender.gws_PrerenderNotSwappedInPLT", 0); 2123 2124 GURL navigate_url = test_server()->GetURL( 2125 "files/prerender/prerender_location_replace.html?" + 2126 net::EscapeQueryParamValue(dest_url.spec(), false) + 2127 "#navigate"); 2128 navigate_url = navigate_url.ReplaceComponents(replacements); 2129 2130 NavigationOrSwapObserver swap_observer( 2131 current_browser()->tab_strip_model(), 2132 GetActiveWebContents(), 2); 2133 current_browser()->OpenURL(OpenURLParams( 2134 navigate_url, Referrer(), CURRENT_TAB, 2135 content::PAGE_TRANSITION_TYPED, false)); 2136 swap_observer.Wait(); 2137 2138 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents())); 2139 2140 histograms.Fetch(); 2141 histograms.ExpectTotalCount("Prerender.gws_PrerenderNotSwappedInPLT", 0); 2142 histograms.ExpectTotalCount("Prerender.gws_PerceivedPLT", 1); 2143 histograms.ExpectTotalCount("Prerender.gws_PerceivedPLTMatched", 1); 2144 histograms.ExpectTotalCount( 2145 "Prerender.gws_PerceivedPLTMatchedComplete", 1); 2146 2147 // The client redirect does /not/ count as a miss because it's a Google URL. 2148 histograms.ExpectTotalCount("Prerender.PerceivedPLTFirstAfterMiss", 0); 2149} 2150 2151// Checks that client-issued redirects work with prerendering. 2152// This version navigates to the final destination page, rather than the 2153// page which does the redirection via a mouse click. 2154IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2155 PrerenderClientRedirectNavigateToSecondViaClick) { 2156 GURL prerender_url = test_server()->GetURL( 2157 CreateClientRedirect("files/prerender/prerender_page.html")); 2158 GURL destination_url = test_server()->GetURL( 2159 "files/prerender/prerender_page.html"); 2160 PrerenderTestURL(prerender_url, FINAL_STATUS_USED, 2); 2161 OpenURLViaClick(destination_url); 2162} 2163 2164// Checks that a page served over HTTPS is correctly prerendered. 2165IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHttps) { 2166 net::SpawnedTestServer https_server( 2167 net::SpawnedTestServer::TYPE_HTTPS, net::SpawnedTestServer::kLocalhost, 2168 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 2169 ASSERT_TRUE(https_server.Start()); 2170 GURL https_url = https_server.GetURL("files/prerender/prerender_page.html"); 2171 PrerenderTestURL(https_url, 2172 FINAL_STATUS_USED, 2173 1); 2174 NavigateToDestURL(); 2175} 2176 2177// Checks that client-issued redirects within an iframe in a prerendered 2178// page will not count as an "alias" for the prerendered page. 2179IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2180 PrerenderClientRedirectInIframe) { 2181 std::string redirect_path = CreateClientRedirect( 2182 "/files/prerender/prerender_embedded_content.html"); 2183 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 2184 replacement_text.push_back( 2185 std::make_pair("REPLACE_WITH_URL", "/" + redirect_path)); 2186 std::string replacement_path; 2187 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 2188 "files/prerender/prerender_with_iframe.html", 2189 replacement_text, 2190 &replacement_path)); 2191 PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 2); 2192 EXPECT_FALSE(UrlIsInPrerenderManager( 2193 "files/prerender/prerender_embedded_content.html")); 2194 NavigateToDestURL(); 2195} 2196 2197// Checks that server-issued redirects work with prerendering. 2198// This version navigates to the page which issues the redirection, rather 2199// than the final destination page. 2200IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2201 PrerenderServerRedirectNavigateToFirst) { 2202 PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"), 2203 FINAL_STATUS_USED, 2204 1); 2205 NavigateToDestURL(); 2206} 2207 2208// Checks that server-issued redirects work with prerendering. 2209// This version navigates to the final destination page, rather than the 2210// page which does the redirection. 2211IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2212 PrerenderServerRedirectNavigateToSecond) { 2213 PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"), 2214 FINAL_STATUS_USED, 2215 1); 2216 NavigateToURL("files/prerender/prerender_page.html"); 2217} 2218 2219// Checks that server-issued redirects work with prerendering. 2220// This version navigates to the final destination page, rather than the 2221// page which does the redirection via a mouse click. 2222IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2223 PrerenderServerRedirectNavigateToSecondViaClick) { 2224 GURL prerender_url = test_server()->GetURL( 2225 CreateServerRedirect("files/prerender/prerender_page.html")); 2226 GURL destination_url = test_server()->GetURL( 2227 "files/prerender/prerender_page.html"); 2228 PrerenderTestURL(prerender_url, FINAL_STATUS_USED, 1); 2229 OpenURLViaClick(destination_url); 2230} 2231 2232// Checks that server-issued redirects within an iframe in a prerendered 2233// page will not count as an "alias" for the prerendered page. 2234IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderServerRedirectInIframe) { 2235 std::string redirect_path = CreateServerRedirect( 2236 "/files/prerender/prerender_embedded_content.html"); 2237 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 2238 replacement_text.push_back( 2239 std::make_pair("REPLACE_WITH_URL", "/" + redirect_path)); 2240 std::string replacement_path; 2241 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 2242 "files/prerender/prerender_with_iframe.html", 2243 replacement_text, 2244 &replacement_path)); 2245 PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1); 2246 EXPECT_FALSE(UrlIsInPrerenderManager( 2247 "files/prerender/prerender_embedded_content.html")); 2248 NavigateToDestURL(); 2249} 2250 2251// Prerenders a page that contains an automatic download triggered through an 2252// iframe. This should not prerender successfully. 2253IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDownloadIframe) { 2254 PrerenderTestURL("files/prerender/prerender_download_iframe.html", 2255 FINAL_STATUS_DOWNLOAD, 2256 0); 2257} 2258 2259// Prerenders a page that contains an automatic download triggered through 2260// Javascript changing the window.location. This should not prerender 2261// successfully 2262IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDownloadLocation) { 2263 PrerenderTestURL(CreateClientRedirect("files/download-test1.lib"), 2264 FINAL_STATUS_DOWNLOAD, 2265 1); 2266} 2267 2268// Prerenders a page that contains an automatic download triggered through a 2269// client-issued redirect. This should not prerender successfully. 2270IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDownloadClientRedirect) { 2271 PrerenderTestURL("files/prerender/prerender_download_refresh.html", 2272 FINAL_STATUS_DOWNLOAD, 2273 1); 2274} 2275 2276// Checks that the referrer is set when prerendering. 2277IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReferrer) { 2278 PrerenderTestURL("files/prerender/prerender_referrer.html", 2279 FINAL_STATUS_USED, 2280 1); 2281 NavigateToDestURL(); 2282} 2283 2284// Checks that the referrer is not set when prerendering and the source page is 2285// HTTPS. 2286IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2287 PrerenderNoSSLReferrer) { 2288 UseHttpsSrcServer(); 2289 PrerenderTestURL("files/prerender/prerender_no_referrer.html", 2290 FINAL_STATUS_USED, 2291 1); 2292 NavigateToDestURL(); 2293} 2294 2295// Checks that the referrer is set when prerendering is cancelled. 2296IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelReferrer) { 2297 scoped_ptr<TestContentBrowserClient> test_content_browser_client( 2298 new TestContentBrowserClient); 2299 content::ContentBrowserClient* original_browser_client = 2300 content::SetBrowserClientForTesting(test_content_browser_client.get()); 2301 2302 PrerenderTestURL("files/prerender/prerender_referrer.html", 2303 FINAL_STATUS_CANCELLED, 2304 1); 2305 OpenDestURLViaClick(); 2306 2307 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents())); 2308 2309 content::SetBrowserClientForTesting(original_browser_client); 2310} 2311 2312// Checks that popups on a prerendered page cause cancellation. 2313IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPopup) { 2314 PrerenderTestURL("files/prerender/prerender_popup.html", 2315 FINAL_STATUS_CREATE_NEW_WINDOW, 2316 0); 2317} 2318 2319// Checks that registering a protocol handler causes cancellation. 2320IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderRegisterProtocolHandler) { 2321 PrerenderTestURL("files/prerender/prerender_register_protocol_handler.html", 2322 FINAL_STATUS_REGISTER_PROTOCOL_HANDLER, 2323 0); 2324} 2325 2326// Checks that renderers using excessive memory will be terminated. 2327IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderExcessiveMemory) { 2328 ASSERT_TRUE(GetPrerenderManager()); 2329 GetPrerenderManager()->mutable_config().max_bytes = 30 * 1024 * 1024; 2330 // The excessive memory kill may happen before or after the load event as it 2331 // happens asynchronously with IPC calls. Even if the test does not start 2332 // allocating until after load, the browser process might notice before the 2333 // message gets through. This happens on XP debug bots because they're so 2334 // slow. Instead, don't bother checking the load event count. 2335 DisableLoadEventCheck(); 2336 PrerenderTestURL("files/prerender/prerender_excessive_memory.html", 2337 FINAL_STATUS_MEMORY_LIMIT_EXCEEDED, 0); 2338} 2339 2340// Checks shutdown code while a prerender is active. 2341IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderQuickQuit) { 2342 DisableJavascriptCalls(); 2343 DisableLoadEventCheck(); 2344 PrerenderTestURL("files/prerender/prerender_page.html", 2345 FINAL_STATUS_APP_TERMINATING, 2346 0); 2347} 2348 2349// Checks that we don't prerender in an infinite loop. 2350IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderInfiniteLoop) { 2351 const char* const kHtmlFileA = "files/prerender/prerender_infinite_a.html"; 2352 const char* const kHtmlFileB = "files/prerender/prerender_infinite_b.html"; 2353 2354 std::vector<FinalStatus> expected_final_status_queue; 2355 expected_final_status_queue.push_back(FINAL_STATUS_USED); 2356 expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING); 2357 2358 ScopedVector<TestPrerender> prerenders = 2359 PrerenderTestURL(kHtmlFileA, expected_final_status_queue, 1); 2360 ASSERT_TRUE(prerenders[0]->contents()); 2361 // Assert that the pending prerender is in there already. This relies on the 2362 // fact that the renderer sends out the AddLinkRelPrerender IPC before sending 2363 // the page load one. 2364 EXPECT_EQ(2U, GetLinkPrerenderCount()); 2365 EXPECT_EQ(1U, GetRunningLinkPrerenderCount()); 2366 2367 // Next url should be in pending list but not an active entry. 2368 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB)); 2369 2370 NavigateToDestURL(); 2371 2372 // Make sure the PrerenderContents for the next url is now in the manager and 2373 // not pending. This relies on pending prerenders being resolved in the same 2374 // event loop iteration as OnPrerenderStop. 2375 EXPECT_TRUE(UrlIsInPrerenderManager(kHtmlFileB)); 2376 EXPECT_EQ(1U, GetLinkPrerenderCount()); 2377 EXPECT_EQ(1U, GetRunningLinkPrerenderCount()); 2378} 2379 2380// Checks that we don't prerender in an infinite loop and multiple links are 2381// handled correctly. 2382IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2383 PrerenderInfiniteLoopMultiple) { 2384 const char* const kHtmlFileA = 2385 "files/prerender/prerender_infinite_a_multiple.html"; 2386 const char* const kHtmlFileB = 2387 "files/prerender/prerender_infinite_b_multiple.html"; 2388 const char* const kHtmlFileC = 2389 "files/prerender/prerender_infinite_c_multiple.html"; 2390 2391 // This test is conceptually simplest if concurrency is at two, since we 2392 // don't have to worry about which of kHtmlFileB or kHtmlFileC gets evicted. 2393 GetPrerenderManager()->mutable_config().max_link_concurrency = 2; 2394 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2; 2395 2396 std::vector<FinalStatus> expected_final_status_queue; 2397 expected_final_status_queue.push_back(FINAL_STATUS_USED); 2398 expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING); 2399 expected_final_status_queue.push_back(FINAL_STATUS_APP_TERMINATING); 2400 2401 ScopedVector<TestPrerender> prerenders = 2402 PrerenderTestURL(kHtmlFileA, expected_final_status_queue, 1); 2403 ASSERT_TRUE(prerenders[0]->contents()); 2404 2405 // Next url should be in pending list but not an active entry. This relies on 2406 // the fact that the renderer sends out the AddLinkRelPrerender IPC before 2407 // sending the page load one. 2408 EXPECT_EQ(3U, GetLinkPrerenderCount()); 2409 EXPECT_EQ(1U, GetRunningLinkPrerenderCount()); 2410 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB)); 2411 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileC)); 2412 2413 NavigateToDestURL(); 2414 2415 // Make sure the PrerenderContents for the next urls are now in the manager 2416 // and not pending. One and only one of the URLs (the last seen) should be the 2417 // active entry. This relies on pending prerenders being resolved in the same 2418 // event loop iteration as OnPrerenderStop. 2419 bool url_b_is_active_prerender = UrlIsInPrerenderManager(kHtmlFileB); 2420 bool url_c_is_active_prerender = UrlIsInPrerenderManager(kHtmlFileC); 2421 EXPECT_TRUE(url_b_is_active_prerender && url_c_is_active_prerender); 2422 EXPECT_EQ(2U, GetLinkPrerenderCount()); 2423 EXPECT_EQ(2U, GetRunningLinkPrerenderCount()); 2424} 2425 2426// Checks that pending prerenders are aborted (and never launched) when launched 2427// by a prerender that itself gets aborted. 2428IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAbortPendingOnCancel) { 2429 const char* const kHtmlFileA = "files/prerender/prerender_infinite_a.html"; 2430 const char* const kHtmlFileB = "files/prerender/prerender_infinite_b.html"; 2431 2432 scoped_ptr<TestPrerender> prerender = 2433 PrerenderTestURL(kHtmlFileA, FINAL_STATUS_CANCELLED, 1); 2434 ASSERT_TRUE(prerender->contents()); 2435 // Assert that the pending prerender is in there already. This relies on the 2436 // fact that the renderer sends out the AddLinkRelPrerender IPC before sending 2437 // the page load one. 2438 EXPECT_EQ(2U, GetLinkPrerenderCount()); 2439 EXPECT_EQ(1U, GetRunningLinkPrerenderCount()); 2440 2441 // Next url should be in pending list but not an active entry. 2442 EXPECT_FALSE(UrlIsInPrerenderManager(kHtmlFileB)); 2443 2444 // Cancel the prerender. 2445 GetPrerenderManager()->CancelAllPrerenders(); 2446 prerender->WaitForStop(); 2447 2448 // All prerenders are now gone. 2449 EXPECT_TRUE(IsEmptyPrerenderLinkManager()); 2450} 2451 2452IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, OpenTaskManagerBeforePrerender) { 2453 const base::string16 any_prerender = MatchTaskManagerPrerender("*"); 2454 const base::string16 any_tab = MatchTaskManagerTab("*"); 2455 const base::string16 original = MatchTaskManagerTab("Preloader"); 2456 const base::string16 prerender = MatchTaskManagerPrerender("Prerender Page"); 2457 const base::string16 final = MatchTaskManagerTab("Prerender Page"); 2458 2459 // Show the task manager. This populates the model. 2460 chrome::OpenTaskManager(current_browser()); 2461 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab)); 2462 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, any_prerender)); 2463 2464 // Prerender a page in addition to the original tab. 2465 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 2466 2467 // A TaskManager entry should appear like "Prerender: Prerender Page" 2468 // alongside the original tab entry. There should be just these two entries. 2469 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, prerender)); 2470 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, original)); 2471 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, final)); 2472 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_prerender)); 2473 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab)); 2474 2475 // Swap in the prerendered content. 2476 NavigateToDestURL(); 2477 2478 // The "Prerender: " TaskManager entry should disappear, being replaced by a 2479 // "Tab: Prerender Page" entry, and nothing else. 2480 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, prerender)); 2481 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, original)); 2482 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, final)); 2483 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab)); 2484 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, any_prerender)); 2485} 2486 2487IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, OpenTaskManagerAfterPrerender) { 2488 const base::string16 any_prerender = MatchTaskManagerPrerender("*"); 2489 const base::string16 any_tab = MatchTaskManagerTab("*"); 2490 const base::string16 original = MatchTaskManagerTab("Preloader"); 2491 const base::string16 prerender = MatchTaskManagerPrerender("Prerender Page"); 2492 const base::string16 final = MatchTaskManagerTab("Prerender Page"); 2493 2494 // Start with two resources. 2495 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 2496 2497 // Show the task manager. This populates the model. Importantly, we're doing 2498 // this after the prerender WebContents already exists - the task manager 2499 // needs to find it, it can't just listen for creation. 2500 chrome::OpenTaskManager(current_browser()); 2501 2502 // A TaskManager entry should appear like "Prerender: Prerender Page" 2503 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, prerender)); 2504 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, original)); 2505 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, final)); 2506 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_prerender)); 2507 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab)); 2508 2509 // Swap in the tab. 2510 NavigateToDestURL(); 2511 2512 // The "Prerender: Prerender Page" TaskManager row should disappear, being 2513 // replaced by "Tab: Prerender Page" 2514 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, prerender)); 2515 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, original)); 2516 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, final)); 2517 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab)); 2518 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, any_prerender)); 2519} 2520 2521IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, OpenTaskManagerAfterSwapIn) { 2522 const base::string16 any_prerender = MatchTaskManagerPrerender("*"); 2523 const base::string16 any_tab = MatchTaskManagerTab("*"); 2524 const base::string16 final = MatchTaskManagerTab("Prerender Page"); 2525 2526 // Prerender, and swap it in. 2527 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 2528 NavigateToDestURL(); 2529 2530 // Show the task manager. This populates the model. Importantly, we're doing 2531 // this after the prerender has been swapped in. 2532 chrome::OpenTaskManager(current_browser()); 2533 2534 // We should not see a prerender resource in the task manager, just a normal 2535 // page. 2536 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, final)); 2537 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(1, any_tab)); 2538 ASSERT_NO_FATAL_FAILURE(WaitForTaskManagerRows(0, any_prerender)); 2539} 2540 2541// Checks that audio loads are deferred on prerendering. 2542IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5Audio) { 2543 PrerenderTestURL("files/prerender/prerender_html5_audio.html", 2544 FINAL_STATUS_USED, 2545 1); 2546 NavigateToDestURL(); 2547 WaitForASCIITitle(GetActiveWebContents(), kPassTitle); 2548} 2549 2550// Checks that audio loads are deferred on prerendering and played back when 2551// the prerender is swapped in if autoplay is set. 2552IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5AudioAutoplay) { 2553 PrerenderTestURL("files/prerender/prerender_html5_audio_autoplay.html", 2554 FINAL_STATUS_USED, 2555 1); 2556 NavigateToDestURL(); 2557 WaitForASCIITitle(GetActiveWebContents(), kPassTitle); 2558} 2559 2560// Checks that audio loads are deferred on prerendering and played back when 2561// the prerender is swapped in if js starts playing. 2562IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5AudioJsplay) { 2563 PrerenderTestURL("files/prerender/prerender_html5_audio_jsplay.html", 2564 FINAL_STATUS_USED, 2565 1); 2566 NavigateToDestURL(); 2567 WaitForASCIITitle(GetActiveWebContents(), kPassTitle); 2568} 2569 2570// Checks that video loads are deferred on prerendering. 2571IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5Video) { 2572 PrerenderTestURL("files/prerender/prerender_html5_video.html", 2573 FINAL_STATUS_USED, 2574 1); 2575 NavigateToDestURL(); 2576 WaitForASCIITitle(GetActiveWebContents(), kPassTitle); 2577} 2578 2579// Checks that video tags inserted by javascript are deferred and played 2580// correctly on swap in. 2581IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5VideoJs) { 2582 PrerenderTestURL("files/prerender/prerender_html5_video_script.html", 2583 FINAL_STATUS_USED, 2584 1); 2585 NavigateToDestURL(); 2586 WaitForASCIITitle(GetActiveWebContents(), kPassTitle); 2587} 2588 2589// Checks for correct network events by using a busy sleep the javascript. 2590IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5VideoNetwork) { 2591 DisableJavascriptCalls(); 2592 scoped_ptr<TestPrerender> prerender = 2593 PrerenderTestURL("files/prerender/prerender_html5_video_network.html", 2594 FINAL_STATUS_USED, 2595 1); 2596 WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle); 2597 EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents())); 2598 NavigateToDestURL(); 2599 WaitForASCIITitle(GetActiveWebContents(), kPassTitle); 2600} 2601 2602// Checks that scripts can retrieve the correct window size while prerendering. 2603IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderWindowSize) { 2604 PrerenderTestURL("files/prerender/prerender_size.html", 2605 FINAL_STATUS_USED, 2606 1); 2607 NavigateToDestURL(); 2608} 2609 2610// TODO(jam): http://crbug.com/350550 2611#if !(defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER)) 2612 2613// Checks that prerenderers will terminate when the RenderView crashes. 2614IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderRendererCrash) { 2615 scoped_ptr<TestPrerender> prerender = 2616 PrerenderTestURL("files/prerender/prerender_page.html", 2617 FINAL_STATUS_RENDERER_CRASHED, 2618 1); 2619 2620 // Navigate to about:crash and then wait for the renderer to crash. 2621 ASSERT_TRUE(prerender->contents()); 2622 ASSERT_TRUE(prerender->contents()->prerender_contents()); 2623 prerender->contents()->prerender_contents()->GetController(). 2624 LoadURL( 2625 GURL(content::kChromeUICrashURL), 2626 content::Referrer(), 2627 content::PAGE_TRANSITION_TYPED, 2628 std::string()); 2629 prerender->WaitForStop(); 2630} 2631#endif 2632 2633IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2634 PrerenderPageWithFragment) { 2635 PrerenderTestURL("files/prerender/prerender_page.html#fragment", 2636 FINAL_STATUS_USED, 2637 1); 2638 2639 ChannelDestructionWatcher channel_close_watcher; 2640 channel_close_watcher.WatchChannel(browser()->tab_strip_model()-> 2641 GetActiveWebContents()->GetRenderProcessHost()); 2642 NavigateToDestURL(); 2643 channel_close_watcher.WaitForChannelClose(); 2644 2645 ASSERT_TRUE(IsEmptyPrerenderLinkManager()); 2646} 2647 2648IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2649 PrerenderPageWithRedirectedFragment) { 2650 PrerenderTestURL( 2651 CreateClientRedirect("files/prerender/prerender_page.html#fragment"), 2652 FINAL_STATUS_USED, 2653 2); 2654 2655 ChannelDestructionWatcher channel_close_watcher; 2656 channel_close_watcher.WatchChannel(browser()->tab_strip_model()-> 2657 GetActiveWebContents()->GetRenderProcessHost()); 2658 NavigateToDestURL(); 2659 channel_close_watcher.WaitForChannelClose(); 2660 2661 ASSERT_TRUE(IsEmptyPrerenderLinkManager()); 2662} 2663 2664// Checks that we do not use a prerendered page when navigating from 2665// the main page to a fragment. 2666IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2667 PrerenderPageNavigateFragment) { 2668 PrerenderTestURL("files/prerender/no_prerender_page.html", 2669 FINAL_STATUS_APP_TERMINATING, 2670 1); 2671 NavigateToURLWithDisposition( 2672 "files/prerender/no_prerender_page.html#fragment", 2673 CURRENT_TAB, false); 2674} 2675 2676// Checks that we do not use a prerendered page when we prerender a fragment 2677// but navigate to the main page. 2678IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2679 PrerenderFragmentNavigatePage) { 2680 PrerenderTestURL("files/prerender/no_prerender_page.html#fragment", 2681 FINAL_STATUS_APP_TERMINATING, 2682 1); 2683 NavigateToURLWithDisposition( 2684 "files/prerender/no_prerender_page.html", 2685 CURRENT_TAB, false); 2686} 2687 2688// Checks that we do not use a prerendered page when we prerender a fragment 2689// but navigate to a different fragment on the same page. 2690IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2691 PrerenderFragmentNavigateFragment) { 2692 PrerenderTestURL("files/prerender/no_prerender_page.html#other_fragment", 2693 FINAL_STATUS_APP_TERMINATING, 2694 1); 2695 NavigateToURLWithDisposition( 2696 "files/prerender/no_prerender_page.html#fragment", 2697 CURRENT_TAB, false); 2698} 2699 2700// Checks that we do not use a prerendered page when the page uses a client 2701// redirect to refresh from a fragment on the same page. 2702IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2703 PrerenderClientRedirectFromFragment) { 2704 PrerenderTestURL( 2705 CreateClientRedirect("files/prerender/no_prerender_page.html#fragment"), 2706 FINAL_STATUS_APP_TERMINATING, 2707 2); 2708 NavigateToURLWithDisposition( 2709 "files/prerender/no_prerender_page.html", 2710 CURRENT_TAB, false); 2711} 2712 2713// Checks that we do not use a prerendered page when the page uses a client 2714// redirect to refresh to a fragment on the same page. 2715IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2716 PrerenderClientRedirectToFragment) { 2717 PrerenderTestURL( 2718 CreateClientRedirect("files/prerender/no_prerender_page.html"), 2719 FINAL_STATUS_APP_TERMINATING, 2720 2); 2721 NavigateToURLWithDisposition( 2722 "files/prerender/no_prerender_page.html#fragment", 2723 CURRENT_TAB, false); 2724} 2725 2726// Checks that we correctly use a prerendered page when the page uses JS to set 2727// the window.location.hash to a fragment on the same page. 2728IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2729 PrerenderPageChangeFragmentLocationHash) { 2730 PrerenderTestURL("files/prerender/prerender_fragment_location_hash.html", 2731 FINAL_STATUS_USED, 2732 1); 2733 NavigateToURL("files/prerender/prerender_fragment_location_hash.html"); 2734} 2735 2736// Checks that prerendering a PNG works correctly. 2737IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderImagePng) { 2738 DisableJavascriptCalls(); 2739 PrerenderTestURL("files/prerender/image.png", FINAL_STATUS_USED, 1); 2740 NavigateToDestURL(); 2741} 2742 2743// Checks that prerendering a JPG works correctly. 2744IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderImageJpeg) { 2745 DisableJavascriptCalls(); 2746 PrerenderTestURL("files/prerender/image.jpeg", FINAL_STATUS_USED, 1); 2747 NavigateToDestURL(); 2748} 2749 2750// Checks that a prerender of a CRX will result in a cancellation due to 2751// download. 2752IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCrx) { 2753 PrerenderTestURL("files/prerender/extension.crx", FINAL_STATUS_DOWNLOAD, 0); 2754} 2755 2756// Checks that xhr GET requests allow prerenders. 2757IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrGet) { 2758 PrerenderTestURL("files/prerender/prerender_xhr_get.html", 2759 FINAL_STATUS_USED, 2760 1); 2761 NavigateToDestURL(); 2762} 2763 2764// Checks that xhr HEAD requests allow prerenders. 2765IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrHead) { 2766 PrerenderTestURL("files/prerender/prerender_xhr_head.html", 2767 FINAL_STATUS_USED, 2768 1); 2769 NavigateToDestURL(); 2770} 2771 2772// Checks that xhr OPTIONS requests allow prerenders. 2773IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrOptions) { 2774 PrerenderTestURL("files/prerender/prerender_xhr_options.html", 2775 FINAL_STATUS_USED, 2776 1); 2777 NavigateToDestURL(); 2778} 2779 2780// Checks that xhr TRACE requests allow prerenders. 2781IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrTrace) { 2782 PrerenderTestURL("files/prerender/prerender_xhr_trace.html", 2783 FINAL_STATUS_USED, 2784 1); 2785 NavigateToDestURL(); 2786} 2787 2788// Checks that xhr POST requests allow prerenders. 2789IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrPost) { 2790 PrerenderTestURL("files/prerender/prerender_xhr_post.html", 2791 FINAL_STATUS_USED, 2792 1); 2793 NavigateToDestURL(); 2794} 2795 2796// Checks that xhr PUT cancels prerenders. 2797IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrPut) { 2798 PrerenderTestURL("files/prerender/prerender_xhr_put.html", 2799 FINAL_STATUS_INVALID_HTTP_METHOD, 2800 1); 2801} 2802 2803// Checks that xhr DELETE cancels prerenders. 2804IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderXhrDelete) { 2805 PrerenderTestURL("files/prerender/prerender_xhr_delete.html", 2806 FINAL_STATUS_INVALID_HTTP_METHOD, 2807 1); 2808} 2809 2810// Checks that a top-level page which would trigger an SSL error is canceled. 2811IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorTopLevel) { 2812 net::SpawnedTestServer::SSLOptions ssl_options; 2813 ssl_options.server_certificate = 2814 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME; 2815 net::SpawnedTestServer https_server( 2816 net::SpawnedTestServer::TYPE_HTTPS, ssl_options, 2817 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 2818 ASSERT_TRUE(https_server.Start()); 2819 GURL https_url = https_server.GetURL("files/prerender/prerender_page.html"); 2820 PrerenderTestURL(https_url, 2821 FINAL_STATUS_SSL_ERROR, 2822 0); 2823} 2824 2825// Checks that an SSL error that comes from a subresource does not cancel 2826// the page. Non-main-frame requests are simply cancelled if they run into 2827// an SSL problem. 2828IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorSubresource) { 2829 net::SpawnedTestServer::SSLOptions ssl_options; 2830 ssl_options.server_certificate = 2831 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME; 2832 net::SpawnedTestServer https_server( 2833 net::SpawnedTestServer::TYPE_HTTPS, ssl_options, 2834 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 2835 ASSERT_TRUE(https_server.Start()); 2836 GURL https_url = https_server.GetURL("files/prerender/image.jpeg"); 2837 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 2838 replacement_text.push_back( 2839 std::make_pair("REPLACE_WITH_IMAGE_URL", https_url.spec())); 2840 std::string replacement_path; 2841 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 2842 "files/prerender/prerender_with_image.html", 2843 replacement_text, 2844 &replacement_path)); 2845 PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1); 2846 NavigateToDestURL(); 2847} 2848 2849// Checks that an SSL error that comes from an iframe does not cancel 2850// the page. Non-main-frame requests are simply cancelled if they run into 2851// an SSL problem. 2852IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLErrorIframe) { 2853 net::SpawnedTestServer::SSLOptions ssl_options; 2854 ssl_options.server_certificate = 2855 net::SpawnedTestServer::SSLOptions::CERT_MISMATCHED_NAME; 2856 net::SpawnedTestServer https_server( 2857 net::SpawnedTestServer::TYPE_HTTPS, ssl_options, 2858 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 2859 ASSERT_TRUE(https_server.Start()); 2860 GURL https_url = https_server.GetURL( 2861 "files/prerender/prerender_embedded_content.html"); 2862 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 2863 replacement_text.push_back( 2864 std::make_pair("REPLACE_WITH_URL", https_url.spec())); 2865 std::string replacement_path; 2866 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 2867 "files/prerender/prerender_with_iframe.html", 2868 replacement_text, 2869 &replacement_path)); 2870 PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1); 2871 NavigateToDestURL(); 2872} 2873 2874// Checks that we cancel correctly when window.print() is called. 2875IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPrint) { 2876 DisableLoadEventCheck(); 2877 PrerenderTestURL("files/prerender/prerender_print.html", 2878 FINAL_STATUS_WINDOW_PRINT, 2879 0); 2880} 2881 2882// Checks that if a page is opened in a new window by javascript and both the 2883// pages are in the same domain, the prerendered page is not used, due to 2884// there being other tabs in the same browsing instance. 2885IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2886 PrerenderSameDomainWindowOpenerWindowOpen) { 2887 PrerenderTestURL("files/prerender/prerender_page.html", 2888 FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE, 2889 1); 2890 OpenDestURLViaWindowOpen(); 2891} 2892 2893// Checks that if a page is opened due to click on a href with target="_blank" 2894// and both pages are in the same domain the prerendered page is not used, due 2895// there being other tabs in the same browsing instance. 2896IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2897 PrerenderSameDomainWindowOpenerClickTarget) { 2898 PrerenderTestURL("files/prerender/prerender_page.html", 2899 FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE, 2900 1); 2901 OpenDestURLViaClickTarget(); 2902} 2903 2904// Checks that prerenders do not get swapped into target pages that have opened 2905// a popup, even if the target page itself does not have an opener. 2906IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderTargetHasPopup) { 2907 PrerenderTestURL("files/prerender/prerender_page.html", 2908 FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE, 2909 1); 2910 OpenURLViaWindowOpen(GURL(content::kAboutBlankURL)); 2911 NavigateToDestURLWithDisposition(CURRENT_TAB, false); 2912} 2913 2914class TestClientCertStore : public net::ClientCertStore { 2915 public: 2916 TestClientCertStore() {} 2917 virtual ~TestClientCertStore() {} 2918 2919 // net::ClientCertStore: 2920 virtual void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info, 2921 net::CertificateList* selected_certs, 2922 const base::Closure& callback) OVERRIDE { 2923 *selected_certs = net::CertificateList( 2924 1, scoped_refptr<net::X509Certificate>( 2925 new net::X509Certificate("test", "test", base::Time(), base::Time()))); 2926 callback.Run(); 2927 } 2928}; 2929 2930scoped_ptr<net::ClientCertStore> CreateCertStore() { 2931 return scoped_ptr<net::ClientCertStore>(new TestClientCertStore); 2932} 2933 2934// Checks that a top-level page which would normally request an SSL client 2935// certificate will never be seen since it's an https top-level resource. 2936IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2937 PrerenderSSLClientCertTopLevel) { 2938 ProfileIOData::FromResourceContext( 2939 current_browser()->profile()->GetResourceContext())-> 2940 set_client_cert_store_factory_for_testing( 2941 base::Bind(&CreateCertStore)); 2942 net::SpawnedTestServer::SSLOptions ssl_options; 2943 ssl_options.request_client_certificate = true; 2944 net::SpawnedTestServer https_server( 2945 net::SpawnedTestServer::TYPE_HTTPS, ssl_options, 2946 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 2947 ASSERT_TRUE(https_server.Start()); 2948 GURL https_url = https_server.GetURL("files/prerender/prerender_page.html"); 2949 PrerenderTestURL(https_url, FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED, 0); 2950} 2951 2952// Checks that an SSL Client Certificate request that originates from a 2953// subresource will cancel the prerendered page. 2954IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 2955 PrerenderSSLClientCertSubresource) { 2956 ProfileIOData::FromResourceContext( 2957 current_browser()->profile()->GetResourceContext())-> 2958 set_client_cert_store_factory_for_testing( 2959 base::Bind(&CreateCertStore)); 2960 net::SpawnedTestServer::SSLOptions ssl_options; 2961 ssl_options.request_client_certificate = true; 2962 net::SpawnedTestServer https_server( 2963 net::SpawnedTestServer::TYPE_HTTPS, ssl_options, 2964 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 2965 ASSERT_TRUE(https_server.Start()); 2966 GURL https_url = https_server.GetURL("files/prerender/image.jpeg"); 2967 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 2968 replacement_text.push_back( 2969 std::make_pair("REPLACE_WITH_IMAGE_URL", https_url.spec())); 2970 std::string replacement_path; 2971 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 2972 "files/prerender/prerender_with_image.html", 2973 replacement_text, 2974 &replacement_path)); 2975 PrerenderTestURL(replacement_path, 2976 FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED, 2977 0); 2978} 2979 2980// Checks that an SSL Client Certificate request that originates from an 2981// iframe will cancel the prerendered page. 2982IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSSLClientCertIframe) { 2983 ProfileIOData::FromResourceContext( 2984 current_browser()->profile()->GetResourceContext())-> 2985 set_client_cert_store_factory_for_testing( 2986 base::Bind(&CreateCertStore)); 2987 net::SpawnedTestServer::SSLOptions ssl_options; 2988 ssl_options.request_client_certificate = true; 2989 net::SpawnedTestServer https_server( 2990 net::SpawnedTestServer::TYPE_HTTPS, ssl_options, 2991 base::FilePath(FILE_PATH_LITERAL("chrome/test/data"))); 2992 ASSERT_TRUE(https_server.Start()); 2993 GURL https_url = https_server.GetURL( 2994 "files/prerender/prerender_embedded_content.html"); 2995 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 2996 replacement_text.push_back( 2997 std::make_pair("REPLACE_WITH_URL", https_url.spec())); 2998 std::string replacement_path; 2999 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 3000 "files/prerender/prerender_with_iframe.html", 3001 replacement_text, 3002 &replacement_path)); 3003 PrerenderTestURL(replacement_path, 3004 FINAL_STATUS_SSL_CLIENT_CERTIFICATE_REQUESTED, 3005 0); 3006} 3007 3008#if defined(FULL_SAFE_BROWSING) 3009// Ensures that we do not prerender pages with a safe browsing 3010// interstitial. 3011IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSafeBrowsingTopLevel) { 3012 GURL url = test_server()->GetURL("files/prerender/prerender_page.html"); 3013 GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl( 3014 url, SB_THREAT_TYPE_URL_MALWARE); 3015 PrerenderTestURL("files/prerender/prerender_page.html", 3016 FINAL_STATUS_SAFE_BROWSING, 0); 3017} 3018 3019// Ensures that server redirects to a malware page will cancel prerenders. 3020IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3021 PrerenderSafeBrowsingServerRedirect) { 3022 GURL url = test_server()->GetURL("files/prerender/prerender_page.html"); 3023 GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl( 3024 url, SB_THREAT_TYPE_URL_MALWARE); 3025 PrerenderTestURL(CreateServerRedirect("files/prerender/prerender_page.html"), 3026 FINAL_STATUS_SAFE_BROWSING, 3027 0); 3028} 3029 3030// Ensures that client redirects to a malware page will cancel prerenders. 3031IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3032 PrerenderSafeBrowsingClientRedirect) { 3033 GURL url = test_server()->GetURL("files/prerender/prerender_page.html"); 3034 GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl( 3035 url, SB_THREAT_TYPE_URL_MALWARE); 3036 PrerenderTestURL(CreateClientRedirect("files/prerender/prerender_page.html"), 3037 FINAL_STATUS_SAFE_BROWSING, 3038 1); 3039} 3040 3041// Ensures that we do not prerender pages which have a malware subresource. 3042IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSafeBrowsingSubresource) { 3043 GURL image_url = test_server()->GetURL("files/prerender/image.jpeg"); 3044 GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl( 3045 image_url, SB_THREAT_TYPE_URL_MALWARE); 3046 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 3047 replacement_text.push_back( 3048 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec())); 3049 std::string replacement_path; 3050 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 3051 "files/prerender/prerender_with_image.html", 3052 replacement_text, 3053 &replacement_path)); 3054 PrerenderTestURL(replacement_path, 3055 FINAL_STATUS_SAFE_BROWSING, 3056 0); 3057} 3058 3059// Ensures that we do not prerender pages which have a malware iframe. 3060IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSafeBrowsingIframe) { 3061 GURL iframe_url = test_server()->GetURL( 3062 "files/prerender/prerender_embedded_content.html"); 3063 GetFakeSafeBrowsingDatabaseManager()->SetThreatTypeForUrl( 3064 iframe_url, SB_THREAT_TYPE_URL_MALWARE); 3065 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 3066 replacement_text.push_back( 3067 std::make_pair("REPLACE_WITH_URL", iframe_url.spec())); 3068 std::string replacement_path; 3069 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 3070 "files/prerender/prerender_with_iframe.html", 3071 replacement_text, 3072 &replacement_path)); 3073 PrerenderTestURL(replacement_path, 3074 FINAL_STATUS_SAFE_BROWSING, 3075 0); 3076} 3077 3078#endif 3079 3080// Checks that a local storage read will not cause prerender to fail. 3081IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderLocalStorageRead) { 3082 PrerenderTestURL("files/prerender/prerender_localstorage_read.html", 3083 FINAL_STATUS_USED, 3084 1); 3085 NavigateToDestURL(); 3086} 3087 3088// Checks that a local storage write will not cause prerender to fail. 3089IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderLocalStorageWrite) { 3090 PrerenderTestURL("files/prerender/prerender_localstorage_write.html", 3091 FINAL_STATUS_USED, 3092 1); 3093 NavigateToDestURL(); 3094} 3095 3096// Checks that the favicon is properly loaded on prerender. 3097IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderFavicon) { 3098 scoped_ptr<TestPrerender> prerender = 3099 PrerenderTestURL("files/prerender/prerender_favicon.html", 3100 FINAL_STATUS_USED, 3101 1); 3102 NavigateToDestURL(); 3103 3104 if (!FaviconTabHelper::FromWebContents( 3105 GetActiveWebContents())->FaviconIsValid()) { 3106 // If the favicon has not been set yet, wait for it to be. 3107 content::WindowedNotificationObserver favicon_update_watcher( 3108 chrome::NOTIFICATION_FAVICON_UPDATED, 3109 content::Source<WebContents>(GetActiveWebContents())); 3110 favicon_update_watcher.Wait(); 3111 } 3112 EXPECT_TRUE(FaviconTabHelper::FromWebContents( 3113 GetActiveWebContents())->FaviconIsValid()); 3114} 3115 3116// Checks that when a prerendered page is swapped in to a referring page, the 3117// unload handlers on the referring page are executed. 3118IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderUnload) { 3119 // Matches URL in prerender_loader_with_unload.html. 3120 const GURL unload_url("http://unload-url.test"); 3121 base::FilePath empty_file = ui_test_utils::GetTestFilePath( 3122 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("empty.html"))); 3123 RequestCounter unload_counter; 3124 BrowserThread::PostTask( 3125 BrowserThread::IO, FROM_HERE, 3126 base::Bind(&CreateCountingProtocolHandlerOnIO, 3127 unload_url, empty_file, unload_counter.AsWeakPtr())); 3128 3129 set_loader_path("files/prerender/prerender_loader_with_unload.html"); 3130 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 3131 NavigateToDestURL(); 3132 unload_counter.WaitForCount(1); 3133} 3134 3135// Checks that a hanging unload on the referring page of a prerender swap does 3136// not crash the browser on exit. 3137IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHangingUnload) { 3138 // Matches URL in prerender_loader_with_unload.html. 3139 const GURL hang_url("http://unload-url.test"); 3140 base::FilePath empty_file = ui_test_utils::GetTestFilePath( 3141 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("empty.html"))); 3142 BrowserThread::PostTask( 3143 BrowserThread::IO, FROM_HERE, 3144 base::Bind(&CreateHangingFirstRequestProtocolHandlerOnIO, 3145 hang_url, empty_file, 3146 base::Closure())); 3147 3148 set_loader_path("files/prerender/prerender_loader_with_unload.html"); 3149 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 3150 NavigateToDestURL(); 3151} 3152 3153 3154// Checks that when the history is cleared, prerendering is cancelled and 3155// prerendering history is cleared. 3156IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClearHistory) { 3157 scoped_ptr<TestPrerender> prerender = 3158 PrerenderTestURL("files/prerender/prerender_page.html", 3159 FINAL_STATUS_CACHE_OR_HISTORY_CLEARED, 3160 1); 3161 3162 ClearBrowsingData(current_browser(), BrowsingDataRemover::REMOVE_HISTORY); 3163 prerender->WaitForStop(); 3164 3165 // Make sure prerender history was cleared. 3166 EXPECT_EQ(0, GetHistoryLength()); 3167} 3168 3169// Checks that when the cache is cleared, prerenders are cancelled but 3170// prerendering history is not cleared. 3171IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClearCache) { 3172 scoped_ptr<TestPrerender> prerender = 3173 PrerenderTestURL("files/prerender/prerender_page.html", 3174 FINAL_STATUS_CACHE_OR_HISTORY_CLEARED, 3175 1); 3176 3177 ClearBrowsingData(current_browser(), BrowsingDataRemover::REMOVE_CACHE); 3178 prerender->WaitForStop(); 3179 3180 // Make sure prerender history was not cleared. Not a vital behavior, but 3181 // used to compare with PrerenderClearHistory test. 3182 EXPECT_EQ(1, GetHistoryLength()); 3183} 3184 3185IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelAll) { 3186 scoped_ptr<TestPrerender> prerender = 3187 PrerenderTestURL("files/prerender/prerender_page.html", 3188 FINAL_STATUS_CANCELLED, 3189 1); 3190 3191 GetPrerenderManager()->CancelAllPrerenders(); 3192 prerender->WaitForStop(); 3193 3194 EXPECT_FALSE(prerender->contents()); 3195} 3196 3197IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderEvents) { 3198 scoped_ptr<TestPrerender> prerender = 3199 PrerenderTestURL("files/prerender/prerender_page.html", 3200 FINAL_STATUS_CANCELLED, 1); 3201 3202 GetPrerenderManager()->CancelAllPrerenders(); 3203 prerender->WaitForStop(); 3204 3205 EXPECT_TRUE(DidReceivePrerenderStartEventForLinkNumber(0)); 3206 EXPECT_TRUE(DidReceivePrerenderStopEventForLinkNumber(0)); 3207 EXPECT_FALSE(HadPrerenderEventErrors()); 3208} 3209 3210// Cancels the prerender of a page with its own prerender. The second prerender 3211// should never be started. 3212IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3213 PrerenderCancelPrerenderWithPrerender) { 3214 scoped_ptr<TestPrerender> prerender = 3215 PrerenderTestURL("files/prerender/prerender_infinite_a.html", 3216 FINAL_STATUS_CANCELLED, 3217 1); 3218 3219 GetPrerenderManager()->CancelAllPrerenders(); 3220 prerender->WaitForStop(); 3221 3222 EXPECT_FALSE(prerender->contents()); 3223} 3224 3225// Prerendering and history tests. 3226// The prerendered page is navigated to in several ways [navigate via 3227// omnibox, click on link, key-modified click to open in background tab, etc], 3228// followed by a navigation to another page from the prerendered page, followed 3229// by a back navigation. 3230 3231IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNavigateClickGoBack) { 3232 PrerenderTestURL("files/prerender/prerender_page_with_link.html", 3233 FINAL_STATUS_USED, 3234 1); 3235 NavigateToDestURL(); 3236 ClickToNextPageAfterPrerender(); 3237 GoBackToPrerender(); 3238} 3239 3240IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNavigateNavigateGoBack) { 3241 PrerenderTestURL("files/prerender/prerender_page_with_link.html", 3242 FINAL_STATUS_USED, 3243 1); 3244 NavigateToDestURL(); 3245 NavigateToNextPageAfterPrerender(); 3246 GoBackToPrerender(); 3247} 3248 3249IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickClickGoBack) { 3250 PrerenderTestURL("files/prerender/prerender_page_with_link.html", 3251 FINAL_STATUS_USED, 3252 1); 3253 OpenDestURLViaClick(); 3254 ClickToNextPageAfterPrerender(); 3255 GoBackToPrerender(); 3256} 3257 3258IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNavigateGoBack) { 3259 PrerenderTestURL("files/prerender/prerender_page_with_link.html", 3260 FINAL_STATUS_USED, 3261 1); 3262 OpenDestURLViaClick(); 3263 NavigateToNextPageAfterPrerender(); 3264 GoBackToPrerender(); 3265} 3266 3267IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewWindow) { 3268 // Prerender currently doesn't interpose on this navigation. 3269 // http://crbug.com/345474. 3270 PrerenderTestURL("files/prerender/prerender_page_with_link.html", 3271 FINAL_STATUS_USED, 3272 1); 3273 OpenDestURLViaClickNewWindow(); 3274} 3275 3276IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewForegroundTab) { 3277 // Prerender currently doesn't interpose on this navigation. 3278 // http://crbug.com/345474. 3279 PrerenderTestURL("files/prerender/prerender_page_with_link.html", 3280 FINAL_STATUS_USED, 3281 1); 3282 OpenDestURLViaClickNewForegroundTab(); 3283} 3284 3285IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderClickNewBackgroundTab) { 3286 // Prerender currently doesn't interpose on this navigation. 3287 // http://crbug.com/345474. 3288 scoped_ptr<TestPrerender> prerender = 3289 PrerenderTestURL("files/prerender/prerender_page_with_link.html", 3290 FINAL_STATUS_USED, 3291 1); 3292 ASSERT_TRUE(prerender->contents()); 3293 prerender->contents()->set_should_be_shown(false); 3294 OpenDestURLViaClickNewBackgroundTab(); 3295} 3296 3297IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3298 NavigateToPrerenderedPageWhenDevToolsAttached) { 3299 DisableJavascriptCalls(); 3300 WebContents* web_contents = 3301 current_browser()->tab_strip_model()->GetActiveWebContents(); 3302 scoped_refptr<DevToolsAgentHost> agent(DevToolsAgentHost::GetOrCreateFor( 3303 web_contents->GetRenderViewHost())); 3304 DevToolsManager* manager = DevToolsManager::GetInstance(); 3305 FakeDevToolsClientHost client_host; 3306 manager->RegisterDevToolsClientHostFor(agent.get(), &client_host); 3307 const char* url = "files/prerender/prerender_page.html"; 3308 PrerenderTestURL(url, FINAL_STATUS_DEVTOOLS_ATTACHED, 1); 3309 NavigateToURLWithDisposition(url, CURRENT_TAB, false); 3310 manager->ClientHostClosing(&client_host); 3311} 3312 3313// Validate that the sessionStorage namespace remains the same when swapping 3314// in a prerendered page. 3315IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSessionStorage) { 3316 set_loader_path("files/prerender/prerender_loader_with_session_storage.html"); 3317 PrerenderTestURL(GetCrossDomainTestUrl("files/prerender/prerender_page.html"), 3318 FINAL_STATUS_USED, 3319 1); 3320 NavigateToDestURL(); 3321 GoBackToPageBeforePrerender(); 3322} 3323 3324// Checks that the control group works. An XHR PUT cannot be detected in the 3325// control group. 3326IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ControlGroup) { 3327 RestorePrerenderMode restore_prerender_mode; 3328 PrerenderManager::SetMode( 3329 PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP); 3330 DisableJavascriptCalls(); 3331 PrerenderTestURL("files/prerender/prerender_xhr_put.html", 3332 FINAL_STATUS_WOULD_HAVE_BEEN_USED, 0); 3333 NavigateToDestURL(); 3334} 3335 3336// Checks that the control group correctly hits WOULD_HAVE_BEEN_USED 3337// renderer-initiated navigations. (This verifies that the ShouldFork logic 3338// behaves correctly.) 3339IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ControlGroupRendererInitiated) { 3340 RestorePrerenderMode restore_prerender_mode; 3341 PrerenderManager::SetMode( 3342 PrerenderManager::PRERENDER_MODE_EXPERIMENT_CONTROL_GROUP); 3343 DisableJavascriptCalls(); 3344 PrerenderTestURL("files/prerender/prerender_xhr_put.html", 3345 FINAL_STATUS_WOULD_HAVE_BEEN_USED, 0); 3346 OpenDestURLViaClick(); 3347} 3348 3349// Make sure that the MatchComplete dummy works in the normal case. Once 3350// a prerender is cancelled because of a script, a dummy must be created to 3351// account for the MatchComplete case, and it must have a final status of 3352// FINAL_STATUS_WOULD_HAVE_BEEN_USED. 3353IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MatchCompleteDummy) { 3354 UMAHistogramHelper histograms; 3355 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 NavigateToDestURL(); 3368 histograms.Fetch(); 3369 histograms.ExpectTotalCount("Prerender.websame_PerceivedPLT", 1); 3370 histograms.ExpectTotalCount("Prerender.websame_PerceivedPLTMatched", 0); 3371 histograms.ExpectTotalCount( 3372 "Prerender.websame_PerceivedPLTMatchedComplete", 1); 3373} 3374 3375// Verify that a navigation that hits a MatchComplete dummy while another is in 3376// progress does not also classify the previous navigation as a MatchComplete. 3377IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3378 MatchCompleteDummyCancelNavigation) { 3379 UMAHistogramHelper histograms; 3380 3381 // Arrange for a URL to hang. 3382 const GURL kNoCommitUrl("http://never-respond.example.com"); 3383 base::FilePath file(FILE_PATH_LITERAL( 3384 "chrome/test/data/prerender/prerender_page.html")); 3385 base::RunLoop hang_loop; 3386 BrowserThread::PostTask( 3387 BrowserThread::IO, FROM_HERE, 3388 base::Bind(&CreateHangingFirstRequestProtocolHandlerOnIO, 3389 kNoCommitUrl, file, hang_loop.QuitClosure())); 3390 3391 // First, fire a prerender that aborts after it completes its load. 3392 std::vector<FinalStatus> expected_final_status_queue; 3393 expected_final_status_queue.push_back(FINAL_STATUS_INVALID_HTTP_METHOD); 3394 expected_final_status_queue.push_back(FINAL_STATUS_WOULD_HAVE_BEEN_USED); 3395 PrerenderTestURL("files/prerender/prerender_xhr_put.html", 3396 expected_final_status_queue, 1); 3397 histograms.Fetch(); 3398 histograms.ExpectTotalCount("Prerender.none_PerceivedPLT", 1); 3399 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0); 3400 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0); 3401 histograms.ExpectTotalCount("Prerender.websame_PrerenderNotSwappedInPLT", 1); 3402 3403 // Open the hanging URL in a new tab. Wait for both the new tab to open and 3404 // the hanging request to be scheduled. 3405 ui_test_utils::NavigateToURLWithDisposition( 3406 current_browser(), kNoCommitUrl, NEW_FOREGROUND_TAB, 3407 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB); 3408 hang_loop.Run(); 3409 3410 // Now interrupt that navigation and navigate to the destination URL. This 3411 // should forcibly complete the previous navigation and also complete a 3412 // WOULD_HAVE_BEEN_PRERENDERED navigation. 3413 NavigateToDestURL(); 3414 histograms.Fetch(); 3415 histograms.ExpectTotalCount("Prerender.none_PerceivedPLT", 2); 3416 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0); 3417 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0); 3418 histograms.ExpectTotalCount("Prerender.websame_PerceivedPLT", 1); 3419 histograms.ExpectTotalCount("Prerender.websame_PerceivedPLTMatched", 0); 3420 histograms.ExpectTotalCount( 3421 "Prerender.websame_PerceivedPLTMatchedComplete", 1); 3422} 3423 3424class PrerenderBrowserTestWithNaCl : public PrerenderBrowserTest { 3425 public: 3426 PrerenderBrowserTestWithNaCl() {} 3427 virtual ~PrerenderBrowserTestWithNaCl() {} 3428 3429 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 3430 PrerenderBrowserTest::SetUpCommandLine(command_line); 3431 command_line->AppendSwitch(switches::kEnableNaCl); 3432 } 3433}; 3434 3435// Check that NaCl plugins work when enabled, with prerendering. 3436IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithNaCl, 3437 PrerenderNaClPluginEnabled) { 3438#if defined(OS_WIN) && defined(USE_ASH) 3439 // Disable this test in Metro+Ash for now (http://crbug.com/262796). 3440 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) 3441 return; 3442#endif 3443 3444 PrerenderTestURL("files/prerender/prerender_plugin_nacl_enabled.html", 3445 FINAL_STATUS_USED, 3446 1); 3447 NavigateToDestURL(); 3448 3449 // To avoid any chance of a race, we have to let the script send its response 3450 // asynchronously. 3451 WebContents* web_contents = 3452 browser()->tab_strip_model()->GetActiveWebContents(); 3453 bool display_test_result = false; 3454 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(web_contents, 3455 "DidDisplayReallyPass()", 3456 &display_test_result)); 3457 ASSERT_TRUE(display_test_result); 3458} 3459 3460// Checks that the referrer policy is used when prerendering. 3461IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReferrerPolicy) { 3462 set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html"); 3463 PrerenderTestURL("files/prerender/prerender_referrer_policy.html", 3464 FINAL_STATUS_USED, 3465 1); 3466 NavigateToDestURL(); 3467} 3468 3469// Checks that the referrer policy is used when prerendering on HTTPS. 3470IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3471 PrerenderSSLReferrerPolicy) { 3472 UseHttpsSrcServer(); 3473 set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html"); 3474 PrerenderTestURL("files/prerender/prerender_referrer_policy.html", 3475 FINAL_STATUS_USED, 3476 1); 3477 NavigateToDestURL(); 3478} 3479 3480// Checks that the referrer policy is used when prerendering is cancelled. 3481IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCancelReferrerPolicy) { 3482 scoped_ptr<TestContentBrowserClient> test_content_browser_client( 3483 new TestContentBrowserClient); 3484 content::ContentBrowserClient* original_browser_client = 3485 content::SetBrowserClientForTesting(test_content_browser_client.get()); 3486 3487 set_loader_path("files/prerender/prerender_loader_with_referrer_policy.html"); 3488 PrerenderTestURL("files/prerender/prerender_referrer_policy.html", 3489 FINAL_STATUS_CANCELLED, 3490 1); 3491 OpenDestURLViaClick(); 3492 3493 bool display_test_result = false; 3494 WebContents* web_contents = 3495 browser()->tab_strip_model()->GetActiveWebContents(); 3496 ASSERT_TRUE(content::ExecuteScriptAndExtractBool( 3497 web_contents, 3498 "window.domAutomationController.send(DidDisplayPass())", 3499 &display_test_result)); 3500 EXPECT_TRUE(display_test_result); 3501 3502 content::SetBrowserClientForTesting(original_browser_client); 3503} 3504 3505// Test interaction of the webNavigation and tabs API with prerender. 3506class PrerenderBrowserTestWithExtensions : public PrerenderBrowserTest, 3507 public ExtensionApiTest { 3508 public: 3509 PrerenderBrowserTestWithExtensions() { 3510 // The individual tests start the test server through ExtensionApiTest, so 3511 // the port number can be passed through to the extension. 3512 autostart_test_server_ = false; 3513 } 3514 3515 virtual void SetUp() OVERRIDE { 3516 PrerenderBrowserTest::SetUp(); 3517 } 3518 3519 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 3520 PrerenderBrowserTest::SetUpCommandLine(command_line); 3521 ExtensionApiTest::SetUpCommandLine(command_line); 3522 } 3523 3524 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 3525 PrerenderBrowserTest::SetUpInProcessBrowserTestFixture(); 3526 ExtensionApiTest::SetUpInProcessBrowserTestFixture(); 3527 } 3528 3529 virtual void TearDownInProcessBrowserTestFixture() OVERRIDE { 3530 PrerenderBrowserTest::TearDownInProcessBrowserTestFixture(); 3531 ExtensionApiTest::TearDownInProcessBrowserTestFixture(); 3532 } 3533 3534 virtual void SetUpOnMainThread() OVERRIDE { 3535 PrerenderBrowserTest::SetUpOnMainThread(); 3536 } 3537}; 3538 3539IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, WebNavigation) { 3540 ASSERT_TRUE(StartSpawnedTestServer()); 3541 extensions::FrameNavigationState::set_allow_extension_scheme(true); 3542 3543 // Wait for the extension to set itself up and return control to us. 3544 ASSERT_TRUE(RunExtensionTest("webnavigation/prerender")) << message_; 3545 3546 ResultCatcher catcher; 3547 3548 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 3549 3550 ChannelDestructionWatcher channel_close_watcher; 3551 channel_close_watcher.WatchChannel(browser()->tab_strip_model()-> 3552 GetActiveWebContents()->GetRenderProcessHost()); 3553 NavigateToDestURL(); 3554 channel_close_watcher.WaitForChannelClose(); 3555 3556 ASSERT_TRUE(IsEmptyPrerenderLinkManager()); 3557 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); 3558} 3559 3560IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, TabsApi) { 3561 ASSERT_TRUE(StartSpawnedTestServer()); 3562 extensions::FrameNavigationState::set_allow_extension_scheme(true); 3563 3564 // Wait for the extension to set itself up and return control to us. 3565 ASSERT_TRUE(RunExtensionTest("tabs/on_replaced")) << message_; 3566 3567 ResultCatcher catcher; 3568 3569 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 3570 3571 ChannelDestructionWatcher channel_close_watcher; 3572 channel_close_watcher.WatchChannel(browser()->tab_strip_model()-> 3573 GetActiveWebContents()->GetRenderProcessHost()); 3574 NavigateToDestURL(); 3575 channel_close_watcher.WaitForChannelClose(); 3576 3577 ASSERT_TRUE(IsEmptyPrerenderLinkManager()); 3578 ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); 3579} 3580 3581// Test that prerenders abort when navigating to a stream. 3582// See chrome/browser/extensions/api/streams_private/streams_private_apitest.cc 3583IN_PROC_BROWSER_TEST_F(PrerenderBrowserTestWithExtensions, StreamsTest) { 3584 ASSERT_TRUE(StartSpawnedTestServer()); 3585 3586 const extensions::Extension* extension = LoadExtension( 3587 test_data_dir_.AppendASCII("streams_private/handle_mime_type")); 3588 ASSERT_TRUE(extension); 3589 EXPECT_EQ(std::string(extension_misc::kStreamsPrivateTestExtensionId), 3590 extension->id()); 3591 MimeTypesHandler* handler = MimeTypesHandler::GetHandler(extension); 3592 ASSERT_TRUE(handler); 3593 EXPECT_TRUE(handler->CanHandleMIMEType("application/msword")); 3594 3595 PrerenderTestURL("files/prerender/document.doc", FINAL_STATUS_DOWNLOAD, 0); 3596 3597 // Sanity-check that the extension would have picked up the stream in a normal 3598 // navigation had prerender not intercepted it. 3599 // streams_private/handle_mime_type reports success if it has handled the 3600 // application/msword type. 3601 ResultCatcher catcher; 3602 NavigateToDestURL(); 3603 EXPECT_TRUE(catcher.GetNextResult()); 3604} 3605 3606// Checks that non-http/https/chrome-extension subresource cancels the 3607// prerender. 3608IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3609 PrerenderCancelSubresourceUnsupportedScheme) { 3610 GURL image_url = GURL("invalidscheme://www.google.com/test.jpg"); 3611 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 3612 replacement_text.push_back( 3613 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec())); 3614 std::string replacement_path; 3615 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 3616 "files/prerender/prerender_with_image.html", 3617 replacement_text, 3618 &replacement_path)); 3619 PrerenderTestURL(replacement_path, FINAL_STATUS_UNSUPPORTED_SCHEME, 0); 3620} 3621 3622// Ensure that about:blank is permitted for any subresource. 3623IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3624 PrerenderAllowAboutBlankSubresource) { 3625 GURL image_url = GURL("about:blank"); 3626 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 3627 replacement_text.push_back( 3628 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec())); 3629 std::string replacement_path; 3630 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 3631 "files/prerender/prerender_with_image.html", 3632 replacement_text, 3633 &replacement_path)); 3634 PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1); 3635 NavigateToDestURL(); 3636} 3637 3638// Checks that non-http/https/chrome-extension subresource cancels the prerender 3639// on redirect. 3640IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3641 PrerenderCancelSubresourceRedirectUnsupportedScheme) { 3642 GURL image_url = test_server()->GetURL( 3643 CreateServerRedirect("invalidscheme://www.google.com/test.jpg")); 3644 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 3645 replacement_text.push_back( 3646 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec())); 3647 std::string replacement_path; 3648 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 3649 "files/prerender/prerender_with_image.html", 3650 replacement_text, 3651 &replacement_path)); 3652 PrerenderTestURL(replacement_path, FINAL_STATUS_UNSUPPORTED_SCHEME, 0); 3653} 3654 3655// Checks that chrome-extension subresource does not cancel the prerender. 3656IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3657 PrerenderKeepSubresourceExtensionScheme) { 3658 GURL image_url = GURL("chrome-extension://abcdefg/test.jpg"); 3659 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 3660 replacement_text.push_back( 3661 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec())); 3662 std::string replacement_path; 3663 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 3664 "files/prerender/prerender_with_image.html", 3665 replacement_text, 3666 &replacement_path)); 3667 PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1); 3668 NavigateToDestURL(); 3669} 3670 3671// Checks that redirect to chrome-extension subresource does not cancel the 3672// prerender. 3673IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3674 PrerenderKeepSubresourceRedirectExtensionScheme) { 3675 GURL image_url = test_server()->GetURL( 3676 CreateServerRedirect("chrome-extension://abcdefg/test.jpg")); 3677 std::vector<net::SpawnedTestServer::StringPair> replacement_text; 3678 replacement_text.push_back( 3679 std::make_pair("REPLACE_WITH_IMAGE_URL", image_url.spec())); 3680 std::string replacement_path; 3681 ASSERT_TRUE(net::SpawnedTestServer::GetFilePathWithReplacements( 3682 "files/prerender/prerender_with_image.html", 3683 replacement_text, 3684 &replacement_path)); 3685 PrerenderTestURL(replacement_path, FINAL_STATUS_USED, 1); 3686 NavigateToDestURL(); 3687} 3688 3689// Checks that non-http/https main page redirects cancel the prerender. 3690IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3691 PrerenderCancelMainFrameRedirectUnsupportedScheme) { 3692 GURL url = test_server()->GetURL( 3693 CreateServerRedirect("invalidscheme://www.google.com/test.html")); 3694 PrerenderTestURL(url, FINAL_STATUS_UNSUPPORTED_SCHEME, 0); 3695} 3696 3697// Checks that media source video loads are deferred on prerendering. 3698IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderHTML5MediaSourceVideo) { 3699 PrerenderTestURL("files/prerender/prerender_html5_video_media_source.html", 3700 FINAL_STATUS_USED, 3701 1); 3702 NavigateToDestURL(); 3703 WaitForASCIITitle(GetActiveWebContents(), kPassTitle); 3704} 3705 3706// Checks that a prerender that creates an audio stream (via a WebAudioDevice) 3707// is cancelled. 3708IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderWebAudioDevice) { 3709 DisableLoadEventCheck(); 3710 PrerenderTestURL("files/prerender/prerender_web_audio_device.html", 3711 FINAL_STATUS_CREATING_AUDIO_STREAM, 0); 3712} 3713 3714// Checks that prerenders do not swap in to WebContents being captured. 3715IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCapturedWebContents) { 3716 PrerenderTestURL("files/prerender/prerender_page.html", 3717 FINAL_STATUS_PAGE_BEING_CAPTURED, 1); 3718 WebContents* web_contents = GetActiveWebContents(); 3719 web_contents->IncrementCapturerCount(gfx::Size()); 3720 NavigateToDestURLWithDisposition(CURRENT_TAB, false); 3721 web_contents->DecrementCapturerCount(); 3722} 3723 3724// Checks that prerenders are aborted on cross-process navigation from 3725// a server redirect. 3726IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3727 PrerenderCrossProcessServerRedirect) { 3728 // Force everything to be a process swap. 3729 SwapProcessesContentBrowserClient test_browser_client; 3730 content::ContentBrowserClient* original_browser_client = 3731 content::SetBrowserClientForTesting(&test_browser_client); 3732 3733 PrerenderTestURL( 3734 CreateServerRedirect("files/prerender/prerender_page.html"), 3735 FINAL_STATUS_OPEN_URL, 0); 3736 3737 content::SetBrowserClientForTesting(original_browser_client); 3738} 3739 3740// Checks that URLRequests for prerenders being aborted on cross-process 3741// navigation from a server redirect are cleaned up, so they don't keep cache 3742// entries locked. 3743// See http://crbug.com/341134 3744IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3745 PrerenderCrossProcessServerRedirectNoHang) { 3746 const char kDestPath[] = "files/prerender/prerender_page.html"; 3747 // Force everything to be a process swap. 3748 SwapProcessesContentBrowserClient test_browser_client; 3749 content::ContentBrowserClient* original_browser_client = 3750 content::SetBrowserClientForTesting(&test_browser_client); 3751 3752 PrerenderTestURL(CreateServerRedirect(kDestPath), FINAL_STATUS_OPEN_URL, 0); 3753 3754 ui_test_utils::NavigateToURL( 3755 browser(), 3756 test_server()->GetURL(kDestPath)); 3757 3758 content::SetBrowserClientForTesting(original_browser_client); 3759} 3760 3761// Checks that prerenders are aborted on cross-process navigation from 3762// a client redirect. 3763IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3764 PrerenderCrossProcessClientRedirect) { 3765 // Cross-process navigation logic for renderer-initiated navigations 3766 // is partially controlled by the renderer, namely 3767 // ChromeContentRendererClient. This test instead relies on the Web 3768 // Store triggering such navigations. 3769 std::string webstore_url = extension_urls::GetWebstoreLaunchURL(); 3770 3771 // Mock out requests to the Web Store. 3772 base::FilePath file(GetTestPath("prerender_page.html")); 3773 BrowserThread::PostTask( 3774 BrowserThread::IO, FROM_HERE, 3775 base::Bind(&CreateMockProtocolHandlerOnIO, 3776 GURL(webstore_url), file)); 3777 3778 PrerenderTestURL(CreateClientRedirect(webstore_url), 3779 FINAL_STATUS_OPEN_URL, 1); 3780} 3781 3782// Checks that canceling a MatchComplete dummy doesn't result in two 3783// stop events. 3784IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, CancelMatchCompleteDummy) { 3785 std::vector<FinalStatus> expected_final_status_queue; 3786 expected_final_status_queue.push_back(FINAL_STATUS_JAVASCRIPT_ALERT); 3787 expected_final_status_queue.push_back(FINAL_STATUS_CANCELLED); 3788 ScopedVector<TestPrerender> prerenders = 3789 PrerenderTestURL("files/prerender/prerender_alert_before_onload.html", 3790 expected_final_status_queue, 0); 3791 3792 // Cancel the MatchComplete dummy. 3793 GetPrerenderManager()->CancelAllPrerenders(); 3794 prerenders[1]->WaitForStop(); 3795 3796 // Check the referring page only got one copy of the event. 3797 EXPECT_FALSE(HadPrerenderEventErrors()); 3798} 3799 3800// Checks that a deferred redirect to an image is not loaded until the page is 3801// visible. Also test the right histogram events are emitted in this case. 3802IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredImage) { 3803 DisableJavascriptCalls(); 3804 UMAHistogramHelper histograms; 3805 3806 // The prerender will not completely load until after the swap, so wait for a 3807 // title change before calling DidPrerenderPass. 3808 scoped_ptr<TestPrerender> prerender = 3809 PrerenderTestURL( 3810 "files/prerender/prerender_deferred_image.html", 3811 FINAL_STATUS_USED, 0); 3812 WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle); 3813 EXPECT_EQ(1, GetPrerenderDomContentLoadedEventCountForLinkNumber(0)); 3814 EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents())); 3815 EXPECT_EQ(0, prerender->number_of_loads()); 3816 histograms.Fetch(); 3817 histograms.ExpectTotalCount("Prerender.none_PerceivedPLT", 1); 3818 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0); 3819 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0); 3820 histograms.ExpectTotalCount("Prerender.websame_PrerenderNotSwappedInPLT", 0); 3821 3822 // Swap. 3823 NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(), 3824 GetActiveWebContents()); 3825 ui_test_utils::NavigateToURLWithDisposition( 3826 current_browser(), dest_url(), CURRENT_TAB, 3827 ui_test_utils::BROWSER_TEST_NONE); 3828 swap_observer.Wait(); 3829 3830 // The prerender never observes the final load. 3831 EXPECT_EQ(0, prerender->number_of_loads()); 3832 3833 // Now check DidDisplayPass. 3834 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents())); 3835 3836 histograms.Fetch(); 3837 histograms.ExpectTotalCount("Prerender.websame_PrerenderNotSwappedInPLT", 0); 3838 histograms.ExpectTotalCount("Prerender.websame_PerceivedPLT", 1); 3839 histograms.ExpectTotalCount("Prerender.websame_PerceivedPLTMatched", 1); 3840 histograms.ExpectTotalCount( 3841 "Prerender.websame_PerceivedPLTMatchedComplete", 1); 3842} 3843 3844// Checks that a deferred redirect to an image is not loaded until the 3845// page is visible, even after another redirect. 3846IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3847 PrerenderDeferredImageAfterRedirect) { 3848 DisableJavascriptCalls(); 3849 3850 // The prerender will not completely load until after the swap, so wait for a 3851 // title change before calling DidPrerenderPass. 3852 scoped_ptr<TestPrerender> prerender = 3853 PrerenderTestURL( 3854 "files/prerender/prerender_deferred_image.html", 3855 FINAL_STATUS_USED, 0); 3856 WaitForASCIITitle(prerender->contents()->prerender_contents(), kReadyTitle); 3857 EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents())); 3858 EXPECT_EQ(0, prerender->number_of_loads()); 3859 3860 // Swap. 3861 NavigationOrSwapObserver swap_observer(current_browser()->tab_strip_model(), 3862 GetActiveWebContents()); 3863 ui_test_utils::NavigateToURLWithDisposition( 3864 current_browser(), dest_url(), CURRENT_TAB, 3865 ui_test_utils::BROWSER_TEST_NONE); 3866 swap_observer.Wait(); 3867 3868 // The prerender never observes the final load. 3869 EXPECT_EQ(0, prerender->number_of_loads()); 3870 3871 // Now check DidDisplayPass. 3872 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents())); 3873} 3874 3875// Checks that deferred redirects in the main frame are followed. 3876IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredMainFrame) { 3877 DisableJavascriptCalls(); 3878 PrerenderTestURL( 3879 "files/prerender/image-deferred.png", 3880 FINAL_STATUS_USED, 1); 3881 NavigateToDestURL(); 3882} 3883 3884// Checks that deferred redirects in the main frame are followed, even 3885// with a double-redirect. 3886IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3887 PrerenderDeferredMainFrameAfterRedirect) { 3888 DisableJavascriptCalls(); 3889 PrerenderTestURL( 3890 CreateServerRedirect("files/prerender/image-deferred.png"), 3891 FINAL_STATUS_USED, 1); 3892 NavigateToDestURL(); 3893} 3894 3895// Checks that deferred redirects in a synchronous XHR abort the 3896// prerender. 3897IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDeferredSynchronousXHR) { 3898 PrerenderTestURL("files/prerender/prerender_deferred_sync_xhr.html", 3899 FINAL_STATUS_BAD_DEFERRED_REDIRECT, 0); 3900 NavigateToDestURL(); 3901} 3902 3903// Checks that prerenders are not swapped for navigations with extra headers. 3904IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderExtraHeadersNoSwap) { 3905 PrerenderTestURL("files/prerender/prerender_page.html", 3906 FINAL_STATUS_APP_TERMINATING, 1); 3907 3908 content::OpenURLParams params(dest_url(), Referrer(), CURRENT_TAB, 3909 content::PAGE_TRANSITION_TYPED, false); 3910 params.extra_headers = "X-Custom-Header: 42\r\n"; 3911 NavigateToURLWithParams(params, false); 3912} 3913 3914// Checks that prerenders are not swapped for navigations with browser-initiated 3915// POST data. 3916IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 3917 PrerenderBrowserInitiatedPostNoSwap) { 3918 PrerenderTestURL("files/prerender/prerender_page.html", 3919 FINAL_STATUS_APP_TERMINATING, 1); 3920 3921 std::string post_data = "DATA"; 3922 content::OpenURLParams params(dest_url(), Referrer(), CURRENT_TAB, 3923 content::PAGE_TRANSITION_TYPED, false); 3924 params.uses_post = true; 3925 params.browser_initiated_post_data = 3926 base::RefCountedString::TakeString(&post_data); 3927 NavigateToURLWithParams(params, false); 3928} 3929 3930// Checks that the prerendering of a page is canceled correctly when the 3931// prerendered page tries to make a second navigation entry. 3932IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderNewNavigationEntry) { 3933 PrerenderTestURL("files/prerender/prerender_new_entry.html", 3934 FINAL_STATUS_NEW_NAVIGATION_ENTRY, 3935 1); 3936} 3937 3938// Attempt a swap-in in a new tab, verifying that session storage namespace 3939// merging works. 3940IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageNewTab) { 3941 // Mock out some URLs and count the number of requests to one of them. Both 3942 // prerender_session_storage.html and init_session_storage.html need to be 3943 // mocked so they are same-origin. 3944 const GURL kInitURL("http://prerender.test/init_session_storage.html"); 3945 base::FilePath init_file = GetTestPath("init_session_storage.html"); 3946 BrowserThread::PostTask( 3947 BrowserThread::IO, FROM_HERE, 3948 base::Bind(&CreateMockProtocolHandlerOnIO, kInitURL, init_file)); 3949 3950 const GURL kTestURL("http://prerender.test/prerender_session_storage.html"); 3951 base::FilePath test_file = GetTestPath("prerender_session_storage.html"); 3952 RequestCounter counter; 3953 BrowserThread::PostTask( 3954 BrowserThread::IO, FROM_HERE, 3955 base::Bind(&CreateCountingProtocolHandlerOnIO, 3956 kTestURL, test_file, counter.AsWeakPtr())); 3957 3958 PrerenderTestURL(kTestURL, FINAL_STATUS_USED, 1); 3959 3960 // Open a new tab to navigate in. 3961 ui_test_utils::NavigateToURLWithDisposition( 3962 current_browser(), kInitURL, NEW_FOREGROUND_TAB, 3963 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 3964 3965 // Now navigate in the new tab. Set expect_swap_to_succeed to false because 3966 // the swap does not occur synchronously. 3967 // 3968 // TODO(davidben): When all swaps become asynchronous, remove the OpenURL 3969 // return value assertion and let this go through the usual successful-swap 3970 // codepath. 3971 NavigateToDestURLWithDisposition(CURRENT_TAB, false); 3972 3973 // Verify DidDisplayPass manually since the previous call skipped it. 3974 EXPECT_TRUE(DidDisplayPass( 3975 current_browser()->tab_strip_model()->GetActiveWebContents())); 3976 3977 // Only one request to the test URL started. 3978 // 3979 // TODO(davidben): Re-enable this check when the races in attaching the 3980 // throttle are resolved. http://crbug.com/335835 3981 // EXPECT_EQ(1, counter.count()); 3982} 3983 3984// Attempt a swap-in in a new tab, verifying that session storage namespace 3985// merging works. Unlike the above test, the swap is for a navigation that would 3986// normally be cross-process. 3987IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPageNewTabCrossProcess) { 3988 base::FilePath test_data_dir; 3989 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)); 3990 3991 // Mock out some URLs and count the number of requests to one of them. Both 3992 // prerender_session_storage.html and init_session_storage.html need to be 3993 // mocked so they are same-origin. 3994 const GURL kInitURL("http://prerender.test/init_session_storage.html"); 3995 base::FilePath init_file = GetTestPath("init_session_storage.html"); 3996 BrowserThread::PostTask( 3997 BrowserThread::IO, FROM_HERE, 3998 base::Bind(&CreateMockProtocolHandlerOnIO, kInitURL, init_file)); 3999 4000 const GURL kTestURL("http://prerender.test/prerender_session_storage.html"); 4001 base::FilePath test_file = GetTestPath("prerender_session_storage.html"); 4002 RequestCounter counter; 4003 BrowserThread::PostTask( 4004 BrowserThread::IO, FROM_HERE, 4005 base::Bind(&CreateCountingProtocolHandlerOnIO, 4006 kTestURL, test_file, counter.AsWeakPtr())); 4007 4008 PrerenderTestURL(kTestURL, FINAL_STATUS_USED, 1); 4009 4010 // Open a new tab to navigate in. 4011 ui_test_utils::NavigateToURLWithDisposition( 4012 current_browser(), kInitURL, NEW_FOREGROUND_TAB, 4013 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 4014 4015 // Navigate to about:blank so the next navigation is cross-process. 4016 ui_test_utils::NavigateToURL(current_browser(), 4017 GURL(content::kAboutBlankURL)); 4018 4019 // Now navigate in the new tab. Set expect_swap_to_succeed to false because 4020 // the swap does not occur synchronously. 4021 // 4022 // TODO(davidben): When all swaps become asynchronous, remove the OpenURL 4023 // return value assertion and let this go through the usual successful-swap 4024 // codepath. 4025 NavigateToDestURLWithDisposition(CURRENT_TAB, false); 4026 4027 // Verify DidDisplayPass manually since the previous call skipped it. 4028 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents())); 4029 4030 // Only one request to the test URL started. 4031 // 4032 // TODO(davidben): Re-enable this check when the races in attaching the 4033 // throttle are resolved. http://crbug.com/335835 4034 // EXPECT_EQ(1, counter.count()); 4035} 4036 4037// Verify that session storage conflicts don't merge. 4038IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderSessionStorageConflict) { 4039 PrerenderTestURL("files/prerender/prerender_session_storage_conflict.html", 4040 FINAL_STATUS_APP_TERMINATING, 1); 4041 4042 // Open a new tab to navigate in. 4043 ui_test_utils::NavigateToURLWithDisposition( 4044 current_browser(), 4045 test_server()->GetURL("files/prerender/init_session_storage.html"), 4046 NEW_FOREGROUND_TAB, 4047 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 4048 4049 // Now navigate in the new tab. 4050 NavigateToDestURLWithDisposition(CURRENT_TAB, false); 4051 4052 // Verify DidDisplayPass in the new tab. 4053 EXPECT_TRUE(DidDisplayPass(GetActiveWebContents())); 4054} 4055 4056// Checks that prerenders honor |should_replace_current_entry|. 4057IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderReplaceCurrentEntry) { 4058 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 4059 4060 content::OpenURLParams params(dest_url(), Referrer(), CURRENT_TAB, 4061 content::PAGE_TRANSITION_TYPED, false); 4062 params.should_replace_current_entry = true; 4063 NavigateToURLWithParams(params, false); 4064 4065 const NavigationController& controller = 4066 GetActiveWebContents()->GetController(); 4067 // First entry is about:blank, second is prerender_page.html. 4068 EXPECT_TRUE(controller.GetPendingEntry() == NULL); 4069 EXPECT_EQ(2, controller.GetEntryCount()); 4070 EXPECT_EQ(GURL(content::kAboutBlankURL), 4071 controller.GetEntryAtIndex(0)->GetURL()); 4072 EXPECT_EQ(dest_url(), controller.GetEntryAtIndex(1)->GetURL()); 4073} 4074 4075// Checks prerender does not hit DCHECKs and behaves properly if two pending 4076// swaps occur in a row. 4077IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDoublePendingSwap) { 4078 GetPrerenderManager()->mutable_config().max_link_concurrency = 2; 4079 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2; 4080 4081 GURL url1 = test_server()->GetURL("files/prerender/prerender_page.html?1"); 4082 scoped_ptr<TestPrerender> prerender1 = 4083 PrerenderTestURL(url1, FINAL_STATUS_APP_TERMINATING, 1); 4084 4085 GURL url2 = test_server()->GetURL("files/prerender/prerender_page.html?2"); 4086 scoped_ptr<TestPrerender> prerender2 = ExpectPrerender(FINAL_STATUS_USED); 4087 AddPrerender(url2, 1); 4088 prerender2->WaitForStart(); 4089 prerender2->WaitForLoads(1); 4090 4091 // There's no reason the second prerender can't be used, but the swap races 4092 // with didStartProvisionalLoad and didFailProvisionalLoad from the previous 4093 // navigation. The current logic will conservatively fail to swap under such 4094 // races. However, if the renderer is slow enough, it's possible for the 4095 // prerender to still be used, so don't program in either expectation. 4096 ASSERT_TRUE(prerender2->contents()); 4097 prerender2->contents()->set_skip_final_checks(true); 4098 4099 // Open a new tab to navigate in. 4100 ui_test_utils::NavigateToURLWithDisposition( 4101 current_browser(), GURL(content::kAboutBlankURL), NEW_FOREGROUND_TAB, 4102 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 4103 4104 // Fire off two navigations, without running the event loop between them. 4105 NavigationOrSwapObserver swap_observer( 4106 current_browser()->tab_strip_model(), 4107 GetActiveWebContents(), 2); 4108 current_browser()->OpenURL(OpenURLParams( 4109 url1, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false)); 4110 current_browser()->OpenURL(OpenURLParams( 4111 url2, Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_TYPED, false)); 4112 swap_observer.Wait(); 4113 4114 // The WebContents should be on url2. There may be 2 or 3 entries, depending 4115 // on whether the first one managed to complete. 4116 // 4117 // TODO(davidben): When http://crbug.com/335835 is fixed, the 3 entry case 4118 // shouldn't be possible because it's throttled by the pending swap that 4119 // cannot complete. 4120 const NavigationController& controller = 4121 GetActiveWebContents()->GetController(); 4122 EXPECT_TRUE(controller.GetPendingEntry() == NULL); 4123 EXPECT_LE(2, controller.GetEntryCount()); 4124 EXPECT_GE(3, controller.GetEntryCount()); 4125 EXPECT_EQ(GURL(content::kAboutBlankURL), 4126 controller.GetEntryAtIndex(0)->GetURL()); 4127 EXPECT_EQ(url2, controller.GetEntryAtIndex( 4128 controller.GetEntryCount() - 1)->GetURL()); 4129} 4130 4131// Verify that pending swaps get aborted on new navigations. 4132IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 4133 PrerenderPendingSwapNewNavigation) { 4134 PrerenderManager::HangSessionStorageMergesForTesting(); 4135 4136 PrerenderTestURL("files/prerender/prerender_page.html", 4137 FINAL_STATUS_APP_TERMINATING, 1); 4138 4139 // Open a new tab to navigate in. 4140 ui_test_utils::NavigateToURLWithDisposition( 4141 current_browser(), GURL(content::kAboutBlankURL), NEW_FOREGROUND_TAB, 4142 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 4143 4144 // Navigate to the URL. Wait for DidStartLoading, just so it's definitely 4145 // progressed somewhere. 4146 content::WindowedNotificationObserver page_load_observer( 4147 content::NOTIFICATION_LOAD_START, 4148 content::Source<NavigationController>( 4149 &GetActiveWebContents()->GetController())); 4150 current_browser()->OpenURL(OpenURLParams( 4151 dest_url(), Referrer(), CURRENT_TAB, 4152 content::PAGE_TRANSITION_TYPED, false)); 4153 page_load_observer.Wait(); 4154 4155 // Navigate somewhere else. This should succeed and abort the pending swap. 4156 TestNavigationObserver nav_observer(GetActiveWebContents()); 4157 current_browser()->OpenURL(OpenURLParams( 4158 GURL(content::kAboutBlankURL), Referrer(), CURRENT_TAB, 4159 content::PAGE_TRANSITION_TYPED, false)); 4160 nav_observer.Wait(); 4161} 4162 4163// Checks that <a ping> requests are not dropped in prerender. 4164IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPing) { 4165 // Count hits to a certain URL. 4166 const GURL kPingURL("http://prerender.test/ping"); 4167 base::FilePath empty_file = ui_test_utils::GetTestFilePath( 4168 base::FilePath(), base::FilePath(FILE_PATH_LITERAL("empty.html"))); 4169 RequestCounter ping_counter; 4170 BrowserThread::PostTask( 4171 BrowserThread::IO, FROM_HERE, 4172 base::Bind(&CreateCountingProtocolHandlerOnIO, 4173 kPingURL, empty_file, ping_counter.AsWeakPtr())); 4174 4175 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 4176 OpenDestURLViaClickPing(kPingURL); 4177 4178 ping_counter.WaitForCount(1); 4179} 4180 4181IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderPPLTNormalNavigation) { 4182 UMAHistogramHelper histograms; 4183 4184 GURL url = test_server()->GetURL("files/prerender/prerender_page.html"); 4185 ui_test_utils::NavigateToURL(current_browser(), url); 4186 histograms.Fetch(); 4187 histograms.ExpectTotalCount("Prerender.none_PerceivedPLT", 1); 4188 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatched", 0); 4189 histograms.ExpectTotalCount("Prerender.none_PerceivedPLTMatchedComplete", 0); 4190} 4191 4192IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 4193 PrerenderCookieChangeConflictTest) { 4194 NavigateStraightToURL( 4195 "files/prerender/prerender_cookie.html?set=1&key=c&value=1"); 4196 4197 GURL url = test_server()->GetURL( 4198 "files/prerender/prerender_cookie.html?set=1&key=c&value=2"); 4199 4200 scoped_ptr<TestPrerender> prerender = 4201 ExpectPrerender(FINAL_STATUS_COOKIE_CONFLICT); 4202 AddPrerender(url, 1); 4203 prerender->WaitForStart(); 4204 prerender->WaitForLoads(1); 4205 // Ensure that in the prerendered page, querying the cookie again 4206 // via javascript yields the same value that was set during load. 4207 EXPECT_TRUE(DidPrerenderPass(prerender->contents()->prerender_contents())); 4208 4209 // The prerender has loaded. Ensure that the change is not visible 4210 // to visible tabs. 4211 std::string value; 4212 RunJSReturningString("GetCookie('c')", &value); 4213 ASSERT_EQ(value, "1"); 4214 4215 // Make a conflicting cookie change, which should cancel the prerender. 4216 RunJS("SetCookie('c', '3')"); 4217 prerender->WaitForStop(); 4218} 4219 4220IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderCookieChangeUseTest) { 4221 // Permit 2 concurrent prerenders. 4222 GetPrerenderManager()->mutable_config().max_link_concurrency = 2; 4223 GetPrerenderManager()->mutable_config().max_link_concurrency_per_launcher = 2; 4224 4225 // Go to a first URL setting the cookie to value "1". 4226 NavigateStraightToURL( 4227 "files/prerender/prerender_cookie.html?set=1&key=c&value=1"); 4228 4229 // Prerender a URL setting the cookie to value "2". 4230 GURL url = test_server()->GetURL( 4231 "files/prerender/prerender_cookie.html?set=1&key=c&value=2"); 4232 4233 scoped_ptr<TestPrerender> prerender1 = ExpectPrerender(FINAL_STATUS_USED); 4234 AddPrerender(url, 1); 4235 prerender1->WaitForStart(); 4236 prerender1->WaitForLoads(1); 4237 4238 // Launch a second prerender, setting the cookie to value "3". 4239 scoped_ptr<TestPrerender> prerender2 = 4240 ExpectPrerender(FINAL_STATUS_COOKIE_CONFLICT); 4241 AddPrerender(test_server()->GetURL( 4242 "files/prerender/prerender_cookie.html?set=1&key=c&value=3"), 1); 4243 prerender2->WaitForStart(); 4244 prerender2->WaitForLoads(1); 4245 4246 // Both prerenders have loaded. Ensure that the visible tab is still 4247 // unchanged and cannot see their changes. 4248 // to visible tabs. 4249 std::string value; 4250 RunJSReturningString("GetCookie('c')", &value); 4251 ASSERT_EQ(value, "1"); 4252 4253 // Navigate to the prerendered URL. The first prerender should be swapped in, 4254 // and the changes should now be visible. The second prerender should 4255 // be cancelled due to the conflict. 4256 ui_test_utils::NavigateToURLWithDisposition( 4257 current_browser(), 4258 url, 4259 CURRENT_TAB, 4260 ui_test_utils::BROWSER_TEST_NONE); 4261 RunJSReturningString("GetCookie('c')", &value); 4262 ASSERT_EQ(value, "2"); 4263 prerender2->WaitForStop(); 4264} 4265 4266IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, 4267 PrerenderCookieChangeConflictHTTPHeaderTest) { 4268 NavigateStraightToURL( 4269 "files/prerender/prerender_cookie.html?set=1&key=c&value=1"); 4270 4271 GURL url = test_server()->GetURL("set-cookie?c=2"); 4272 scoped_ptr<TestPrerender> prerender = 4273 ExpectPrerender(FINAL_STATUS_COOKIE_CONFLICT); 4274 AddPrerender(url, 1); 4275 prerender->WaitForStart(); 4276 prerender->WaitForLoads(1); 4277 4278 // The prerender has loaded. Ensure that the change is not visible 4279 // to visible tabs. 4280 std::string value; 4281 RunJSReturningString("GetCookie('c')", &value); 4282 ASSERT_EQ(value, "1"); 4283 4284 // Make a conflicting cookie change, which should cancel the prerender. 4285 RunJS("SetCookie('c', '3')"); 4286 prerender->WaitForStop(); 4287} 4288 4289// Checks that a prerender which calls window.close() on itself is aborted. 4290IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderWindowClose) { 4291 DisableLoadEventCheck(); 4292 PrerenderTestURL("files/prerender/prerender_window_close.html", 4293 FINAL_STATUS_CLOSED, 0); 4294} 4295 4296class PrerenderIncognitoBrowserTest : public PrerenderBrowserTest { 4297 public: 4298 virtual void SetUpOnMainThread() OVERRIDE { 4299 Profile* normal_profile = current_browser()->profile(); 4300 set_browser(ui_test_utils::OpenURLOffTheRecord( 4301 normal_profile, GURL("about:blank"))); 4302 PrerenderBrowserTest::SetUpOnMainThread(); 4303 } 4304}; 4305 4306// Checks that prerendering works in incognito mode. 4307IN_PROC_BROWSER_TEST_F(PrerenderIncognitoBrowserTest, PrerenderIncognito) { 4308 PrerenderTestURL("files/prerender/prerender_page.html", FINAL_STATUS_USED, 1); 4309 NavigateToDestURL(); 4310} 4311 4312// Checks that prerenders are aborted when an incognito profile is closed. 4313IN_PROC_BROWSER_TEST_F(PrerenderIncognitoBrowserTest, 4314 PrerenderIncognitoClosed) { 4315 scoped_ptr<TestPrerender> prerender = 4316 PrerenderTestURL("files/prerender/prerender_page.html", 4317 FINAL_STATUS_PROFILE_DESTROYED, 1); 4318 current_browser()->window()->Close(); 4319 prerender->WaitForStop(); 4320} 4321 4322class PrerenderOmniboxBrowserTest : public PrerenderBrowserTest { 4323 public: 4324 LocationBar* GetLocationBar() { 4325 return current_browser()->window()->GetLocationBar(); 4326 } 4327 4328 OmniboxView* GetOmniboxView() { 4329 return GetLocationBar()->GetOmniboxView(); 4330 } 4331 4332 void WaitForAutocompleteDone(OmniboxView* omnibox_view) { 4333 AutocompleteController* controller = 4334 omnibox_view->model()->popup_model()->autocomplete_controller(); 4335 while (!controller->done()) { 4336 content::WindowedNotificationObserver ready_observer( 4337 chrome::NOTIFICATION_AUTOCOMPLETE_CONTROLLER_RESULT_READY, 4338 content::Source<AutocompleteController>(controller)); 4339 ready_observer.Wait(); 4340 } 4341 } 4342 4343 predictors::AutocompleteActionPredictor* GetAutocompleteActionPredictor() { 4344 Profile* profile = current_browser()->profile(); 4345 return predictors::AutocompleteActionPredictorFactory::GetForProfile( 4346 profile); 4347 } 4348 4349 scoped_ptr<TestPrerender> StartOmniboxPrerender( 4350 const GURL& url, 4351 FinalStatus expected_final_status) { 4352 scoped_ptr<TestPrerender> prerender = 4353 ExpectPrerender(expected_final_status); 4354 WebContents* web_contents = GetActiveWebContents(); 4355 GetAutocompleteActionPredictor()->StartPrerendering( 4356 url, 4357 web_contents->GetController().GetSessionStorageNamespaceMap(), 4358 gfx::Size(50, 50)); 4359 prerender->WaitForStart(); 4360 return prerender.Pass(); 4361 } 4362}; 4363 4364// Checks that closing the omnibox popup cancels an omnibox prerender. 4365IN_PROC_BROWSER_TEST_F(PrerenderOmniboxBrowserTest, PrerenderOmniboxCancel) { 4366 // Ensure the cookie store has been loaded. 4367 if (!GetPrerenderManager()->cookie_store_loaded()) { 4368 base::RunLoop loop; 4369 GetPrerenderManager()->set_on_cookie_store_loaded_cb_for_testing( 4370 loop.QuitClosure()); 4371 loop.Run(); 4372 } 4373 4374 // Fake an omnibox prerender. 4375 scoped_ptr<TestPrerender> prerender = StartOmniboxPrerender( 4376 test_server()->GetURL("files/empty.html"), 4377 FINAL_STATUS_CANCELLED); 4378 4379 // Revert the location bar. This should cancel the prerender. 4380 GetLocationBar()->Revert(); 4381 prerender->WaitForStop(); 4382} 4383 4384// Checks that closing the omnibox popup cancels an omnibox prerender. 4385IN_PROC_BROWSER_TEST_F(PrerenderOmniboxBrowserTest, PrerenderOmniboxAbandon) { 4386 // Set the abandon timeout to something high so it does not introduce 4387 // flakiness if the prerender times out before the test completes. 4388 GetPrerenderManager()->mutable_config().abandon_time_to_live = 4389 base::TimeDelta::FromDays(999); 4390 4391 // Ensure the cookie store has been loaded. 4392 if (!GetPrerenderManager()->cookie_store_loaded()) { 4393 base::RunLoop loop; 4394 GetPrerenderManager()->set_on_cookie_store_loaded_cb_for_testing( 4395 loop.QuitClosure()); 4396 loop.Run(); 4397 } 4398 4399 // Enter a URL into the Omnibox. 4400 OmniboxView* omnibox_view = GetOmniboxView(); 4401 omnibox_view->OnBeforePossibleChange(); 4402 omnibox_view->SetUserText( 4403 base::UTF8ToUTF16(test_server()->GetURL("files/empty.html?1").spec())); 4404 omnibox_view->OnAfterPossibleChange(); 4405 WaitForAutocompleteDone(omnibox_view); 4406 4407 // Fake an omnibox prerender for a different URL. 4408 scoped_ptr<TestPrerender> prerender = StartOmniboxPrerender( 4409 test_server()->GetURL("files/empty.html?2"), 4410 FINAL_STATUS_APP_TERMINATING); 4411 4412 // Navigate to the URL entered. 4413 omnibox_view->model()->AcceptInput(CURRENT_TAB, false); 4414 4415 // Prerender should be running, but abandoned. 4416 EXPECT_TRUE( 4417 GetAutocompleteActionPredictor()->IsPrerenderAbandonedForTesting()); 4418} 4419 4420} // namespace prerender 4421