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 <set> 6 #include <utility> 7 8 #include "base/files/file_path.h" 9 #include "base/logging.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/run_loop.h" 12 #include "base/threading/sequenced_worker_pool.h" 13 #include "chrome/browser/net/url_request_mock_util.h" 14 #include "chrome/browser/prerender/prerender_contents.h" 15 #include "chrome/browser/prerender/prerender_manager.h" 16 #include "chrome/browser/prerender/prerender_resource_throttle.h" 17 #include "chrome/browser/prerender/prerender_tracker.h" 18 #include "chrome/test/base/testing_browser_process.h" 19 #include "content/public/browser/resource_controller.h" 20 #include "content/public/browser/resource_request_info.h" 21 #include "content/public/test/test_browser_thread.h" 22 #include "content/test/net/url_request_mock_http_job.h" 23 #include "net/base/request_priority.h" 24 #include "net/url_request/url_request.h" 25 #include "net/url_request/url_request_test_util.h" 26 #include "testing/gtest/include/gtest/gtest.h" 27 28 using content::BrowserThread; 29 30 namespace prerender { 31 32 namespace { 33 34 class TestPrerenderContents : public PrerenderContents { 35 public: 36 TestPrerenderContents(PrerenderManager* prerender_manager, 37 int child_id, int route_id) 38 : PrerenderContents(prerender_manager, static_cast<Profile*>(NULL), 39 GURL(), content::Referrer(), ORIGIN_NONE, 40 PrerenderManager::kNoExperiment), 41 child_id_(child_id), 42 route_id_(route_id) { 43 } 44 45 virtual ~TestPrerenderContents() { 46 if (final_status() == FINAL_STATUS_MAX) 47 SetFinalStatus(FINAL_STATUS_USED); 48 } 49 50 virtual bool GetChildId(int* child_id) const OVERRIDE { 51 *child_id = child_id_; 52 return true; 53 } 54 55 virtual bool GetRouteId(int* route_id) const OVERRIDE { 56 *route_id = route_id_; 57 return true; 58 } 59 60 void Start() { 61 AddObserver(prerender_manager()->prerender_tracker()); 62 prerendering_has_started_ = true; 63 NotifyPrerenderStart(); 64 } 65 66 void Cancel() { 67 Destroy(FINAL_STATUS_CANCELLED); 68 } 69 70 void Use() { 71 SetFinalStatus(FINAL_STATUS_USED); 72 PrepareForUse(); 73 } 74 75 private: 76 int child_id_; 77 int route_id_; 78 }; 79 80 class TestPrerenderManager : public PrerenderManager { 81 public: 82 explicit TestPrerenderManager(PrerenderTracker* prerender_tracker) : 83 PrerenderManager(NULL, prerender_tracker) { 84 mutable_config().rate_limit_enabled = false; 85 } 86 87 virtual void DestroyPrerenderForRenderView( 88 int process_id, int view_id, FinalStatus final_status) OVERRIDE { 89 cancelled_id_pairs_.insert(std::make_pair(process_id, view_id)); 90 } 91 92 // We never allocate our PrerenderContents in PrerenderManager, so we don't 93 // ever want the default pending delete behaviour. 94 virtual void MoveEntryToPendingDelete(PrerenderContents* entry, 95 FinalStatus final_status) OVERRIDE { 96 } 97 98 bool WasPrerenderCancelled(int child_id, int route_id) { 99 std::pair<int, int> child_route_id_pair(child_id, route_id); 100 return cancelled_id_pairs_.count(child_route_id_pair) != 0; 101 } 102 103 // Set of all the RenderViews that have been cancelled. 104 std::set<std::pair<int, int> > cancelled_id_pairs_; 105 }; 106 107 class DeferredRedirectDelegate : public net::URLRequest::Delegate, 108 public content::ResourceController { 109 public: 110 DeferredRedirectDelegate() 111 : throttle_(NULL), 112 was_deferred_(false), 113 cancel_called_(false), 114 resume_called_(false) { 115 } 116 117 void SetThrottle(PrerenderResourceThrottle* throttle) { 118 throttle_ = throttle; 119 throttle_->set_controller_for_testing(this); 120 } 121 122 void Run() { 123 run_loop_.reset(new base::RunLoop()); 124 run_loop_->Run(); 125 } 126 127 bool was_deferred() const { return was_deferred_; } 128 bool cancel_called() const { return cancel_called_; } 129 bool resume_called() const { return resume_called_; } 130 131 // net::URLRequest::Delegate implementation: 132 virtual void OnReceivedRedirect(net::URLRequest* request, 133 const GURL& new_url, 134 bool* defer_redirect) OVERRIDE { 135 // Defer the redirect either way. 136 *defer_redirect = true; 137 138 // Find out what the throttle would have done. 139 throttle_->WillRedirectRequest(new_url, &was_deferred_); 140 run_loop_->Quit(); 141 } 142 virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE { } 143 virtual void OnReadCompleted(net::URLRequest* request, 144 int bytes_read) OVERRIDE { 145 } 146 147 // content::ResourceController implementation: 148 virtual void Cancel() OVERRIDE { 149 EXPECT_FALSE(cancel_called_); 150 EXPECT_FALSE(resume_called_); 151 152 cancel_called_ = true; 153 run_loop_->Quit(); 154 } 155 virtual void CancelAndIgnore() OVERRIDE { Cancel(); } 156 virtual void CancelWithError(int error_code) OVERRIDE { Cancel(); } 157 virtual void Resume() OVERRIDE { 158 EXPECT_TRUE(was_deferred_); 159 EXPECT_FALSE(cancel_called_); 160 EXPECT_FALSE(resume_called_); 161 162 resume_called_ = true; 163 run_loop_->Quit(); 164 } 165 166 private: 167 scoped_ptr<base::RunLoop> run_loop_; 168 PrerenderResourceThrottle* throttle_; 169 bool was_deferred_; 170 bool cancel_called_; 171 bool resume_called_; 172 173 DISALLOW_COPY_AND_ASSIGN(DeferredRedirectDelegate); 174 }; 175 176 } // namespace 177 178 class PrerenderTrackerTest : public testing::Test { 179 public: 180 static const int kDefaultChildId = 0; 181 static const int kDefaultRouteId = 100; 182 183 PrerenderTrackerTest() : 184 ui_thread_(BrowserThread::UI, &message_loop_), 185 io_thread_(BrowserThread::IO, &message_loop_), 186 prerender_manager_(prerender_tracker()), 187 test_contents_(&prerender_manager_, kDefaultChildId, kDefaultRouteId) { 188 chrome_browser_net::SetUrlRequestMocksEnabled(true); 189 } 190 191 virtual ~PrerenderTrackerTest() { 192 chrome_browser_net::SetUrlRequestMocksEnabled(false); 193 194 // Cleanup work so the file IO tasks from URLRequestMockHTTPJob 195 // are gone. 196 content::BrowserThread::GetBlockingPool()->FlushForTesting(); 197 RunEvents(); 198 } 199 200 PrerenderTracker* prerender_tracker() { 201 return g_browser_process->prerender_tracker(); 202 } 203 204 TestPrerenderManager* prerender_manager() { 205 return &prerender_manager_; 206 } 207 208 TestPrerenderContents* test_contents() { 209 return &test_contents_; 210 } 211 212 int GetCurrentStatus(int child_id, int route_id) { 213 FinalStatus final_status; 214 if (!prerender_tracker()->GetFinalStatus(child_id, route_id, 215 &final_status)) { 216 return -1; 217 } 218 return final_status; 219 } 220 221 // Runs any tasks queued on either thread. 222 void RunEvents() { 223 message_loop_.RunUntilIdle(); 224 } 225 226 private: 227 base::MessageLoopForIO message_loop_; 228 content::TestBrowserThread ui_thread_; 229 content::TestBrowserThread io_thread_; 230 231 TestPrerenderManager prerender_manager_; 232 TestPrerenderContents test_contents_; 233 }; 234 235 // Check that a non-existant RenderView is handled correctly. 236 TEST_F(PrerenderTrackerTest, PrerenderTrackerNull) { 237 EXPECT_FALSE(prerender_tracker()->TryUse(kDefaultChildId, kDefaultRouteId)); 238 EXPECT_FALSE(prerender_tracker()->TryCancel( 239 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 240 EXPECT_FALSE(prerender_tracker()->TryCancelOnIOThread( 241 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 242 EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread( 243 kDefaultChildId, kDefaultRouteId)); 244 FinalStatus final_status; 245 EXPECT_FALSE(prerender_tracker()->GetFinalStatus( 246 kDefaultChildId, kDefaultRouteId, &final_status)); 247 EXPECT_FALSE(prerender_manager()->WasPrerenderCancelled( 248 kDefaultChildId, kDefaultRouteId)); 249 } 250 251 // Check that a page that is used is handled correctly. 252 TEST_F(PrerenderTrackerTest, PrerenderTrackerUsed) { 253 test_contents()->Start(); 254 255 EXPECT_EQ(FINAL_STATUS_MAX, 256 GetCurrentStatus(kDefaultChildId, kDefaultRouteId)); 257 258 // This calls AddPrerenderOnIOThreadTask(). 259 RunEvents(); 260 261 EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread( 262 kDefaultChildId, kDefaultRouteId)); 263 EXPECT_EQ(FINAL_STATUS_MAX, 264 GetCurrentStatus(kDefaultChildId, kDefaultRouteId)); 265 266 // Display the prerendered RenderView. 267 EXPECT_TRUE(prerender_tracker()->TryUse(kDefaultChildId, kDefaultRouteId)); 268 269 // Make sure the page can't be destroyed or claim it was destroyed after 270 // it's been used. 271 EXPECT_FALSE(prerender_tracker()->TryCancel( 272 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 273 EXPECT_FALSE(prerender_tracker()->TryCancelOnIOThread( 274 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_TIMED_OUT)); 275 EXPECT_EQ(FINAL_STATUS_USED, 276 GetCurrentStatus(kDefaultChildId, kDefaultRouteId)); 277 278 // This would call DestroyPrerenderForChildRouteIdPair(), if the prerender 279 // were cancelled. 280 RunEvents(); 281 282 // These functions should all behave as before. 283 EXPECT_FALSE(prerender_tracker()->TryCancel( 284 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 285 EXPECT_FALSE(prerender_tracker()->TryCancelOnIOThread( 286 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_TIMED_OUT)); 287 EXPECT_EQ(FINAL_STATUS_USED, GetCurrentStatus( 288 kDefaultChildId, kDefaultRouteId)); 289 290 // This calls DestroyPrerenderForChildRouteIdPair(). 291 test_contents()->Use(); 292 EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread( 293 kDefaultChildId, kDefaultRouteId)); 294 295 // This calls RemovePrerenderOnIOThreadTask(). 296 RunEvents(); 297 298 FinalStatus final_status; 299 EXPECT_FALSE(prerender_tracker()->GetFinalStatus( 300 kDefaultChildId, kDefaultRouteId, &final_status)); 301 EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread( 302 kDefaultChildId, kDefaultRouteId)); 303 EXPECT_FALSE(prerender_tracker()->TryCancel( 304 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 305 EXPECT_FALSE(prerender_manager()->WasPrerenderCancelled( 306 kDefaultChildId, kDefaultRouteId)); 307 } 308 309 // Check that a prerendered page cancelled by TryCancel() is handled correctly. 310 TEST_F(PrerenderTrackerTest, PrerenderTrackerCancelled) { 311 test_contents()->Start(); 312 EXPECT_EQ(FINAL_STATUS_MAX, 313 GetCurrentStatus(kDefaultChildId, kDefaultRouteId)); 314 315 // This calls AddPrerenderOnIOThreadTask(). 316 RunEvents(); 317 318 // Cancel the prerender. 319 EXPECT_TRUE(prerender_tracker()->TryCancel( 320 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 321 322 EXPECT_FALSE(prerender_tracker()->TryUse(kDefaultChildId, kDefaultRouteId)); 323 EXPECT_TRUE(prerender_tracker()->TryCancel( 324 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_TIMED_OUT)); 325 EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread( 326 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_TIMED_OUT)); 327 EXPECT_EQ(FINAL_STATUS_CANCELLED, 328 GetCurrentStatus(kDefaultChildId, kDefaultRouteId)); 329 330 // This calls DestroyPrerenderForChildRouteIdPair(). 331 RunEvents(); 332 EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled( 333 kDefaultChildId, kDefaultRouteId)); 334 335 // These should all work until the prerendering RenderViewHost is destroyed. 336 EXPECT_TRUE(prerender_tracker()->TryCancel( 337 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_TIMED_OUT)); 338 EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread( 339 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_TIMED_OUT)); 340 EXPECT_EQ(FINAL_STATUS_CANCELLED, 341 GetCurrentStatus(kDefaultChildId, kDefaultRouteId)); 342 343 test_contents()->Cancel(); 344 EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread( 345 kDefaultChildId, kDefaultRouteId)); 346 347 // This calls RemovePrerenderOnIOThreadTask(). 348 RunEvents(); 349 350 FinalStatus final_status; 351 EXPECT_FALSE(prerender_tracker()->GetFinalStatus( 352 kDefaultChildId, kDefaultRouteId, &final_status)); 353 EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread( 354 kDefaultChildId, kDefaultRouteId)); 355 } 356 357 // Check that a prerendered page cancelled on the IO thread by 358 // TryCancelOnIOThread() is handled correctly. 359 TEST_F(PrerenderTrackerTest, PrerenderTrackerCancelledOnIO) { 360 test_contents()->Start(); 361 EXPECT_EQ(FINAL_STATUS_MAX, 362 GetCurrentStatus(kDefaultChildId, kDefaultRouteId)); 363 364 // This calls AddPrerenderOnIOThreadTask(). 365 RunEvents(); 366 367 // Cancel the prerender. 368 EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread( 369 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_TIMED_OUT)); 370 371 EXPECT_FALSE(prerender_tracker()->TryUse(kDefaultChildId, kDefaultRouteId)); 372 EXPECT_TRUE(prerender_tracker()->TryCancel(kDefaultChildId, kDefaultRouteId, 373 FINAL_STATUS_CANCELLED)); 374 EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread( 375 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 376 EXPECT_EQ(FINAL_STATUS_TIMED_OUT, 377 GetCurrentStatus(kDefaultChildId, kDefaultRouteId)); 378 379 // This calls DestroyPrerenderForChildRouteIdPair(). 380 RunEvents(); 381 EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled( 382 kDefaultChildId, kDefaultRouteId)); 383 384 // These should all work until the prerendering RenderViewHost is destroyed. 385 EXPECT_TRUE(prerender_tracker()->TryCancel( 386 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 387 EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread( 388 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 389 EXPECT_EQ(FINAL_STATUS_TIMED_OUT, 390 GetCurrentStatus(kDefaultChildId, kDefaultRouteId)); 391 392 test_contents()->Cancel(); 393 EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread( 394 kDefaultChildId, kDefaultRouteId)); 395 396 // This calls RemovePrerenderOnIOThreadTask(). 397 RunEvents(); 398 399 FinalStatus final_status; 400 EXPECT_FALSE(prerender_tracker()->GetFinalStatus( 401 kDefaultChildId, kDefaultRouteId, &final_status)); 402 EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread( 403 kDefaultChildId, kDefaultRouteId)); 404 } 405 406 // Check that a prerendered page cancelled before it reaches the IO thread is 407 // handled correctly. 408 TEST_F(PrerenderTrackerTest, PrerenderTrackerCancelledFast) { 409 test_contents()->Start(); 410 411 // Cancel the prerender. 412 EXPECT_TRUE(prerender_tracker()->TryCancel( 413 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 414 415 EXPECT_FALSE(prerender_tracker()->TryUse(kDefaultChildId, kDefaultRouteId)); 416 EXPECT_TRUE(prerender_tracker()->TryCancel( 417 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_TIMED_OUT)); 418 419 // This calls AddPrerenderOnIOThreadTask() and 420 // DestroyPrerenderForChildRouteIdPair(). 421 RunEvents(); 422 EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled( 423 kDefaultChildId, kDefaultRouteId)); 424 425 EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread( 426 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_TIMED_OUT)); 427 EXPECT_TRUE(prerender_tracker()->TryCancel( 428 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_TIMED_OUT)); 429 EXPECT_EQ(FINAL_STATUS_CANCELLED, GetCurrentStatus( 430 kDefaultChildId, kDefaultRouteId)); 431 432 test_contents()->Cancel(); 433 434 // This calls RemovePrerenderOnIOThreadTask(). 435 RunEvents(); 436 437 FinalStatus final_status; 438 EXPECT_FALSE(prerender_tracker()->GetFinalStatus( 439 kDefaultChildId, kDefaultRouteId, &final_status)); 440 EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread( 441 kDefaultChildId, kDefaultRouteId)); 442 } 443 444 // Check that handling two pages at once works. 445 TEST_F(PrerenderTrackerTest, PrerenderTrackerMultiple) { 446 test_contents()->Start(); 447 448 // This calls AddPrerenderOnIOThreadTask(). 449 RunEvents(); 450 EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread( 451 kDefaultChildId, kDefaultRouteId)); 452 EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread( 453 kDefaultChildId + 1, kDefaultRouteId + 1)); 454 EXPECT_FALSE(prerender_tracker()->TryUse( 455 kDefaultChildId + 1, kDefaultRouteId + 1)); 456 EXPECT_FALSE(prerender_tracker()->TryCancel( 457 kDefaultChildId + 1, kDefaultRouteId + 1, FINAL_STATUS_CANCELLED)); 458 459 // Start second prerender. 460 TestPrerenderContents second_test_contents(prerender_manager(), 461 kDefaultChildId + 1, 462 kDefaultRouteId + 1); 463 464 second_test_contents.Start(); 465 // This calls AddPrerenderOnIOThreadTask(). 466 RunEvents(); 467 468 // Use (kDefaultChildId, kDefaultRouteId). 469 EXPECT_TRUE(prerender_tracker()->TryUse(kDefaultChildId, kDefaultRouteId)); 470 EXPECT_EQ(FINAL_STATUS_USED, GetCurrentStatus( 471 kDefaultChildId, kDefaultRouteId)); 472 EXPECT_EQ(FINAL_STATUS_MAX, 473 GetCurrentStatus(kDefaultChildId + 1, kDefaultRouteId + 1)); 474 475 // Cancel (kDefaultChildId + 1, kDefaultRouteId + 1). 476 EXPECT_TRUE(prerender_tracker()->TryCancelOnIOThread( 477 kDefaultChildId + 1, kDefaultRouteId + 1, FINAL_STATUS_CANCELLED)); 478 479 EXPECT_FALSE(prerender_tracker()->TryCancel( 480 kDefaultChildId, kDefaultRouteId, FINAL_STATUS_CANCELLED)); 481 EXPECT_EQ(FINAL_STATUS_USED, 482 GetCurrentStatus(kDefaultChildId, kDefaultRouteId)); 483 484 EXPECT_FALSE(prerender_tracker()->TryUse( 485 kDefaultChildId + 1, kDefaultRouteId + 1)); 486 EXPECT_TRUE(prerender_tracker()->TryCancel( 487 kDefaultChildId + 1, kDefaultRouteId + 1, FINAL_STATUS_CANCELLED)); 488 EXPECT_EQ(FINAL_STATUS_CANCELLED, 489 GetCurrentStatus(kDefaultChildId + 1, kDefaultRouteId + 1)); 490 491 // This calls DestroyPrerenderForChildRouteIdPair(). 492 RunEvents(); 493 EXPECT_FALSE(prerender_manager()->WasPrerenderCancelled(kDefaultChildId, 494 kDefaultRouteId)); 495 EXPECT_TRUE(prerender_manager()->WasPrerenderCancelled(kDefaultChildId + 1, 496 kDefaultRouteId + 1)); 497 498 test_contents()->Cancel(); 499 second_test_contents.Cancel(); 500 501 // This calls RemovePrerenderOnIOThreadTask(). 502 RunEvents(); 503 504 FinalStatus final_status; 505 EXPECT_FALSE(prerender_tracker()->GetFinalStatus( 506 kDefaultChildId, kDefaultRouteId, &final_status)); 507 EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread( 508 kDefaultChildId, kDefaultRouteId)); 509 510 EXPECT_FALSE(prerender_tracker()->GetFinalStatus( 511 kDefaultChildId + 1, kDefaultRouteId + 1, &final_status)); 512 EXPECT_FALSE(prerender_tracker()->IsPrerenderingOnIOThread( 513 kDefaultChildId + 1, kDefaultRouteId + 1)); 514 } 515 516 // Checks that deferred redirects are throttled and resumed correctly. 517 TEST_F(PrerenderTrackerTest, PrerenderThrottledRedirectResume) { 518 const base::FilePath::CharType kRedirectPath[] = 519 FILE_PATH_LITERAL("prerender/image-deferred.png"); 520 521 test_contents()->Start(); 522 // This calls AddPrerenderOnIOThreadTask(). 523 RunEvents(); 524 EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread( 525 kDefaultChildId, kDefaultRouteId)); 526 527 // Fake a request. 528 net::TestURLRequestContext url_request_context; 529 DeferredRedirectDelegate delegate; 530 net::URLRequest request( 531 content::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kRedirectPath)), 532 net::DEFAULT_PRIORITY, 533 &delegate, 534 &url_request_context); 535 content::ResourceRequestInfo::AllocateForTesting( 536 &request, ResourceType::IMAGE, NULL, 537 kDefaultChildId, kDefaultRouteId, true); 538 539 // Install a prerender throttle. 540 PrerenderResourceThrottle throttle(&request, prerender_tracker()); 541 delegate.SetThrottle(&throttle); 542 543 // Start the request and wait for a redirect. 544 request.Start(); 545 delegate.Run(); 546 EXPECT_TRUE(delegate.was_deferred()); 547 548 // Display the prerendered RenderView and wait for the throttle to 549 // notice. 550 test_contents()->Use(); 551 delegate.Run(); 552 EXPECT_TRUE(delegate.resume_called()); 553 EXPECT_FALSE(delegate.cancel_called()); 554 } 555 556 // Checks that deferred redirects are cancelled on prerender cancel. 557 TEST_F(PrerenderTrackerTest, PrerenderThrottledRedirectCancel) { 558 const base::FilePath::CharType kRedirectPath[] = 559 FILE_PATH_LITERAL("prerender/image-deferred.png"); 560 561 test_contents()->Start(); 562 // This calls AddPrerenderOnIOThreadTask(). 563 RunEvents(); 564 EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread( 565 kDefaultChildId, kDefaultRouteId)); 566 567 // Fake a request. 568 net::TestURLRequestContext url_request_context; 569 DeferredRedirectDelegate delegate; 570 net::URLRequest request( 571 content::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kRedirectPath)), 572 net::DEFAULT_PRIORITY, 573 &delegate, 574 &url_request_context); 575 content::ResourceRequestInfo::AllocateForTesting( 576 &request, ResourceType::IMAGE, NULL, 577 kDefaultChildId, kDefaultRouteId, true); 578 579 // Install a prerender throttle. 580 PrerenderResourceThrottle throttle(&request, prerender_tracker()); 581 delegate.SetThrottle(&throttle); 582 583 // Start the request and wait for a redirect. 584 request.Start(); 585 delegate.Run(); 586 EXPECT_TRUE(delegate.was_deferred()); 587 588 // Display the prerendered RenderView and wait for the throttle to 589 // notice. 590 test_contents()->Cancel(); 591 delegate.Run(); 592 EXPECT_FALSE(delegate.resume_called()); 593 EXPECT_TRUE(delegate.cancel_called()); 594 } 595 596 // Checks that redirects in main frame loads are not deferred. 597 TEST_F(PrerenderTrackerTest, PrerenderThrottledRedirectMainFrame) { 598 const base::FilePath::CharType kRedirectPath[] = 599 FILE_PATH_LITERAL("prerender/image-deferred.png"); 600 601 test_contents()->Start(); 602 // This calls AddPrerenderOnIOThreadTask(). 603 RunEvents(); 604 EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread( 605 kDefaultChildId, kDefaultRouteId)); 606 607 // Fake a request. 608 net::TestURLRequestContext url_request_context; 609 DeferredRedirectDelegate delegate; 610 net::URLRequest request( 611 content::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kRedirectPath)), 612 net::DEFAULT_PRIORITY, 613 &delegate, 614 &url_request_context); 615 content::ResourceRequestInfo::AllocateForTesting( 616 &request, ResourceType::MAIN_FRAME, NULL, 617 kDefaultChildId, kDefaultRouteId, true); 618 619 // Install a prerender throttle. 620 PrerenderResourceThrottle throttle(&request, prerender_tracker()); 621 delegate.SetThrottle(&throttle); 622 623 // Start the request and wait for a redirect. This time, it should 624 // not be deferred. 625 request.Start(); 626 delegate.Run(); 627 EXPECT_FALSE(delegate.was_deferred()); 628 629 // Cleanup work so the prerender is gone. 630 test_contents()->Cancel(); 631 RunEvents(); 632 } 633 634 // Checks that attempting to defer a synchronous request aborts the 635 // prerender. 636 TEST_F(PrerenderTrackerTest, PrerenderThrottledRedirectSyncXHR) { 637 const base::FilePath::CharType kRedirectPath[] = 638 FILE_PATH_LITERAL("prerender/image-deferred.png"); 639 640 test_contents()->Start(); 641 // This calls AddPrerenderOnIOThreadTask(). 642 RunEvents(); 643 EXPECT_TRUE(prerender_tracker()->IsPrerenderingOnIOThread( 644 kDefaultChildId, kDefaultRouteId)); 645 646 // Fake a request. 647 net::TestURLRequestContext url_request_context; 648 DeferredRedirectDelegate delegate; 649 net::URLRequest request( 650 content::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kRedirectPath)), 651 net::DEFAULT_PRIORITY, 652 &delegate, 653 &url_request_context); 654 content::ResourceRequestInfo::AllocateForTesting( 655 &request, ResourceType::XHR, NULL, 656 kDefaultChildId, kDefaultRouteId, false); 657 658 // Install a prerender throttle. 659 PrerenderResourceThrottle throttle(&request, prerender_tracker()); 660 delegate.SetThrottle(&throttle); 661 662 // Start the request and wait for a redirect. 663 request.Start(); 664 delegate.Run(); 665 EXPECT_FALSE(delegate.was_deferred()); 666 667 // We should have cancelled the prerender. 668 EXPECT_EQ(FINAL_STATUS_BAD_DEFERRED_REDIRECT, GetCurrentStatus( 669 kDefaultChildId, kDefaultRouteId)); 670 671 // Cleanup work so the prerender is gone. 672 test_contents()->Cancel(); 673 RunEvents(); 674 } 675 676 } // namespace prerender 677