| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/prerender/prerender_resource_handler.h" | 5 #include "chrome/browser/prerender/prerender_resource_handler.h" |
| 6 #include "chrome/common/resource_response.h" | 6 #include "chrome/common/resource_response.h" |
| 7 #include "net/http/http_response_headers.h" | 7 #include "net/http/http_response_headers.h" |
| 8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
| 9 | 9 |
| 10 namespace { | 10 namespace { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 const std::string& security_info) { | 52 const std::string& security_info) { |
| 53 return true; | 53 return true; |
| 54 } | 54 } |
| 55 | 55 |
| 56 virtual void OnRequestClosed() { | 56 virtual void OnRequestClosed() { |
| 57 } | 57 } |
| 58 | 58 |
| 59 virtual void OnDataDownloaded(int request_id, int bytes_downloaded) {} | 59 virtual void OnDataDownloaded(int request_id, int bytes_downloaded) {} |
| 60 }; | 60 }; |
| 61 | 61 |
| 62 base::Time FixedGetCurrentTime() { | |
| 63 return base::Time(); | |
| 64 } | |
| 65 | |
| 66 // HttpResponseHeaders expects the raw input for it's constructor | 62 // HttpResponseHeaders expects the raw input for it's constructor |
| 67 // to be a NUL ('\0') separated string for each line. This is a little | 63 // to be a NUL ('\0') separated string for each line. This is a little |
| 68 // difficult to do for string literals, so this helper function accepts | 64 // difficult to do for string literals, so this helper function accepts |
| 69 // newline-separated string literals and does the substitution. The | 65 // newline-separated string literals and does the substitution. The |
| 70 // returned object is expected to be deleted by the caller. | 66 // returned object is expected to be deleted by the caller. |
| 71 net::HttpResponseHeaders* CreateResponseHeaders( | 67 net::HttpResponseHeaders* CreateResponseHeaders( |
| 72 const char* newline_separated_headers) { | 68 const char* newline_separated_headers) { |
| 73 std::string headers(newline_separated_headers); | 69 std::string headers(newline_separated_headers); |
| 74 std::string::iterator i = headers.begin(); | 70 std::string::iterator i = headers.begin(); |
| 75 std::string::iterator end = headers.end(); | 71 std::string::iterator end = headers.end(); |
| 76 while (i != end) { | 72 while (i != end) { |
| 77 if (*i == '\n') | 73 if (*i == '\n') |
| 78 *i = '\0'; | 74 *i = '\0'; |
| 79 ++i; | 75 ++i; |
| 80 } | 76 } |
| 81 return new net::HttpResponseHeaders(headers); | 77 return new net::HttpResponseHeaders(headers); |
| 82 } | 78 } |
| 83 | 79 |
| 84 } // namespace | 80 } // namespace |
| 85 | 81 |
| 86 class PrerenderResourceHandlerTest : public testing::Test { | 82 class PrerenderResourceHandlerTest : public testing::Test { |
| 87 protected: | 83 protected: |
| 88 PrerenderResourceHandlerTest() | 84 PrerenderResourceHandlerTest() |
| 89 : prerender_duration_(base::TimeDelta::FromSeconds(10)), | 85 : ALLOW_THIS_IN_INITIALIZER_LIST( |
| 90 ALLOW_THIS_IN_INITIALIZER_LIST( | |
| 91 pre_handler_(new PrerenderResourceHandler( | 86 pre_handler_(new PrerenderResourceHandler( |
| 92 new MockResourceHandler(), | 87 new MockResourceHandler(), |
| 93 NewCallback( | 88 NewCallback( |
| 94 this, | 89 this, |
| 95 &PrerenderResourceHandlerTest::SetLastHandledURL)))), | 90 &PrerenderResourceHandlerTest::SetLastHandledURL)))), |
| 96 ui_thread_(BrowserThread::UI, &loop_), | 91 ui_thread_(BrowserThread::UI, &loop_), |
| 97 io_thread_(BrowserThread::IO, &loop_), | 92 io_thread_(BrowserThread::IO, &loop_), |
| 98 default_url_("http://www.prerender.com") { | 93 default_url_("http://www.prerender.com") { |
| 99 pre_handler_->set_prerender_duration(prerender_duration_); | |
| 100 pre_handler_->set_get_current_time_function(&FixedGetCurrentTime); | |
| 101 } | 94 } |
| 102 | 95 |
| 103 virtual ~PrerenderResourceHandlerTest() { | 96 virtual ~PrerenderResourceHandlerTest() { |
| 104 // When a ResourceHandler's reference count drops to 0, it is not | 97 // 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 | 98 // deleted immediately. Instead, a task is posted to the IO thread's |
| 106 // message loop to delete it. | 99 // message loop to delete it. |
| 107 // So, drop the reference count to 0 and run the message loop once | 100 // 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. | 101 // to ensure that all resources are cleaned up before the test exits. |
| 109 pre_handler_ = NULL; | 102 pre_handler_ = NULL; |
| 110 loop_.RunAllPending(); | 103 loop_.RunAllPending(); |
| 111 } | 104 } |
| 112 | 105 |
| 113 void SetLastHandledURL(const GURL& url, const std::vector<GURL>& alias_urls) { | 106 void SetLastHandledURL(const GURL& url, const std::vector<GURL>& alias_urls) { |
| 114 last_handled_url_ = url; | 107 last_handled_url_ = url; |
| 115 alias_urls_ = alias_urls; | 108 alias_urls_ = alias_urls; |
| 116 } | 109 } |
| 117 | 110 |
| 118 // Common logic shared by many of the tests | 111 // Common logic shared by many of the tests |
| 119 void StartPrerendering(const std::string& mime_type, | 112 void StartPrerendering(const std::string& mime_type, |
| 120 const char* headers) { | 113 const char* headers) { |
| 121 int request_id = 1; | 114 int request_id = 1; |
| 122 bool defer = false; | 115 bool defer = false; |
| 123 EXPECT_TRUE(pre_handler_->OnWillStart(request_id, default_url_, &defer)); | 116 EXPECT_TRUE(pre_handler_->OnWillStart(request_id, default_url_, &defer)); |
| 124 EXPECT_FALSE(defer); | 117 EXPECT_FALSE(defer); |
| 125 scoped_refptr<ResourceResponse> response(new ResourceResponse); | 118 scoped_refptr<ResourceResponse> response(new ResourceResponse); |
| 126 response->response_head.request_time = FixedGetCurrentTime(); | |
| 127 response->response_head.response_time = FixedGetCurrentTime(); | |
| 128 response->response_head.mime_type = mime_type; | 119 response->response_head.mime_type = mime_type; |
| 129 response->response_head.headers = CreateResponseHeaders(headers); | 120 response->response_head.headers = CreateResponseHeaders(headers); |
| 130 EXPECT_TRUE(last_handled_url_.is_empty()); | 121 EXPECT_TRUE(last_handled_url_.is_empty()); |
| 131 | 122 |
| 132 // Start the response. If it is able to prerender, a task will | 123 // Start the response. If it is able to prerender, a task will |
| 133 // be posted to the UI thread and |SetLastHandledURL| will be called. | 124 // be posted to the UI thread and |SetLastHandledURL| will be called. |
| 134 EXPECT_TRUE(pre_handler_->OnResponseStarted(request_id, response)); | 125 EXPECT_TRUE(pre_handler_->OnResponseStarted(request_id, response)); |
| 135 loop_.RunAllPending(); | 126 loop_.RunAllPending(); |
| 136 } | 127 } |
| 137 | 128 |
| 138 // Test whether a given URL is part of alias_urls_. | 129 // Test whether a given URL is part of alias_urls_. |
| 139 bool ContainsAliasURL(const GURL& url) { | 130 bool ContainsAliasURL(const GURL& url) { |
| 140 return std::find(alias_urls_.begin(), alias_urls_.end(), url) | 131 return std::find(alias_urls_.begin(), alias_urls_.end(), url) |
| 141 != alias_urls_.end(); | 132 != alias_urls_.end(); |
| 142 } | 133 } |
| 143 | 134 |
| 144 base::TimeDelta prerender_duration_; | |
| 145 scoped_refptr<PrerenderResourceHandler> pre_handler_; | 135 scoped_refptr<PrerenderResourceHandler> pre_handler_; |
| 146 MessageLoop loop_; | 136 MessageLoop loop_; |
| 147 BrowserThread ui_thread_; | 137 BrowserThread ui_thread_; |
| 148 BrowserThread io_thread_; | 138 BrowserThread io_thread_; |
| 149 GURL last_handled_url_; | 139 GURL last_handled_url_; |
| 150 GURL default_url_; | 140 GURL default_url_; |
| 151 std::vector<GURL> alias_urls_; | 141 std::vector<GURL> alias_urls_; |
| 152 }; | 142 }; |
| 153 | 143 |
| 154 namespace { | 144 namespace { |
| 155 | 145 |
| 156 TEST_F(PrerenderResourceHandlerTest, NoOp) { | 146 TEST_F(PrerenderResourceHandlerTest, NoOp) { |
| 157 } | 147 } |
| 158 | 148 |
| 159 // Tests that a valid HTML resource will correctly get diverted | 149 // Tests that a valid HTML resource will correctly get diverted |
| 160 // to the PrerenderManager. | 150 // to the PrerenderManager. |
| 161 TEST_F(PrerenderResourceHandlerTest, Prerender) { | 151 TEST_F(PrerenderResourceHandlerTest, Prerender) { |
| 162 StartPrerendering("text/html", | 152 StartPrerendering("text/html", |
| 163 "HTTP/1.1 200 OK\n" | 153 "HTTP/1.1 200 OK\n"); |
| 164 "cache-control: max-age=86400\n"); | |
| 165 EXPECT_EQ(default_url_, last_handled_url_); | 154 EXPECT_EQ(default_url_, last_handled_url_); |
| 166 } | 155 } |
| 167 | 156 |
| 168 // Tests that a no-cache HTML resource will not get diverted | |
| 169 // to the PrerenderManager. | |
| 170 TEST_F(PrerenderResourceHandlerTest, PrerenderNoCache) { | |
| 171 StartPrerendering("text/html", | |
| 172 "HTTP/1.1 200 OK\n" | |
| 173 "cache-control: no-cache\n"); | |
| 174 EXPECT_TRUE(last_handled_url_.is_empty()); | |
| 175 } | |
| 176 | |
| 177 // Tests that a cacheable HTML resource which needs to be revalidated | |
| 178 // shortly will not be prerendered. | |
| 179 TEST_F(PrerenderResourceHandlerTest, PrerenderShortMaxAge) { | |
| 180 StartPrerendering("text/html", | |
| 181 "HTTP/1.1 200 OK\n" | |
| 182 "cache-control: max-age=5\n"); | |
| 183 EXPECT_TRUE(last_handled_url_.is_empty()); | |
| 184 } | |
| 185 | |
| 186 // Tests that a resource with the wrong MIME type (a GIF in this example) | |
| 187 // will not be diverted to the PrerenderManager. | |
| 188 TEST_F(PrerenderResourceHandlerTest, PrerenderWrongMimeType) { | |
| 189 StartPrerendering("image/gif", | |
| 190 "HTTP/1.1 200 OK\n" | |
| 191 "cache-control: max-age=86400\n"); | |
| 192 EXPECT_TRUE(last_handled_url_.is_empty()); | |
| 193 } | |
| 194 | |
| 195 // Tests that a resource with a non-200 response will not be diverted | |
| 196 // to the PrerenderManager | |
| 197 TEST_F(PrerenderResourceHandlerTest, PrerenderBadResponseCode) { | |
| 198 StartPrerendering("text/html", | |
| 199 "HTTP/1.1 403 Forbidden\n" | |
| 200 "cache-control: max-age=86400\n"); | |
| 201 EXPECT_TRUE(last_handled_url_.is_empty()); | |
| 202 } | |
| 203 | |
| 204 // Tests that the final request in a redirect chain will | 157 // Tests that the final request in a redirect chain will |
| 205 // get diverted to the PrerenderManager. | 158 // get diverted to the PrerenderManager. |
| 206 TEST_F(PrerenderResourceHandlerTest, PrerenderRedirect) { | 159 TEST_F(PrerenderResourceHandlerTest, PrerenderRedirect) { |
| 207 int request_id = 1; | 160 int request_id = 1; |
| 208 GURL url_redirect("http://www.redirect.com"); | 161 GURL url_redirect("http://www.redirect.com"); |
| 209 bool defer = false; | 162 bool defer = false; |
| 210 EXPECT_TRUE(pre_handler_->OnWillStart(request_id, default_url_, &defer)); | 163 EXPECT_TRUE(pre_handler_->OnWillStart(request_id, default_url_, &defer)); |
| 211 EXPECT_FALSE(defer); | 164 EXPECT_FALSE(defer); |
| 212 EXPECT_TRUE(pre_handler_->OnRequestRedirected(request_id, | 165 EXPECT_TRUE(pre_handler_->OnRequestRedirected(request_id, |
| 213 url_redirect, | 166 url_redirect, |
| 214 NULL, | 167 NULL, |
| 215 &defer)); | 168 &defer)); |
| 216 EXPECT_FALSE(defer); | 169 EXPECT_FALSE(defer); |
| 217 scoped_refptr<ResourceResponse> response(new ResourceResponse); | 170 scoped_refptr<ResourceResponse> response(new ResourceResponse); |
| 218 response->response_head.mime_type = "text/html"; | 171 response->response_head.mime_type = "text/html"; |
| 219 response->response_head.request_time = FixedGetCurrentTime(); | |
| 220 response->response_head.response_time = FixedGetCurrentTime(); | |
| 221 response->response_head.headers = CreateResponseHeaders( | 172 response->response_head.headers = CreateResponseHeaders( |
| 222 "HTTP/1.1 200 OK\n" | 173 "HTTP/1.1 200 OK\n"); |
| 223 "cache-control: max-age=86400\n"); | |
| 224 EXPECT_TRUE(pre_handler_->OnResponseStarted(request_id, response)); | 174 EXPECT_TRUE(pre_handler_->OnResponseStarted(request_id, response)); |
| 225 EXPECT_TRUE(last_handled_url_.is_empty()); | 175 EXPECT_TRUE(last_handled_url_.is_empty()); |
| 226 loop_.RunAllPending(); | 176 loop_.RunAllPending(); |
| 227 EXPECT_EQ(url_redirect, last_handled_url_); | 177 EXPECT_EQ(url_redirect, last_handled_url_); |
| 228 EXPECT_EQ(true, ContainsAliasURL(url_redirect)); | 178 EXPECT_EQ(true, ContainsAliasURL(url_redirect)); |
| 229 EXPECT_EQ(true, ContainsAliasURL(default_url_)); | 179 EXPECT_EQ(true, ContainsAliasURL(default_url_)); |
| 230 EXPECT_EQ(2, static_cast<int>(alias_urls_.size())); | 180 EXPECT_EQ(2, static_cast<int>(alias_urls_.size())); |
| 231 } | 181 } |
| 232 | 182 |
| 233 } | 183 } |
| OLD | NEW |