| 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 |