Home | History | Annotate | Download | only in prerender
      1 // Copyright (c) 2011 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 "chrome/browser/prerender/prerender_resource_handler.h"
      6 #include "content/common/resource_response.h"
      7 #include "net/http/http_response_headers.h"
      8 #include "net/url_request/url_request_test_util.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 
     11 namespace prerender {
     12 
     13 namespace {
     14 
     15 class MockResourceHandler : public ResourceHandler {
     16  public:
     17   MockResourceHandler() {}
     18 
     19   virtual bool OnUploadProgress(int request_id,
     20                                 uint64 position,
     21                                 uint64 size) {
     22     return true;
     23   }
     24 
     25   virtual bool OnRequestRedirected(int request_id, const GURL& url,
     26                                    ResourceResponse* response,
     27                                    bool* defer) {
     28     *defer = false;
     29     return true;
     30   }
     31 
     32   virtual bool OnResponseStarted(int request_id,
     33                                  ResourceResponse* response) {
     34     return true;
     35   }
     36 
     37   virtual bool OnWillStart(int request_id, const GURL& url, bool* defer) {
     38     *defer = false;
     39     return true;
     40   }
     41 
     42   virtual bool OnWillRead(int request_id,
     43                           net::IOBuffer** buf,
     44                           int* buf_size,
     45                           int min_size) {
     46     return true;
     47   }
     48 
     49   virtual bool OnReadCompleted(int request_id, int* bytes_read) {
     50     return true;
     51   }
     52 
     53   virtual bool OnResponseCompleted(int request_id,
     54                                    const net::URLRequestStatus& status,
     55                                    const std::string& security_info) {
     56     return true;
     57   }
     58 
     59   virtual void OnRequestClosed() {
     60   }
     61 
     62   virtual void OnDataDownloaded(int request_id, int bytes_downloaded) {}
     63 };
     64 
     65 // HttpResponseHeaders expects the raw input for it's constructor
     66 // to be a NUL ('\0') separated string for each line. This is a little
     67 // difficult to do for string literals, so this helper function accepts
     68 // newline-separated string literals and does the substitution. The
     69 // returned object is expected to be deleted by the caller.
     70 net::HttpResponseHeaders* CreateResponseHeaders(
     71     const char* newline_separated_headers) {
     72   std::string headers(newline_separated_headers);
     73   std::string::iterator i = headers.begin();
     74   std::string::iterator end = headers.end();
     75   while (i != end) {
     76     if (*i == '\n')
     77       *i = '\0';
     78     ++i;
     79   }
     80   return new net::HttpResponseHeaders(headers);
     81 }
     82 
     83 }  // namespace
     84 
     85 class PrerenderResourceHandlerTest : public testing::Test {
     86  protected:
     87   PrerenderResourceHandlerTest()
     88       : loop_(MessageLoop::TYPE_IO),
     89         ui_thread_(BrowserThread::UI, &loop_),
     90         io_thread_(BrowserThread::IO, &loop_),
     91         test_url_request_(GURL("http://www.referrer.com"),
     92                           &test_url_request_delegate_),
     93         ALLOW_THIS_IN_INITIALIZER_LIST(
     94             pre_handler_(new PrerenderResourceHandler(
     95                 test_url_request_,
     96                 new MockResourceHandler(),
     97                 NewCallback(
     98                     this,
     99                     &PrerenderResourceHandlerTest::SetLastHandledURL)))),
    100         default_url_("http://www.prerender.com") {
    101   }
    102 
    103   virtual ~PrerenderResourceHandlerTest() {
    104     // When a ResourceHandler's reference count drops to 0, it is not
    105     // deleted immediately. Instead, a task is posted to the IO thread's
    106     // message loop to delete it.
    107     // So, drop the reference count to 0 and run the message loop once
    108     // to ensure that all resources are cleaned up before the test exits.
    109     pre_handler_ = NULL;
    110     loop_.RunAllPending();
    111   }
    112 
    113   void SetLastHandledURL(const std::pair<int, int>& child_route_id_pair,
    114                          const GURL& url, const std::vector<GURL>& alias_urls,
    115                          const GURL& referrer, bool make_pending) {
    116     last_handled_url_ = url;
    117     alias_urls_ = alias_urls;
    118     referrer_ = referrer;
    119   }
    120 
    121   // Common logic shared by many of the tests
    122   void StartPrerendering(const std::string& mime_type,
    123                          const char* headers) {
    124     int request_id = 1;
    125     bool defer = false;
    126     EXPECT_TRUE(pre_handler_->OnWillStart(request_id, default_url_, &defer));
    127     EXPECT_FALSE(defer);
    128     scoped_refptr<ResourceResponse> response(new ResourceResponse);
    129     response->response_head.mime_type = mime_type;
    130     response->response_head.headers = CreateResponseHeaders(headers);
    131     EXPECT_TRUE(last_handled_url_.is_empty());
    132 
    133     // Start the response. If it is able to prerender, a task will
    134     // be posted to the UI thread and |SetLastHandledURL| will be called.
    135     EXPECT_TRUE(pre_handler_->OnResponseStarted(request_id, response));
    136     loop_.RunAllPending();
    137   }
    138 
    139   // Test whether a given URL is part of alias_urls_.
    140   bool ContainsAliasURL(const GURL& url) {
    141     return std::find(alias_urls_.begin(), alias_urls_.end(), url)
    142         != alias_urls_.end();
    143   }
    144 
    145   // Must be initialized before |test_url_request_|.
    146   MessageLoop loop_;
    147   BrowserThread ui_thread_;
    148   BrowserThread io_thread_;
    149 
    150   TestDelegate test_url_request_delegate_;
    151   TestURLRequest test_url_request_;
    152 
    153   scoped_refptr<PrerenderResourceHandler> pre_handler_;
    154   GURL last_handled_url_;
    155   GURL default_url_;
    156   std::vector<GURL> alias_urls_;
    157   GURL referrer_;
    158 };
    159 
    160 namespace {
    161 
    162 TEST_F(PrerenderResourceHandlerTest, NoOp) {
    163 }
    164 
    165 // Tests that a valid HTML resource will correctly get diverted
    166 // to the PrerenderManager.
    167 TEST_F(PrerenderResourceHandlerTest, Prerender) {
    168   StartPrerendering("text/html",
    169                     "HTTP/1.1 200 OK\n");
    170   EXPECT_EQ(default_url_, last_handled_url_);
    171 }
    172 
    173 static const int kRequestId = 1;
    174 
    175 // Tests that the final request in a redirect chain will
    176 // get diverted to the PrerenderManager.
    177 TEST_F(PrerenderResourceHandlerTest, PrerenderRedirect) {
    178   GURL url_redirect("http://www.redirect.com");
    179   bool defer = false;
    180   EXPECT_TRUE(pre_handler_->OnWillStart(kRequestId, default_url_, &defer));
    181   EXPECT_FALSE(defer);
    182   EXPECT_TRUE(pre_handler_->OnRequestRedirected(kRequestId,
    183                                                 url_redirect,
    184                                                 NULL,
    185                                                 &defer));
    186   EXPECT_FALSE(defer);
    187   scoped_refptr<ResourceResponse> response(new ResourceResponse);
    188   response->response_head.mime_type = "text/html";
    189   response->response_head.headers = CreateResponseHeaders(
    190       "HTTP/1.1 200 OK\n");
    191   EXPECT_TRUE(pre_handler_->OnResponseStarted(kRequestId, response));
    192   EXPECT_TRUE(last_handled_url_.is_empty());
    193   loop_.RunAllPending();
    194   EXPECT_EQ(url_redirect, last_handled_url_);
    195   EXPECT_EQ(true, ContainsAliasURL(url_redirect));
    196   EXPECT_EQ(true, ContainsAliasURL(default_url_));
    197   EXPECT_EQ(2, static_cast<int>(alias_urls_.size()));
    198 }
    199 
    200 // Tests that https requests will not be prerendered.
    201 TEST_F(PrerenderResourceHandlerTest, PrerenderHttps) {
    202   GURL url_https("https://www.google.com");
    203   bool defer = false;
    204   EXPECT_FALSE(pre_handler_->OnWillStart(kRequestId, url_https, &defer));
    205   EXPECT_FALSE(defer);
    206 }
    207 
    208 TEST_F(PrerenderResourceHandlerTest, PrerenderRedirectToHttps) {
    209   bool defer = false;
    210   EXPECT_TRUE(pre_handler_->OnWillStart(kRequestId, default_url_, &defer));
    211   EXPECT_FALSE(defer);
    212   GURL url_https("https://www.google.com");
    213   EXPECT_FALSE(pre_handler_->OnRequestRedirected(kRequestId,
    214                                                  url_https,
    215                                                  NULL,
    216                                                  &defer));
    217   EXPECT_FALSE(defer);
    218 }
    219 
    220 }  // namespace
    221 
    222 }  // namespace prerender
    223