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