OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "content/browser/loader/resource_loader.h" | 5 #include "content/browser/loader/resource_loader.h" |
6 | 6 |
7 #include "base/files/file.h" | 7 #include "base/files/file.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 info->ssl_info.security_bits = kTestSecurityBits; | 205 info->ssl_info.security_bits = kTestSecurityBits; |
206 info->ssl_info.connection_status = kTestConnectionStatus; | 206 info->ssl_info.connection_status = kTestConnectionStatus; |
207 } | 207 } |
208 | 208 |
209 private: | 209 private: |
210 ~MockHTTPSURLRequestJob() override {} | 210 ~MockHTTPSURLRequestJob() override {} |
211 | 211 |
212 DISALLOW_COPY_AND_ASSIGN(MockHTTPSURLRequestJob); | 212 DISALLOW_COPY_AND_ASSIGN(MockHTTPSURLRequestJob); |
213 }; | 213 }; |
214 | 214 |
| 215 const char kRedirectHeaders[] = |
| 216 "HTTP/1.1 302 Found\0" |
| 217 "Location: https://example.test\0" |
| 218 "\0"; |
| 219 |
215 class MockHTTPSJobURLRequestInterceptor : public net::URLRequestInterceptor { | 220 class MockHTTPSJobURLRequestInterceptor : public net::URLRequestInterceptor { |
216 public: | 221 public: |
217 MockHTTPSJobURLRequestInterceptor() {} | 222 MockHTTPSJobURLRequestInterceptor(bool redirect) : redirect_(redirect) {} |
218 ~MockHTTPSJobURLRequestInterceptor() override {} | 223 ~MockHTTPSJobURLRequestInterceptor() override {} |
219 | 224 |
220 // net::URLRequestInterceptor: | 225 // net::URLRequestInterceptor: |
221 net::URLRequestJob* MaybeInterceptRequest( | 226 net::URLRequestJob* MaybeInterceptRequest( |
222 net::URLRequest* request, | 227 net::URLRequest* request, |
223 net::NetworkDelegate* network_delegate) const override { | 228 net::NetworkDelegate* network_delegate) const override { |
224 return new MockHTTPSURLRequestJob(request, network_delegate, | 229 std::string headers = |
225 net::URLRequestTestJob::test_headers(), | 230 redirect_ ? std::string(kRedirectHeaders, arraysize(kRedirectHeaders)) |
| 231 : net::URLRequestTestJob::test_headers(); |
| 232 return new MockHTTPSURLRequestJob(request, network_delegate, headers, |
226 "dummy response", true); | 233 "dummy response", true); |
227 } | 234 } |
| 235 |
| 236 private: |
| 237 bool redirect_; |
228 }; | 238 }; |
229 | 239 |
230 // Arbitrary read buffer size. | 240 // Arbitrary read buffer size. |
231 const int kReadBufSize = 1024; | 241 const int kReadBufSize = 1024; |
232 | 242 |
233 // Dummy implementation of ResourceHandler, instance of which is needed to | 243 // Dummy implementation of ResourceHandler, instance of which is needed to |
234 // initialize ResourceLoader. | 244 // initialize ResourceLoader. |
235 class ResourceHandlerStub : public ResourceHandler { | 245 class ResourceHandlerStub : public ResourceHandler { |
236 public: | 246 public: |
237 explicit ResourceHandlerStub(net::URLRequest* request) | 247 explicit ResourceHandlerStub(net::URLRequest* request) |
238 : ResourceHandler(request), | 248 : ResourceHandler(request), |
239 read_buffer_(new net::IOBuffer(kReadBufSize)), | 249 read_buffer_(new net::IOBuffer(kReadBufSize)), |
240 defer_request_on_will_start_(false), | 250 defer_request_on_will_start_(false), |
241 expect_reads_(true), | 251 expect_reads_(true), |
242 cancel_on_read_completed_(false), | 252 cancel_on_read_completed_(false), |
243 defer_eof_(false), | 253 defer_eof_(false), |
244 received_on_will_read_(false), | 254 received_on_will_read_(false), |
245 received_eof_(false), | 255 received_eof_(false), |
246 received_response_completed_(false), | 256 received_response_completed_(false), |
| 257 received_request_redirected_(false), |
247 total_bytes_downloaded_(0), | 258 total_bytes_downloaded_(0), |
248 upload_position_(0) { | 259 upload_position_(0) {} |
249 } | |
250 | 260 |
251 // If true, defers the resource load in OnWillStart. | 261 // If true, defers the resource load in OnWillStart. |
252 void set_defer_request_on_will_start(bool defer_request_on_will_start) { | 262 void set_defer_request_on_will_start(bool defer_request_on_will_start) { |
253 defer_request_on_will_start_ = defer_request_on_will_start; | 263 defer_request_on_will_start_ = defer_request_on_will_start; |
254 } | 264 } |
255 | 265 |
256 // If true, expect OnWillRead / OnReadCompleted pairs for handling | 266 // If true, expect OnWillRead / OnReadCompleted pairs for handling |
257 // data. Otherwise, expect OnDataDownloaded. | 267 // data. Otherwise, expect OnDataDownloaded. |
258 void set_expect_reads(bool expect_reads) { expect_reads_ = expect_reads; } | 268 void set_expect_reads(bool expect_reads) { expect_reads_ = expect_reads; } |
259 | 269 |
260 // If true, cancel the request in OnReadCompleted by returning false. | 270 // If true, cancel the request in OnReadCompleted by returning false. |
261 void set_cancel_on_read_completed(bool cancel_on_read_completed) { | 271 void set_cancel_on_read_completed(bool cancel_on_read_completed) { |
262 cancel_on_read_completed_ = cancel_on_read_completed; | 272 cancel_on_read_completed_ = cancel_on_read_completed; |
263 } | 273 } |
264 | 274 |
265 // If true, cancel the request in OnReadCompleted by returning false. | 275 // If true, cancel the request in OnReadCompleted by returning false. |
266 void set_defer_eof(bool defer_eof) { defer_eof_ = defer_eof; } | 276 void set_defer_eof(bool defer_eof) { defer_eof_ = defer_eof; } |
267 | 277 |
268 const GURL& start_url() const { return start_url_; } | 278 const GURL& start_url() const { return start_url_; } |
269 ResourceResponse* response() const { return response_.get(); } | 279 ResourceResponse* response() const { return response_.get(); } |
| 280 ResourceResponse* redirect_response() const { |
| 281 return redirect_response_.get(); |
| 282 } |
270 bool received_response_completed() const { | 283 bool received_response_completed() const { |
271 return received_response_completed_; | 284 return received_response_completed_; |
272 } | 285 } |
| 286 bool received_request_redirected() const { |
| 287 return received_request_redirected_; |
| 288 } |
273 const net::URLRequestStatus& status() const { return status_; } | 289 const net::URLRequestStatus& status() const { return status_; } |
274 int total_bytes_downloaded() const { return total_bytes_downloaded_; } | 290 int total_bytes_downloaded() const { return total_bytes_downloaded_; } |
275 | 291 |
276 void Resume() { | 292 void Resume() { |
277 controller()->Resume(); | 293 controller()->Resume(); |
278 } | 294 } |
279 | 295 |
280 // Waits until OnUploadProgress is called and returns the upload position. | 296 // Waits until OnUploadProgress is called and returns the upload position. |
281 uint64 WaitForUploadProgress() { | 297 uint64 WaitForUploadProgress() { |
282 wait_for_progress_loop_.reset(new base::RunLoop()); | 298 wait_for_progress_loop_.reset(new base::RunLoop()); |
283 wait_for_progress_loop_->Run(); | 299 wait_for_progress_loop_->Run(); |
284 wait_for_progress_loop_.reset(); | 300 wait_for_progress_loop_.reset(); |
285 return upload_position_; | 301 return upload_position_; |
286 } | 302 } |
287 | 303 |
288 // ResourceHandler implementation: | 304 // ResourceHandler implementation: |
289 bool OnUploadProgress(uint64 position, uint64 size) override { | 305 bool OnUploadProgress(uint64 position, uint64 size) override { |
290 EXPECT_LE(position, size); | 306 EXPECT_LE(position, size); |
291 EXPECT_GT(position, upload_position_); | 307 EXPECT_GT(position, upload_position_); |
292 upload_position_ = position; | 308 upload_position_ = position; |
293 if (wait_for_progress_loop_) | 309 if (wait_for_progress_loop_) |
294 wait_for_progress_loop_->Quit(); | 310 wait_for_progress_loop_->Quit(); |
295 return true; | 311 return true; |
296 } | 312 } |
297 | 313 |
298 bool OnRequestRedirected(const net::RedirectInfo& redirect_info, | 314 bool OnRequestRedirected(const net::RedirectInfo& redirect_info, |
299 ResourceResponse* response, | 315 ResourceResponse* response, |
300 bool* defer) override { | 316 bool* defer) override { |
301 NOTREACHED(); | 317 redirect_response_ = response; |
| 318 received_request_redirected_ = true; |
302 return true; | 319 return true; |
303 } | 320 } |
304 | 321 |
305 bool OnResponseStarted(ResourceResponse* response, bool* defer) override { | 322 bool OnResponseStarted(ResourceResponse* response, bool* defer) override { |
306 EXPECT_FALSE(response_.get()); | 323 EXPECT_FALSE(response_.get()); |
307 response_ = response; | 324 response_ = response; |
308 return true; | 325 return true; |
309 } | 326 } |
310 | 327 |
311 bool OnWillStart(const GURL& url, bool* defer) override { | 328 bool OnWillStart(const GURL& url, bool* defer) override { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 private: | 388 private: |
372 scoped_refptr<net::IOBuffer> read_buffer_; | 389 scoped_refptr<net::IOBuffer> read_buffer_; |
373 | 390 |
374 bool defer_request_on_will_start_; | 391 bool defer_request_on_will_start_; |
375 bool expect_reads_; | 392 bool expect_reads_; |
376 bool cancel_on_read_completed_; | 393 bool cancel_on_read_completed_; |
377 bool defer_eof_; | 394 bool defer_eof_; |
378 | 395 |
379 GURL start_url_; | 396 GURL start_url_; |
380 scoped_refptr<ResourceResponse> response_; | 397 scoped_refptr<ResourceResponse> response_; |
| 398 scoped_refptr<ResourceResponse> redirect_response_; |
381 bool received_on_will_read_; | 399 bool received_on_will_read_; |
382 bool received_eof_; | 400 bool received_eof_; |
383 bool received_response_completed_; | 401 bool received_response_completed_; |
| 402 bool received_request_redirected_; |
384 net::URLRequestStatus status_; | 403 net::URLRequestStatus status_; |
385 int total_bytes_downloaded_; | 404 int total_bytes_downloaded_; |
386 scoped_ptr<base::RunLoop> wait_for_progress_loop_; | 405 scoped_ptr<base::RunLoop> wait_for_progress_loop_; |
387 uint64 upload_position_; | 406 uint64 upload_position_; |
388 }; | 407 }; |
389 | 408 |
390 // Test browser client that captures calls to SelectClientCertificates and | 409 // Test browser client that captures calls to SelectClientCertificates and |
391 // records the arguments of the most recent call for later inspection. | 410 // records the arguments of the most recent call for later inspection. |
392 class SelectCertificateBrowserClient : public TestContentBrowserClient { | 411 class SelectCertificateBrowserClient : public TestContentBrowserClient { |
393 public: | 412 public: |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 scoped_ptr<ResourceLoader> loader_; | 613 scoped_ptr<ResourceLoader> loader_; |
595 }; | 614 }; |
596 | 615 |
597 class ClientCertResourceLoaderTest : public ResourceLoaderTest { | 616 class ClientCertResourceLoaderTest : public ResourceLoaderTest { |
598 protected: | 617 protected: |
599 net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler() override { | 618 net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler() override { |
600 return new MockClientCertJobProtocolHandler; | 619 return new MockClientCertJobProtocolHandler; |
601 } | 620 } |
602 }; | 621 }; |
603 | 622 |
604 // A ResourceLoaderTest that intercepts https://example.test URLs and | 623 // A ResourceLoaderTest that intercepts https://example.test and |
605 // sets SSL info on the responses. | 624 // https://example-redirect.test URLs and sets SSL info on the |
| 625 // responses. The latter serves a Location: header in the response. |
606 class HTTPSSecurityInfoResourceLoaderTest : public ResourceLoaderTest { | 626 class HTTPSSecurityInfoResourceLoaderTest : public ResourceLoaderTest { |
607 public: | 627 public: |
608 HTTPSSecurityInfoResourceLoaderTest() | 628 HTTPSSecurityInfoResourceLoaderTest() |
609 : ResourceLoaderTest(), test_https_url_("https://example.test") {} | 629 : ResourceLoaderTest(), |
| 630 test_https_url_("https://example.test"), |
| 631 test_https_redirect_url_("https://example-redirect.test") {} |
610 | 632 |
611 ~HTTPSSecurityInfoResourceLoaderTest() override {} | 633 ~HTTPSSecurityInfoResourceLoaderTest() override {} |
612 | 634 |
613 const GURL& test_https_url() { return test_https_url_; } | 635 const GURL& test_https_url() const { return test_https_url_; } |
| 636 const GURL& test_https_redirect_url() const { |
| 637 return test_https_redirect_url_; |
| 638 } |
614 | 639 |
615 protected: | 640 protected: |
616 void SetUp() override { | 641 void SetUp() override { |
617 ResourceLoaderTest::SetUp(); | 642 ResourceLoaderTest::SetUp(); |
| 643 net::URLRequestFilter::GetInstance()->ClearHandlers(); |
618 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( | 644 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( |
619 "https", "example.test", scoped_ptr<net::URLRequestInterceptor>( | 645 "https", "example.test", |
620 new MockHTTPSJobURLRequestInterceptor)); | 646 scoped_ptr<net::URLRequestInterceptor>( |
| 647 new MockHTTPSJobURLRequestInterceptor(false /* redirect */))); |
| 648 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor( |
| 649 "https", "example-redirect.test", |
| 650 scoped_ptr<net::URLRequestInterceptor>( |
| 651 new MockHTTPSJobURLRequestInterceptor(true /* redirect */))); |
621 } | 652 } |
622 | 653 |
623 private: | 654 private: |
624 const GURL test_https_url_; | 655 const GURL test_https_url_; |
| 656 const GURL test_https_redirect_url_; |
625 }; | 657 }; |
626 | 658 |
627 // Tests that client certificates are requested with ClientCertStore lookup. | 659 // Tests that client certificates are requested with ClientCertStore lookup. |
628 TEST_F(ClientCertResourceLoaderTest, WithStoreLookup) { | 660 TEST_F(ClientCertResourceLoaderTest, WithStoreLookup) { |
629 // Set up the test client cert store. | 661 // Set up the test client cert store. |
630 int store_request_count; | 662 int store_request_count; |
631 std::vector<std::string> store_requested_authorities; | 663 std::vector<std::string> store_requested_authorities; |
632 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>( | 664 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>( |
633 new net::X509Certificate("test", "test", base::Time(), base::Time()))); | 665 new net::X509Certificate("test", "test", base::Time(), base::Time()))); |
634 scoped_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub( | 666 scoped_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub( |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1110 scoped_refptr<net::X509Certificate> cert; | 1142 scoped_refptr<net::X509Certificate> cert; |
1111 ASSERT_TRUE( | 1143 ASSERT_TRUE( |
1112 CertStore::GetInstance()->RetrieveCert(deserialized.cert_id, &cert)); | 1144 CertStore::GetInstance()->RetrieveCert(deserialized.cert_id, &cert)); |
1113 EXPECT_TRUE(cert->Equals(GetTestCert().get())); | 1145 EXPECT_TRUE(cert->Equals(GetTestCert().get())); |
1114 | 1146 |
1115 EXPECT_EQ(kTestCertError, deserialized.cert_status); | 1147 EXPECT_EQ(kTestCertError, deserialized.cert_status); |
1116 EXPECT_EQ(kTestConnectionStatus, deserialized.connection_status); | 1148 EXPECT_EQ(kTestConnectionStatus, deserialized.connection_status); |
1117 EXPECT_EQ(kTestSecurityBits, deserialized.security_bits); | 1149 EXPECT_EQ(kTestSecurityBits, deserialized.security_bits); |
1118 } | 1150 } |
1119 | 1151 |
| 1152 // Test that an HTTPS redirect response has the expected security info |
| 1153 // attached to it. |
| 1154 TEST_F(HTTPSSecurityInfoResourceLoaderTest, |
| 1155 SecurityInfoOnHTTPSRedirectResource) { |
| 1156 // Start the request and wait for it to finish. |
| 1157 scoped_ptr<net::URLRequest> request( |
| 1158 resource_context_.GetRequestContext()->CreateRequest( |
| 1159 test_https_redirect_url(), net::DEFAULT_PRIORITY, |
| 1160 nullptr /* delegate */)); |
| 1161 SetUpResourceLoader(request.Pass()); |
| 1162 |
| 1163 // Send the request and wait until it completes. |
| 1164 loader_->StartRequest(); |
| 1165 base::RunLoop().RunUntilIdle(); |
| 1166 ASSERT_EQ(net::URLRequestStatus::SUCCESS, |
| 1167 raw_ptr_to_request_->status().status()); |
| 1168 ASSERT_TRUE(raw_ptr_resource_handler_->received_response_completed()); |
| 1169 ASSERT_TRUE(raw_ptr_resource_handler_->received_request_redirected()); |
| 1170 |
| 1171 ResourceResponse* redirect_response = |
| 1172 raw_ptr_resource_handler_->redirect_response(); |
| 1173 ASSERT_TRUE(redirect_response); |
| 1174 |
| 1175 // Deserialize the security info from the redirect response and check |
| 1176 // that it is as expected. |
| 1177 SSLStatus deserialized; |
| 1178 ASSERT_TRUE(DeserializeSecurityInfo(redirect_response->head.security_info, |
| 1179 &deserialized)); |
| 1180 |
| 1181 // Expect a BROKEN security style because the cert status has errors. |
| 1182 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN, |
| 1183 deserialized.security_style); |
| 1184 scoped_refptr<net::X509Certificate> cert; |
| 1185 ASSERT_TRUE( |
| 1186 CertStore::GetInstance()->RetrieveCert(deserialized.cert_id, &cert)); |
| 1187 EXPECT_TRUE(cert->Equals(GetTestCert().get())); |
| 1188 |
| 1189 EXPECT_EQ(kTestCertError, deserialized.cert_status); |
| 1190 EXPECT_EQ(kTestConnectionStatus, deserialized.connection_status); |
| 1191 EXPECT_EQ(kTestSecurityBits, deserialized.security_bits); |
| 1192 } |
| 1193 |
1120 } // namespace content | 1194 } // namespace content |
OLD | NEW |