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/macros.h" |
9 #include "base/message_loop/message_loop_proxy.h" | 10 #include "base/message_loop/message_loop_proxy.h" |
10 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
11 #include "content/browser/browser_thread_impl.h" | 12 #include "content/browser/browser_thread_impl.h" |
12 #include "content/browser/loader/redirect_to_file_resource_handler.h" | 13 #include "content/browser/loader/redirect_to_file_resource_handler.h" |
13 #include "content/browser/loader/resource_loader_delegate.h" | 14 #include "content/browser/loader/resource_loader_delegate.h" |
| 15 #include "content/public/browser/client_certificate_delegate.h" |
14 #include "content/public/browser/resource_request_info.h" | 16 #include "content/public/browser/resource_request_info.h" |
15 #include "content/public/common/resource_response.h" | 17 #include "content/public/common/resource_response.h" |
16 #include "content/public/test/mock_resource_context.h" | 18 #include "content/public/test/mock_resource_context.h" |
| 19 #include "content/public/test/test_browser_context.h" |
17 #include "content/public/test/test_browser_thread_bundle.h" | 20 #include "content/public/test/test_browser_thread_bundle.h" |
| 21 #include "content/public/test/test_renderer_host.h" |
18 #include "content/test/test_content_browser_client.h" | 22 #include "content/test/test_content_browser_client.h" |
| 23 #include "content/test/test_web_contents.h" |
19 #include "ipc/ipc_message.h" | 24 #include "ipc/ipc_message.h" |
20 #include "net/base/io_buffer.h" | 25 #include "net/base/io_buffer.h" |
21 #include "net/base/mock_file_stream.h" | 26 #include "net/base/mock_file_stream.h" |
| 27 #include "net/base/net_errors.h" |
22 #include "net/base/request_priority.h" | 28 #include "net/base/request_priority.h" |
23 #include "net/cert/x509_certificate.h" | 29 #include "net/cert/x509_certificate.h" |
24 #include "net/ssl/client_cert_store.h" | 30 #include "net/ssl/client_cert_store.h" |
25 #include "net/ssl/ssl_cert_request_info.h" | 31 #include "net/ssl/ssl_cert_request_info.h" |
26 #include "net/url_request/url_request.h" | 32 #include "net/url_request/url_request.h" |
| 33 #include "net/url_request/url_request_job_factory.h" |
27 #include "net/url_request/url_request_job_factory_impl.h" | 34 #include "net/url_request/url_request_job_factory_impl.h" |
28 #include "net/url_request/url_request_test_job.h" | 35 #include "net/url_request/url_request_test_job.h" |
29 #include "net/url_request/url_request_test_util.h" | 36 #include "net/url_request/url_request_test_util.h" |
30 #include "storage/browser/blob/shareable_file_reference.h" | 37 #include "storage/browser/blob/shareable_file_reference.h" |
31 #include "testing/gtest/include/gtest/gtest.h" | 38 #include "testing/gtest/include/gtest/gtest.h" |
32 | 39 |
33 using storage::ShareableFileReference; | 40 using storage::ShareableFileReference; |
34 | 41 |
35 namespace content { | 42 namespace content { |
36 namespace { | 43 namespace { |
37 | 44 |
38 // Stub client certificate store that returns a preset list of certificates for | 45 // Stub client certificate store that returns a preset list of certificates for |
39 // each request and records the arguments of the most recent request for later | 46 // each request and records the arguments of the most recent request for later |
40 // inspection. | 47 // inspection. |
41 class ClientCertStoreStub : public net::ClientCertStore { | 48 class ClientCertStoreStub : public net::ClientCertStore { |
42 public: | 49 public: |
43 // Creates a new ClientCertStoreStub that returns |response| on query. It | 50 // Creates a new ClientCertStoreStub that returns |response| on query. It |
44 // saves the number of requests and most recently certificate authorities list | 51 // saves the number of requests and most recently certificate authorities list |
45 // in |requested_authorities| and |request_count|, respectively. The caller is | 52 // in |requested_authorities| and |request_count|, respectively. The caller is |
46 // responsible for ensuring those pointers outlive the ClientCertStoreStub. | 53 // responsible for ensuring those pointers outlive the ClientCertStoreStub. |
47 // | 54 // |
48 // TODO(ppi): Make the stub independent from the internal representation of | 55 // TODO(ppi): Make the stub independent from the internal representation of |
49 // SSLCertRequestInfo. For now it seems that we can neither save the | 56 // SSLCertRequestInfo. For now it seems that we can neither save the |
50 // scoped_refptr<> (since it is never passed to us) nor copy the entire | 57 // scoped_refptr<> (since it is never passed to us) nor copy the entire |
51 // CertificateRequestInfo (since there is no copy constructor). | 58 // CertificateRequestInfo (since there is no copy constructor). |
52 ClientCertStoreStub(const net::CertificateList& response, | 59 ClientCertStoreStub(const net::CertificateList& response, |
53 int* request_count, | 60 int* request_count, |
54 std::vector<std::string>* requested_authorities) | 61 std::vector<std::string>* requested_authorities) |
55 : response_(response), | 62 : response_(response), |
56 async_(false), | |
57 requested_authorities_(requested_authorities), | 63 requested_authorities_(requested_authorities), |
58 request_count_(request_count) { | 64 request_count_(request_count) { |
59 requested_authorities_->clear(); | 65 requested_authorities_->clear(); |
60 *request_count_ = 0; | 66 *request_count_ = 0; |
61 } | 67 } |
62 | 68 |
63 ~ClientCertStoreStub() override {} | 69 ~ClientCertStoreStub() override {} |
64 | 70 |
65 // Configures whether the certificates are returned asynchronously or not. | |
66 void set_async(bool async) { async_ = async; } | |
67 | |
68 // net::ClientCertStore: | 71 // net::ClientCertStore: |
69 void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info, | 72 void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info, |
70 net::CertificateList* selected_certs, | 73 net::CertificateList* selected_certs, |
71 const base::Closure& callback) override { | 74 const base::Closure& callback) override { |
72 *requested_authorities_ = cert_request_info.cert_authorities; | 75 *requested_authorities_ = cert_request_info.cert_authorities; |
73 ++(*request_count_); | 76 ++(*request_count_); |
74 | 77 |
75 *selected_certs = response_; | 78 *selected_certs = response_; |
76 if (async_) { | 79 callback.Run(); |
77 base::MessageLoop::current()->PostTask(FROM_HERE, callback); | |
78 } else { | |
79 callback.Run(); | |
80 } | |
81 } | 80 } |
82 | 81 |
83 private: | 82 private: |
84 const net::CertificateList response_; | 83 const net::CertificateList response_; |
85 bool async_; | |
86 std::vector<std::string>* requested_authorities_; | 84 std::vector<std::string>* requested_authorities_; |
87 int* request_count_; | 85 int* request_count_; |
88 }; | 86 }; |
89 | 87 |
| 88 // Client certificate store which destroys its resource loader before the |
| 89 // asynchronous GetClientCerts callback is called. |
| 90 class LoaderDestroyingCertStore : public net::ClientCertStore { |
| 91 public: |
| 92 // Creates a client certificate store which, when looked up, posts a task to |
| 93 // reset |loader| and then call the callback. The caller is responsible for |
| 94 // ensuring the pointers remain valid until the process is complete. |
| 95 explicit LoaderDestroyingCertStore(scoped_ptr<ResourceLoader>* loader) |
| 96 : loader_(loader) {} |
| 97 |
| 98 // net::ClientCertStore: |
| 99 void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info, |
| 100 net::CertificateList* selected_certs, |
| 101 const base::Closure& callback) override { |
| 102 // Don't destroy |loader_| while it's on the stack. |
| 103 base::MessageLoop::current()->PostTask( |
| 104 FROM_HERE, base::Bind(&LoaderDestroyingCertStore::DoCallback, |
| 105 base::Unretained(loader_), callback)); |
| 106 } |
| 107 |
| 108 private: |
| 109 static void DoCallback(scoped_ptr<ResourceLoader>* loader, |
| 110 const base::Closure& callback) { |
| 111 loader->reset(); |
| 112 callback.Run(); |
| 113 } |
| 114 |
| 115 scoped_ptr<ResourceLoader>* loader_; |
| 116 }; |
| 117 |
| 118 // A mock URLRequestJob which simulates an SSL client auth request. |
| 119 class MockClientCertURLRequestJob : public net::URLRequestTestJob { |
| 120 public: |
| 121 MockClientCertURLRequestJob(net::URLRequest* request, |
| 122 net::NetworkDelegate* network_delegate) |
| 123 : net::URLRequestTestJob(request, network_delegate) {} |
| 124 |
| 125 static std::vector<std::string> test_authorities() { |
| 126 return std::vector<std::string>(1, "dummy"); |
| 127 } |
| 128 |
| 129 // net::URLRequestTestJob: |
| 130 void Start() override { |
| 131 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( |
| 132 new net::SSLCertRequestInfo); |
| 133 cert_request_info->cert_authorities = test_authorities(); |
| 134 base::MessageLoop::current()->PostTask( |
| 135 FROM_HERE, |
| 136 base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested, |
| 137 this, cert_request_info)); |
| 138 } |
| 139 |
| 140 void ContinueWithCertificate(net::X509Certificate* cert) override { |
| 141 net::URLRequestTestJob::Start(); |
| 142 } |
| 143 |
| 144 private: |
| 145 ~MockClientCertURLRequestJob() override {} |
| 146 |
| 147 DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob); |
| 148 }; |
| 149 |
| 150 class MockClientCertJobProtocolHandler |
| 151 : public net::URLRequestJobFactory::ProtocolHandler { |
| 152 public: |
| 153 // URLRequestJobFactory::ProtocolHandler implementation: |
| 154 net::URLRequestJob* MaybeCreateJob( |
| 155 net::URLRequest* request, |
| 156 net::NetworkDelegate* network_delegate) const override { |
| 157 return new MockClientCertURLRequestJob(request, network_delegate); |
| 158 } |
| 159 }; |
| 160 |
90 // Arbitrary read buffer size. | 161 // Arbitrary read buffer size. |
91 const int kReadBufSize = 1024; | 162 const int kReadBufSize = 1024; |
92 | 163 |
93 // Dummy implementation of ResourceHandler, instance of which is needed to | 164 // Dummy implementation of ResourceHandler, instance of which is needed to |
94 // initialize ResourceLoader. | 165 // initialize ResourceLoader. |
95 class ResourceHandlerStub : public ResourceHandler { | 166 class ResourceHandlerStub : public ResourceHandler { |
96 public: | 167 public: |
97 explicit ResourceHandlerStub(net::URLRequest* request) | 168 explicit ResourceHandlerStub(net::URLRequest* request) |
98 : ResourceHandler(request), | 169 : ResourceHandler(request), |
99 read_buffer_(new net::IOBuffer(kReadBufSize)), | 170 read_buffer_(new net::IOBuffer(kReadBufSize)), |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 int total_bytes_downloaded_; | 303 int total_bytes_downloaded_; |
233 }; | 304 }; |
234 | 305 |
235 // Test browser client that captures calls to SelectClientCertificates and | 306 // Test browser client that captures calls to SelectClientCertificates and |
236 // records the arguments of the most recent call for later inspection. | 307 // records the arguments of the most recent call for later inspection. |
237 class SelectCertificateBrowserClient : public TestContentBrowserClient { | 308 class SelectCertificateBrowserClient : public TestContentBrowserClient { |
238 public: | 309 public: |
239 SelectCertificateBrowserClient() : call_count_(0) {} | 310 SelectCertificateBrowserClient() : call_count_(0) {} |
240 | 311 |
241 void SelectClientCertificate( | 312 void SelectClientCertificate( |
242 int render_process_id, | 313 WebContents* web_contents, |
243 int render_view_id, | |
244 net::SSLCertRequestInfo* cert_request_info, | 314 net::SSLCertRequestInfo* cert_request_info, |
245 const base::Callback<void(net::X509Certificate*)>& callback) override { | 315 scoped_ptr<ClientCertificateDelegate> delegate) override { |
246 ++call_count_; | 316 ++call_count_; |
247 passed_certs_ = cert_request_info->client_certs; | 317 passed_certs_ = cert_request_info->client_certs; |
| 318 delegate_ = delegate.Pass(); |
248 } | 319 } |
249 | 320 |
250 int call_count() { | 321 int call_count() { return call_count_; } |
251 return call_count_; | 322 net::CertificateList passed_certs() { return passed_certs_; } |
| 323 |
| 324 void ContinueWithCertificate(net::X509Certificate* cert) { |
| 325 delegate_->ContinueWithCertificate(cert); |
| 326 delegate_.reset(); |
252 } | 327 } |
253 | 328 |
254 net::CertificateList passed_certs() { | 329 void CancelCertificateSelection() { delegate_.reset(); } |
255 return passed_certs_; | |
256 } | |
257 | 330 |
258 private: | 331 private: |
259 net::CertificateList passed_certs_; | 332 net::CertificateList passed_certs_; |
260 int call_count_; | 333 int call_count_; |
| 334 scoped_ptr<ClientCertificateDelegate> delegate_; |
261 }; | 335 }; |
262 | 336 |
263 class ResourceContextStub : public MockResourceContext { | 337 class ResourceContextStub : public MockResourceContext { |
264 public: | 338 public: |
265 explicit ResourceContextStub(net::URLRequestContext* test_request_context) | 339 explicit ResourceContextStub(net::URLRequestContext* test_request_context) |
266 : MockResourceContext(test_request_context) {} | 340 : MockResourceContext(test_request_context) {} |
267 | 341 |
268 scoped_ptr<net::ClientCertStore> CreateClientCertStore() override { | 342 scoped_ptr<net::ClientCertStore> CreateClientCertStore() override { |
269 return dummy_cert_store_.Pass(); | 343 return dummy_cert_store_.Pass(); |
270 } | 344 } |
(...skipping 19 matching lines...) Expand all Loading... |
290 } // namespace | 364 } // namespace |
291 | 365 |
292 class ResourceLoaderTest : public testing::Test, | 366 class ResourceLoaderTest : public testing::Test, |
293 public ResourceLoaderDelegate { | 367 public ResourceLoaderDelegate { |
294 protected: | 368 protected: |
295 ResourceLoaderTest() | 369 ResourceLoaderTest() |
296 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), | 370 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), |
297 resource_context_(&test_url_request_context_), | 371 resource_context_(&test_url_request_context_), |
298 raw_ptr_resource_handler_(NULL), | 372 raw_ptr_resource_handler_(NULL), |
299 raw_ptr_to_request_(NULL) { | 373 raw_ptr_to_request_(NULL) { |
300 job_factory_.SetProtocolHandler( | |
301 "test", net::URLRequestTestJob::CreateProtocolHandler()); | |
302 test_url_request_context_.set_job_factory(&job_factory_); | 374 test_url_request_context_.set_job_factory(&job_factory_); |
303 } | 375 } |
304 | 376 |
305 GURL test_url() const { | 377 GURL test_url() const { return net::URLRequestTestJob::test_url_1(); } |
306 return net::URLRequestTestJob::test_url_1(); | |
307 } | |
308 | 378 |
309 std::string test_data() const { | 379 std::string test_data() const { |
310 return net::URLRequestTestJob::test_data_1(); | 380 return net::URLRequestTestJob::test_data_1(); |
311 } | 381 } |
312 | 382 |
| 383 virtual net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler() { |
| 384 return net::URLRequestTestJob::CreateProtocolHandler(); |
| 385 } |
| 386 |
313 virtual scoped_ptr<ResourceHandler> WrapResourceHandler( | 387 virtual scoped_ptr<ResourceHandler> WrapResourceHandler( |
314 scoped_ptr<ResourceHandlerStub> leaf_handler, | 388 scoped_ptr<ResourceHandlerStub> leaf_handler, |
315 net::URLRequest* request) { | 389 net::URLRequest* request) { |
316 return leaf_handler.Pass(); | 390 return leaf_handler.Pass(); |
317 } | 391 } |
318 | 392 |
319 void SetUp() override { | 393 void SetUp() override { |
320 const int kRenderProcessId = 1; | 394 job_factory_.SetProtocolHandler("test", CreateProtocolHandler()); |
321 const int kRenderViewId = 2; | 395 |
| 396 browser_context_.reset(new TestBrowserContext()); |
| 397 scoped_refptr<SiteInstance> site_instance = |
| 398 SiteInstance::Create(browser_context_.get()); |
| 399 web_contents_.reset( |
| 400 TestWebContents::Create(browser_context_.get(), site_instance.get())); |
| 401 RenderFrameHost* rfh = web_contents_->GetMainFrame(); |
322 | 402 |
323 scoped_ptr<net::URLRequest> request( | 403 scoped_ptr<net::URLRequest> request( |
324 resource_context_.GetRequestContext()->CreateRequest( | 404 resource_context_.GetRequestContext()->CreateRequest( |
325 test_url(), | 405 test_url(), |
326 net::DEFAULT_PRIORITY, | 406 net::DEFAULT_PRIORITY, |
327 NULL /* delegate */, | 407 NULL /* delegate */, |
328 NULL /* cookie_store */)); | 408 NULL /* cookie_store */)); |
329 raw_ptr_to_request_ = request.get(); | 409 raw_ptr_to_request_ = request.get(); |
330 ResourceRequestInfo::AllocateForTesting(request.get(), | 410 ResourceRequestInfo::AllocateForTesting( |
331 RESOURCE_TYPE_MAIN_FRAME, | 411 request.get(), RESOURCE_TYPE_MAIN_FRAME, &resource_context_, |
332 &resource_context_, | 412 rfh->GetProcess()->GetID(), rfh->GetRenderViewHost()->GetRoutingID(), |
333 kRenderProcessId, | 413 rfh->GetRoutingID(), true /* is_main_frame */, |
334 kRenderViewId, | 414 false /* parent_is_main_frame */, true /* allow_download */, |
335 MSG_ROUTING_NONE, | 415 false /* is_async */); |
336 true, // is_main_frame | |
337 false, // parent_is_main_frame | |
338 true, // allow_download | |
339 false); // is_async | |
340 scoped_ptr<ResourceHandlerStub> resource_handler( | 416 scoped_ptr<ResourceHandlerStub> resource_handler( |
341 new ResourceHandlerStub(request.get())); | 417 new ResourceHandlerStub(request.get())); |
342 raw_ptr_resource_handler_ = resource_handler.get(); | 418 raw_ptr_resource_handler_ = resource_handler.get(); |
343 loader_.reset(new ResourceLoader( | 419 loader_.reset(new ResourceLoader( |
344 request.Pass(), | 420 request.Pass(), |
345 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_), | 421 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_), |
346 this)); | 422 this)); |
347 } | 423 } |
348 | 424 |
| 425 void TearDown() override { |
| 426 // Destroy the WebContents and pump the event loop before destroying |
| 427 // |rvh_test_enabler_| and |thread_bundle_|. This lets asynchronous cleanup |
| 428 // tasks complete. |
| 429 web_contents_.reset(); |
| 430 base::RunLoop().RunUntilIdle(); |
| 431 } |
| 432 |
349 // ResourceLoaderDelegate: | 433 // ResourceLoaderDelegate: |
350 ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( | 434 ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( |
351 ResourceLoader* loader, | 435 ResourceLoader* loader, |
352 net::AuthChallengeInfo* auth_info) override { | 436 net::AuthChallengeInfo* auth_info) override { |
353 return NULL; | 437 return NULL; |
354 } | 438 } |
355 bool HandleExternalProtocol(ResourceLoader* loader, | 439 bool HandleExternalProtocol(ResourceLoader* loader, |
356 const GURL& url) override { | 440 const GURL& url) override { |
357 return false; | 441 return false; |
358 } | 442 } |
359 void DidStartRequest(ResourceLoader* loader) override {} | 443 void DidStartRequest(ResourceLoader* loader) override {} |
360 void DidReceiveRedirect(ResourceLoader* loader, | 444 void DidReceiveRedirect(ResourceLoader* loader, |
361 const GURL& new_url) override {} | 445 const GURL& new_url) override {} |
362 void DidReceiveResponse(ResourceLoader* loader) override {} | 446 void DidReceiveResponse(ResourceLoader* loader) override {} |
363 void DidFinishLoading(ResourceLoader* loader) override {} | 447 void DidFinishLoading(ResourceLoader* loader) override {} |
364 | 448 |
365 content::TestBrowserThreadBundle thread_bundle_; | 449 TestBrowserThreadBundle thread_bundle_; |
| 450 RenderViewHostTestEnabler rvh_test_enabler_; |
366 | 451 |
367 net::URLRequestJobFactoryImpl job_factory_; | 452 net::URLRequestJobFactoryImpl job_factory_; |
368 net::TestURLRequestContext test_url_request_context_; | 453 net::TestURLRequestContext test_url_request_context_; |
369 ResourceContextStub resource_context_; | 454 ResourceContextStub resource_context_; |
| 455 scoped_ptr<TestBrowserContext> browser_context_; |
| 456 scoped_ptr<TestWebContents> web_contents_; |
370 | 457 |
371 // The ResourceLoader owns the URLRequest and the ResourceHandler. | 458 // The ResourceLoader owns the URLRequest and the ResourceHandler. |
372 ResourceHandlerStub* raw_ptr_resource_handler_; | 459 ResourceHandlerStub* raw_ptr_resource_handler_; |
373 net::URLRequest* raw_ptr_to_request_; | 460 net::URLRequest* raw_ptr_to_request_; |
374 scoped_ptr<ResourceLoader> loader_; | 461 scoped_ptr<ResourceLoader> loader_; |
375 }; | 462 }; |
376 | 463 |
377 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested() | 464 class ClientCertResourceLoaderTest : public ResourceLoaderTest { |
378 // causes client cert store to be queried for certificates and if the returned | 465 protected: |
379 // certificates are correctly passed to the content browser client for | 466 net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler() override { |
380 // selection. | 467 return new MockClientCertJobProtocolHandler; |
381 TEST_F(ResourceLoaderTest, ClientCertStoreLookup) { | 468 } |
| 469 }; |
| 470 |
| 471 // Tests that client certificates are requested with ClientCertStore lookup. |
| 472 TEST_F(ClientCertResourceLoaderTest, WithStoreLookup) { |
382 // Set up the test client cert store. | 473 // Set up the test client cert store. |
383 int store_request_count; | 474 int store_request_count; |
384 std::vector<std::string> store_requested_authorities; | 475 std::vector<std::string> store_requested_authorities; |
385 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>( | 476 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>( |
386 new net::X509Certificate("test", "test", base::Time(), base::Time()))); | 477 new net::X509Certificate("test", "test", base::Time(), base::Time()))); |
387 scoped_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub( | 478 scoped_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub( |
388 dummy_certs, &store_request_count, &store_requested_authorities)); | 479 dummy_certs, &store_request_count, &store_requested_authorities)); |
389 resource_context_.SetClientCertStore(test_store.Pass()); | 480 resource_context_.SetClientCertStore(test_store.Pass()); |
390 | 481 |
391 // Prepare a dummy certificate request. | |
392 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( | |
393 new net::SSLCertRequestInfo()); | |
394 std::vector<std::string> dummy_authority(1, "dummy"); | |
395 cert_request_info->cert_authorities = dummy_authority; | |
396 | |
397 // Plug in test content browser client. | 482 // Plug in test content browser client. |
398 SelectCertificateBrowserClient test_client; | 483 SelectCertificateBrowserClient test_client; |
399 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client); | 484 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client); |
400 | 485 |
401 // Everything is set up. Trigger the resource loader certificate request event | 486 // Start the request and wait for it to pause. |
402 // and run the message loop. | 487 loader_->StartRequest(); |
403 loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get()); | |
404 base::RunLoop().RunUntilIdle(); | 488 base::RunLoop().RunUntilIdle(); |
405 | 489 |
406 // Restore the original content browser client. | 490 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed()); |
407 SetBrowserClientForTesting(old_client); | |
408 | 491 |
409 // Check if the test store was queried against correct |cert_authorities|. | 492 // Check if the test store was queried against correct |cert_authorities|. |
410 EXPECT_EQ(1, store_request_count); | 493 EXPECT_EQ(1, store_request_count); |
411 EXPECT_EQ(dummy_authority, store_requested_authorities); | 494 EXPECT_EQ(MockClientCertURLRequestJob::test_authorities(), |
| 495 store_requested_authorities); |
412 | 496 |
413 // Check if the retrieved certificates were passed to the content browser | 497 // Check if the retrieved certificates were passed to the content browser |
414 // client. | 498 // client. |
415 EXPECT_EQ(1, test_client.call_count()); | 499 EXPECT_EQ(1, test_client.call_count()); |
416 EXPECT_EQ(dummy_certs, test_client.passed_certs()); | 500 EXPECT_EQ(dummy_certs, test_client.passed_certs()); |
| 501 |
| 502 // Continue the request. |
| 503 test_client.ContinueWithCertificate(dummy_certs[0].get()); |
| 504 base::RunLoop().RunUntilIdle(); |
| 505 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); |
| 506 EXPECT_EQ(net::OK, raw_ptr_resource_handler_->status().error()); |
| 507 |
| 508 // Restore the original content browser client. |
| 509 SetBrowserClientForTesting(old_client); |
417 } | 510 } |
418 | 511 |
419 // Verifies if a call to net::URLRequest::Delegate::OnCertificateRequested() | 512 // Tests that client certificates are requested on a platform with NULL |
420 // on a platform with a NULL client cert store still calls the content browser | 513 // ClientCertStore. |
421 // client for selection. | 514 TEST_F(ClientCertResourceLoaderTest, WithNullStore) { |
422 TEST_F(ResourceLoaderTest, ClientCertStoreNull) { | 515 // Plug in test content browser client. |
423 // Prepare a dummy certificate request. | 516 SelectCertificateBrowserClient test_client; |
424 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( | 517 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client); |
425 new net::SSLCertRequestInfo()); | 518 |
426 std::vector<std::string> dummy_authority(1, "dummy"); | 519 // Start the request and wait for it to pause. |
427 cert_request_info->cert_authorities = dummy_authority; | 520 loader_->StartRequest(); |
| 521 base::RunLoop().RunUntilIdle(); |
| 522 |
| 523 // Check if the SelectClientCertificate was called on the content browser |
| 524 // client. |
| 525 EXPECT_EQ(1, test_client.call_count()); |
| 526 EXPECT_EQ(net::CertificateList(), test_client.passed_certs()); |
| 527 |
| 528 // Continue the request. |
| 529 scoped_refptr<net::X509Certificate> cert( |
| 530 new net::X509Certificate("test", "test", base::Time(), base::Time())); |
| 531 test_client.ContinueWithCertificate(cert.get()); |
| 532 base::RunLoop().RunUntilIdle(); |
| 533 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); |
| 534 EXPECT_EQ(net::OK, raw_ptr_resource_handler_->status().error()); |
| 535 |
| 536 // Restore the original content browser client. |
| 537 SetBrowserClientForTesting(old_client); |
| 538 } |
| 539 |
| 540 // Tests that the ContentBrowserClient may cancel a certificate request. |
| 541 TEST_F(ClientCertResourceLoaderTest, CancelSelection) { |
| 542 // Plug in test content browser client. |
| 543 SelectCertificateBrowserClient test_client; |
| 544 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client); |
| 545 |
| 546 // Start the request and wait for it to pause. |
| 547 loader_->StartRequest(); |
| 548 base::RunLoop().RunUntilIdle(); |
| 549 |
| 550 // Check if the SelectClientCertificate was called on the content browser |
| 551 // client. |
| 552 EXPECT_EQ(1, test_client.call_count()); |
| 553 EXPECT_EQ(net::CertificateList(), test_client.passed_certs()); |
| 554 |
| 555 // Cancel the request. |
| 556 test_client.CancelCertificateSelection(); |
| 557 base::RunLoop().RunUntilIdle(); |
| 558 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); |
| 559 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, |
| 560 raw_ptr_resource_handler_->status().error()); |
| 561 |
| 562 // Restore the original content browser client. |
| 563 SetBrowserClientForTesting(old_client); |
| 564 } |
| 565 |
| 566 // Verifies that requests without WebContents attached abort. |
| 567 TEST_F(ClientCertResourceLoaderTest, NoWebContents) { |
| 568 // Destroy the WebContents before starting the request. |
| 569 web_contents_.reset(); |
428 | 570 |
429 // Plug in test content browser client. | 571 // Plug in test content browser client. |
430 SelectCertificateBrowserClient test_client; | 572 SelectCertificateBrowserClient test_client; |
431 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client); | 573 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client); |
432 | 574 |
433 // Everything is set up. Trigger the resource loader certificate request event | 575 // Start the request and wait for it to pause. |
434 // and run the message loop. | 576 loader_->StartRequest(); |
435 loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get()); | |
436 base::RunLoop().RunUntilIdle(); | 577 base::RunLoop().RunUntilIdle(); |
437 | 578 |
| 579 // Check that SelectClientCertificate wasn't called and the request aborted. |
| 580 EXPECT_EQ(0, test_client.call_count()); |
| 581 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); |
| 582 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, |
| 583 raw_ptr_resource_handler_->status().error()); |
| 584 |
438 // Restore the original content browser client. | 585 // Restore the original content browser client. |
439 SetBrowserClientForTesting(old_client); | 586 SetBrowserClientForTesting(old_client); |
440 | |
441 // Check if the SelectClientCertificate was called on the content browser | |
442 // client. | |
443 EXPECT_EQ(1, test_client.call_count()); | |
444 EXPECT_EQ(net::CertificateList(), test_client.passed_certs()); | |
445 } | 587 } |
446 | 588 |
447 TEST_F(ResourceLoaderTest, ClientCertStoreAsyncCancel) { | 589 // Verifies that ClientCertStore's callback doesn't crash if called after the |
448 // Set up the test client cert store. | 590 // loader is destroyed. |
449 int store_request_count; | 591 TEST_F(ClientCertResourceLoaderTest, StoreAsyncCancel) { |
450 std::vector<std::string> store_requested_authorities; | 592 scoped_ptr<LoaderDestroyingCertStore> test_store( |
451 scoped_ptr<ClientCertStoreStub> test_store( | 593 new LoaderDestroyingCertStore(&loader_)); |
452 new ClientCertStoreStub(net::CertificateList(), &store_request_count, | |
453 &store_requested_authorities)); | |
454 test_store->set_async(true); | |
455 EXPECT_EQ(0, store_request_count); | |
456 resource_context_.SetClientCertStore(test_store.Pass()); | 594 resource_context_.SetClientCertStore(test_store.Pass()); |
457 | 595 |
458 // Prepare a dummy certificate request. | 596 loader_->StartRequest(); |
459 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( | 597 base::RunLoop().RunUntilIdle(); |
460 new net::SSLCertRequestInfo()); | 598 EXPECT_FALSE(loader_); |
461 std::vector<std::string> dummy_authority(1, "dummy"); | |
462 cert_request_info->cert_authorities = dummy_authority; | |
463 | 599 |
464 // Everything is set up. Trigger the resource loader certificate request | 600 // Pump the event loop to ensure nothing asynchronous crashes either. |
465 // event. | |
466 loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get()); | |
467 | |
468 // Check if the test store was queried against correct |cert_authorities|. | |
469 EXPECT_EQ(1, store_request_count); | |
470 EXPECT_EQ(dummy_authority, store_requested_authorities); | |
471 | |
472 // Cancel the request before the store calls the callback. | |
473 loader_.reset(); | |
474 | |
475 // Pump the event loop. There shouldn't be a crash when the callback is run. | |
476 base::RunLoop().RunUntilIdle(); | 601 base::RunLoop().RunUntilIdle(); |
477 } | 602 } |
478 | 603 |
479 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) { | 604 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) { |
480 raw_ptr_resource_handler_->set_defer_request_on_will_start(true); | 605 raw_ptr_resource_handler_->set_defer_request_on_will_start(true); |
481 | 606 |
482 loader_->StartRequest(); | 607 loader_->StartRequest(); |
483 loader_->CancelRequest(true); | 608 loader_->CancelRequest(true); |
484 static_cast<ResourceController*>(loader_.get())->Resume(); | 609 static_cast<ResourceController*>(loader_.get())->Resume(); |
485 } | 610 } |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
760 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents)); | 885 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents)); |
761 EXPECT_EQ(test_data(), contents); | 886 EXPECT_EQ(test_data(), contents); |
762 | 887 |
763 // Release the loader. The file should be gone now. | 888 // Release the loader. The file should be gone now. |
764 ReleaseLoader(); | 889 ReleaseLoader(); |
765 base::RunLoop().RunUntilIdle(); | 890 base::RunLoop().RunUntilIdle(); |
766 EXPECT_FALSE(base::PathExists(temp_path())); | 891 EXPECT_FALSE(base::PathExists(temp_path())); |
767 } | 892 } |
768 | 893 |
769 } // namespace content | 894 } // namespace content |
OLD | NEW |