Home | History | Annotate | Download | only in prerender
      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