• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
MockResourceHandler()17   MockResourceHandler() {}
18 
OnUploadProgress(int request_id,uint64 position,uint64 size)19   virtual bool OnUploadProgress(int request_id,
20                                 uint64 position,
21                                 uint64 size) {
22     return true;
23   }
24 
OnRequestRedirected(int request_id,const GURL & url,ResourceResponse * response,bool * defer)25   virtual bool OnRequestRedirected(int request_id, const GURL& url,
26                                    ResourceResponse* response,
27                                    bool* defer) {
28     *defer = false;
29     return true;
30   }
31 
OnResponseStarted(int request_id,ResourceResponse * response)32   virtual bool OnResponseStarted(int request_id,
33                                  ResourceResponse* response) {
34     return true;
35   }
36 
OnWillStart(int request_id,const GURL & url,bool * defer)37   virtual bool OnWillStart(int request_id, const GURL& url, bool* defer) {
38     *defer = false;
39     return true;
40   }
41 
OnWillRead(int request_id,net::IOBuffer ** buf,int * buf_size,int min_size)42   virtual bool OnWillRead(int request_id,
43                           net::IOBuffer** buf,
44                           int* buf_size,
45                           int min_size) {
46     return true;
47   }
48 
OnReadCompleted(int request_id,int * bytes_read)49   virtual bool OnReadCompleted(int request_id, int* bytes_read) {
50     return true;
51   }
52 
OnResponseCompleted(int request_id,const net::URLRequestStatus & status,const std::string & security_info)53   virtual bool OnResponseCompleted(int request_id,
54                                    const net::URLRequestStatus& status,
55                                    const std::string& security_info) {
56     return true;
57   }
58 
OnRequestClosed()59   virtual void OnRequestClosed() {
60   }
61 
OnDataDownloaded(int request_id,int bytes_downloaded)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.
CreateResponseHeaders(const char * newline_separated_headers)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:
PrerenderResourceHandlerTest()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 
~PrerenderResourceHandlerTest()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 
SetLastHandledURL(const std::pair<int,int> & child_route_id_pair,const GURL & url,const std::vector<GURL> & alias_urls,const GURL & referrer,bool make_pending)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
StartPrerendering(const std::string & mime_type,const char * headers)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_.
ContainsAliasURL(const GURL & url)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 
TEST_F(PrerenderResourceHandlerTest,NoOp)162 TEST_F(PrerenderResourceHandlerTest, NoOp) {
163 }
164 
165 // Tests that a valid HTML resource will correctly get diverted
166 // to the PrerenderManager.
TEST_F(PrerenderResourceHandlerTest,Prerender)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.
TEST_F(PrerenderResourceHandlerTest,PrerenderRedirect)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.
TEST_F(PrerenderResourceHandlerTest,PrerenderHttps)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 
TEST_F(PrerenderResourceHandlerTest,PrerenderRedirectToHttps)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