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
3 // found in the LICENSE file.
5 #include "content/browser/loader/resource_loader.h"
7 #include "base/files/file.h"
8 #include "base/files/file_util.h"
9 #include "base/location.h"
10 #include "base/macros.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/run_loop.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "content/browser/browser_thread_impl.h"
16 #include "content/browser/loader/redirect_to_file_resource_handler.h"
17 #include "content/browser/loader/resource_loader_delegate.h"
18 #include "content/common/ssl_status_serialization.h"
19 #include "content/public/browser/cert_store.h"
20 #include "content/public/browser/client_certificate_delegate.h"
21 #include "content/public/browser/resource_request_info.h"
22 #include "content/public/common/content_paths.h"
23 #include "content/public/common/resource_response.h"
24 #include "content/public/test/mock_resource_context.h"
25 #include "content/public/test/test_browser_context.h"
26 #include "content/public/test/test_browser_thread_bundle.h"
27 #include "content/public/test/test_renderer_host.h"
28 #include "content/test/test_content_browser_client.h"
29 #include "content/test/test_web_contents.h"
30 #include "ipc/ipc_message.h"
31 #include "net/base/chunked_upload_data_stream.h"
32 #include "net/base/io_buffer.h"
33 #include "net/base/mock_file_stream.h"
34 #include "net/base/net_errors.h"
35 #include "net/base/request_priority.h"
36 #include "net/base/test_data_directory.h"
37 #include "net/base/upload_bytes_element_reader.h"
38 #include "net/cert/x509_certificate.h"
39 #include "net/ssl/client_cert_store.h"
40 #include "net/ssl/ssl_cert_request_info.h"
41 #include "net/test/cert_test_util.h"
42 #include "net/test/embedded_test_server/embedded_test_server.h"
43 #include "net/url_request/url_request.h"
44 #include "net/url_request/url_request_filter.h"
45 #include "net/url_request/url_request_interceptor.h"
46 #include "net/url_request/url_request_job_factory.h"
47 #include "net/url_request/url_request_job_factory_impl.h"
48 #include "net/url_request/url_request_test_job.h"
49 #include "net/url_request/url_request_test_util.h"
50 #include "storage/browser/blob/shareable_file_reference.h"
51 #include "testing/gtest/include/gtest/gtest.h"
53 using storage::ShareableFileReference
;
58 // Stub client certificate store that returns a preset list of certificates for
59 // each request and records the arguments of the most recent request for later
61 class ClientCertStoreStub
: public net::ClientCertStore
{
63 // Creates a new ClientCertStoreStub that returns |response| on query. It
64 // saves the number of requests and most recently certificate authorities list
65 // in |requested_authorities| and |request_count|, respectively. The caller is
66 // responsible for ensuring those pointers outlive the ClientCertStoreStub.
68 // TODO(ppi): Make the stub independent from the internal representation of
69 // SSLCertRequestInfo. For now it seems that we can neither save the
70 // scoped_refptr<> (since it is never passed to us) nor copy the entire
71 // CertificateRequestInfo (since there is no copy constructor).
72 ClientCertStoreStub(const net::CertificateList
& response
,
74 std::vector
<std::string
>* requested_authorities
)
75 : response_(response
),
76 requested_authorities_(requested_authorities
),
77 request_count_(request_count
) {
78 requested_authorities_
->clear();
82 ~ClientCertStoreStub() override
{}
84 // net::ClientCertStore:
85 void GetClientCerts(const net::SSLCertRequestInfo
& cert_request_info
,
86 net::CertificateList
* selected_certs
,
87 const base::Closure
& callback
) override
{
88 *requested_authorities_
= cert_request_info
.cert_authorities
;
91 *selected_certs
= response_
;
96 const net::CertificateList response_
;
97 std::vector
<std::string
>* requested_authorities_
;
101 // Client certificate store which destroys its resource loader before the
102 // asynchronous GetClientCerts callback is called.
103 class LoaderDestroyingCertStore
: public net::ClientCertStore
{
105 // Creates a client certificate store which, when looked up, posts a task to
106 // reset |loader| and then call the callback. The caller is responsible for
107 // ensuring the pointers remain valid until the process is complete.
108 LoaderDestroyingCertStore(scoped_ptr
<ResourceLoader
>* loader
,
109 const base::Closure
& on_loader_deleted_callback
)
111 on_loader_deleted_callback_(on_loader_deleted_callback
) {
114 // net::ClientCertStore:
115 void GetClientCerts(const net::SSLCertRequestInfo
& cert_request_info
,
116 net::CertificateList
* selected_certs
,
117 const base::Closure
& cert_selected_callback
) override
{
118 // Don't destroy |loader_| while it's on the stack.
119 base::ThreadTaskRunnerHandle::Get()->PostTask(
120 FROM_HERE
, base::Bind(&LoaderDestroyingCertStore::DoCallback
,
121 base::Unretained(loader_
),
122 cert_selected_callback
,
123 on_loader_deleted_callback_
));
127 // This needs to be static because |loader| owns the
128 // LoaderDestroyingCertStore (ClientCertStores are actually handles, and not
129 // global cert stores).
130 static void DoCallback(scoped_ptr
<ResourceLoader
>* loader
,
131 const base::Closure
& cert_selected_callback
,
132 const base::Closure
& on_loader_deleted_callback
) {
134 cert_selected_callback
.Run();
135 on_loader_deleted_callback
.Run();
138 scoped_ptr
<ResourceLoader
>* loader_
;
139 base::Closure on_loader_deleted_callback_
;
141 DISALLOW_COPY_AND_ASSIGN(LoaderDestroyingCertStore
);
144 // A mock URLRequestJob which simulates an SSL client auth request.
145 class MockClientCertURLRequestJob
: public net::URLRequestTestJob
{
147 MockClientCertURLRequestJob(net::URLRequest
* request
,
148 net::NetworkDelegate
* network_delegate
)
149 : net::URLRequestTestJob(request
, network_delegate
) {}
151 static std::vector
<std::string
> test_authorities() {
152 return std::vector
<std::string
>(1, "dummy");
155 // net::URLRequestTestJob:
156 void Start() override
{
157 scoped_refptr
<net::SSLCertRequestInfo
> cert_request_info(
158 new net::SSLCertRequestInfo
);
159 cert_request_info
->cert_authorities
= test_authorities();
160 base::ThreadTaskRunnerHandle::Get()->PostTask(
162 base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested
,
163 this, cert_request_info
));
166 void ContinueWithCertificate(net::X509Certificate
* cert
) override
{
167 net::URLRequestTestJob::Start();
171 ~MockClientCertURLRequestJob() override
{}
173 DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob
);
176 class MockClientCertJobProtocolHandler
177 : public net::URLRequestJobFactory::ProtocolHandler
{
179 // URLRequestJobFactory::ProtocolHandler implementation:
180 net::URLRequestJob
* MaybeCreateJob(
181 net::URLRequest
* request
,
182 net::NetworkDelegate
* network_delegate
) const override
{
183 return new MockClientCertURLRequestJob(request
, network_delegate
);
187 // Set up dummy values to use in test HTTPS requests.
189 scoped_refptr
<net::X509Certificate
> GetTestCert() {
190 return net::ImportCertFromFile(net::GetTestCertsDirectory(),
191 "test_mail_google_com.pem");
194 const net::CertStatus kTestCertError
= net::CERT_STATUS_DATE_INVALID
;
195 const int kTestSecurityBits
= 256;
196 // SSL3 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
197 const int kTestConnectionStatus
= 0x300039;
199 // A mock URLRequestJob which simulates an HTTPS request.
200 class MockHTTPSURLRequestJob
: public net::URLRequestTestJob
{
202 MockHTTPSURLRequestJob(net::URLRequest
* request
,
203 net::NetworkDelegate
* network_delegate
,
204 const std::string
& response_headers
,
205 const std::string
& response_data
,
207 : net::URLRequestTestJob(request
,
213 // net::URLRequestTestJob:
214 void GetResponseInfo(net::HttpResponseInfo
* info
) override
{
215 // Get the original response info, but override the SSL info.
216 net::URLRequestJob::GetResponseInfo(info
);
217 info
->ssl_info
.cert
= GetTestCert();
218 info
->ssl_info
.cert_status
= kTestCertError
;
219 info
->ssl_info
.security_bits
= kTestSecurityBits
;
220 info
->ssl_info
.connection_status
= kTestConnectionStatus
;
224 ~MockHTTPSURLRequestJob() override
{}
226 DISALLOW_COPY_AND_ASSIGN(MockHTTPSURLRequestJob
);
229 const char kRedirectHeaders
[] =
230 "HTTP/1.1 302 Found\0"
231 "Location: https://example.test\0"
234 class MockHTTPSJobURLRequestInterceptor
: public net::URLRequestInterceptor
{
236 MockHTTPSJobURLRequestInterceptor(bool redirect
) : redirect_(redirect
) {}
237 ~MockHTTPSJobURLRequestInterceptor() override
{}
239 // net::URLRequestInterceptor:
240 net::URLRequestJob
* MaybeInterceptRequest(
241 net::URLRequest
* request
,
242 net::NetworkDelegate
* network_delegate
) const override
{
243 std::string headers
=
244 redirect_
? std::string(kRedirectHeaders
, arraysize(kRedirectHeaders
))
245 : net::URLRequestTestJob::test_headers();
246 return new MockHTTPSURLRequestJob(request
, network_delegate
, headers
,
247 "dummy response", true);
254 // Arbitrary read buffer size.
255 const int kReadBufSize
= 1024;
257 // Dummy implementation of ResourceHandler, instance of which is needed to
258 // initialize ResourceLoader.
259 class ResourceHandlerStub
: public ResourceHandler
{
261 explicit ResourceHandlerStub(net::URLRequest
* request
)
262 : ResourceHandler(request
),
263 read_buffer_(new net::IOBuffer(kReadBufSize
)),
264 defer_request_on_will_start_(false),
266 cancel_on_read_completed_(false),
268 received_on_will_read_(false),
269 received_eof_(false),
270 received_response_completed_(false),
271 received_request_redirected_(false),
272 total_bytes_downloaded_(0) {}
274 // If true, defers the resource load in OnWillStart.
275 void set_defer_request_on_will_start(bool defer_request_on_will_start
) {
276 defer_request_on_will_start_
= defer_request_on_will_start
;
279 // If true, expect OnWillRead / OnReadCompleted pairs for handling
280 // data. Otherwise, expect OnDataDownloaded.
281 void set_expect_reads(bool expect_reads
) { expect_reads_
= expect_reads
; }
283 // If true, cancel the request in OnReadCompleted by returning false.
284 void set_cancel_on_read_completed(bool cancel_on_read_completed
) {
285 cancel_on_read_completed_
= cancel_on_read_completed
;
288 // If true, cancel the request in OnReadCompleted by returning false.
289 void set_defer_eof(bool defer_eof
) { defer_eof_
= defer_eof
; }
291 const GURL
& start_url() const { return start_url_
; }
292 ResourceResponse
* response() const { return response_
.get(); }
293 ResourceResponse
* redirect_response() const {
294 return redirect_response_
.get();
296 bool received_response_completed() const {
297 return received_response_completed_
;
299 bool received_request_redirected() const {
300 return received_request_redirected_
;
302 const net::URLRequestStatus
& status() const { return status_
; }
303 int total_bytes_downloaded() const { return total_bytes_downloaded_
; }
306 controller()->Resume();
309 bool OnRequestRedirected(const net::RedirectInfo
& redirect_info
,
310 ResourceResponse
* response
,
311 bool* defer
) override
{
312 redirect_response_
= response
;
313 received_request_redirected_
= true;
317 bool OnResponseStarted(ResourceResponse
* response
, bool* defer
) override
{
318 EXPECT_FALSE(response_
.get());
319 response_
= response
;
323 bool OnWillStart(const GURL
& url
, bool* defer
) override
{
324 EXPECT_TRUE(start_url_
.is_empty());
326 if (defer_request_on_will_start_
) {
328 deferred_run_loop_
.Quit();
333 bool OnBeforeNetworkStart(const GURL
& url
, bool* defer
) override
{
337 bool OnWillRead(scoped_refptr
<net::IOBuffer
>* buf
,
339 int min_size
) override
{
340 EXPECT_TRUE(expect_reads_
);
341 EXPECT_FALSE(received_on_will_read_
);
342 EXPECT_FALSE(received_eof_
);
343 EXPECT_FALSE(received_response_completed_
);
346 *buf_size
= kReadBufSize
;
347 received_on_will_read_
= true;
351 bool OnReadCompleted(int bytes_read
, bool* defer
) override
{
352 EXPECT_TRUE(received_on_will_read_
);
353 EXPECT_TRUE(expect_reads_
);
354 EXPECT_FALSE(received_response_completed_
);
356 if (bytes_read
== 0) {
357 received_eof_
= true;
361 deferred_run_loop_
.Quit();
365 // Need another OnWillRead() call before seeing an OnReadCompleted().
366 received_on_will_read_
= false;
368 return !cancel_on_read_completed_
;
371 void OnResponseCompleted(const net::URLRequestStatus
& status
,
372 const std::string
& security_info
,
373 bool* defer
) override
{
374 EXPECT_FALSE(received_response_completed_
);
375 if (status
.is_success() && expect_reads_
)
376 EXPECT_TRUE(received_eof_
);
378 received_response_completed_
= true;
380 response_completed_run_loop_
.Quit();
383 void OnDataDownloaded(int bytes_downloaded
) override
{
384 EXPECT_FALSE(expect_reads_
);
385 total_bytes_downloaded_
+= bytes_downloaded
;
388 // Waits for the the first deferred step to run, if there is one.
389 void WaitForDeferredStep() {
390 DCHECK(defer_request_on_will_start_
|| defer_eof_
);
391 deferred_run_loop_
.Run();
394 // Waits until the response has completed.
395 void WaitForResponseComplete() {
396 response_completed_run_loop_
.Run();
397 EXPECT_TRUE(received_response_completed_
);
401 scoped_refptr
<net::IOBuffer
> read_buffer_
;
403 bool defer_request_on_will_start_
;
405 bool cancel_on_read_completed_
;
409 scoped_refptr
<ResourceResponse
> response_
;
410 scoped_refptr
<ResourceResponse
> redirect_response_
;
411 bool received_on_will_read_
;
413 bool received_response_completed_
;
414 bool received_request_redirected_
;
415 net::URLRequestStatus status_
;
416 int total_bytes_downloaded_
;
417 base::RunLoop deferred_run_loop_
;
418 base::RunLoop response_completed_run_loop_
;
419 scoped_ptr
<base::RunLoop
> wait_for_progress_run_loop_
;
422 // Test browser client that captures calls to SelectClientCertificates and
423 // records the arguments of the most recent call for later inspection.
424 class SelectCertificateBrowserClient
: public TestContentBrowserClient
{
426 SelectCertificateBrowserClient() : call_count_(0) {}
428 // Waits until the first call to SelectClientCertificate.
429 void WaitForSelectCertificate() {
430 select_certificate_run_loop_
.Run();
431 // Process any pending messages - just so tests can check if
432 // SelectClientCertificate was called more than once.
433 base::RunLoop().RunUntilIdle();
436 void SelectClientCertificate(
437 WebContents
* web_contents
,
438 net::SSLCertRequestInfo
* cert_request_info
,
439 scoped_ptr
<ClientCertificateDelegate
> delegate
) override
{
440 EXPECT_FALSE(delegate_
.get());
443 passed_certs_
= cert_request_info
->client_certs
;
444 delegate_
= delegate
.Pass();
445 select_certificate_run_loop_
.Quit();
448 int call_count() { return call_count_
; }
449 net::CertificateList
passed_certs() { return passed_certs_
; }
451 void ContinueWithCertificate(net::X509Certificate
* cert
) {
452 delegate_
->ContinueWithCertificate(cert
);
456 void CancelCertificateSelection() { delegate_
.reset(); }
459 net::CertificateList passed_certs_
;
461 scoped_ptr
<ClientCertificateDelegate
> delegate_
;
463 base::RunLoop select_certificate_run_loop_
;
465 DISALLOW_COPY_AND_ASSIGN(SelectCertificateBrowserClient
);
468 class ResourceContextStub
: public MockResourceContext
{
470 explicit ResourceContextStub(net::URLRequestContext
* test_request_context
)
471 : MockResourceContext(test_request_context
) {}
473 scoped_ptr
<net::ClientCertStore
> CreateClientCertStore() override
{
474 return dummy_cert_store_
.Pass();
477 void SetClientCertStore(scoped_ptr
<net::ClientCertStore
> store
) {
478 dummy_cert_store_
= store
.Pass();
482 scoped_ptr
<net::ClientCertStore
> dummy_cert_store_
;
485 // Wraps a ChunkedUploadDataStream to behave as non-chunked to enable upload
486 // progress reporting.
487 class NonChunkedUploadDataStream
: public net::UploadDataStream
{
489 explicit NonChunkedUploadDataStream(uint64 size
)
490 : net::UploadDataStream(false, 0), stream_(0), size_(size
) {}
492 void AppendData(const char* data
) {
493 stream_
.AppendData(data
, strlen(data
), false);
497 int InitInternal() override
{
499 stream_
.Init(base::Bind(&NonChunkedUploadDataStream::OnInitCompleted
,
500 base::Unretained(this)));
504 int ReadInternal(net::IOBuffer
* buf
, int buf_len
) override
{
505 return stream_
.Read(buf
, buf_len
,
506 base::Bind(&NonChunkedUploadDataStream::OnReadCompleted
,
507 base::Unretained(this)));
510 void ResetInternal() override
{ stream_
.Reset(); }
512 net::ChunkedUploadDataStream stream_
;
515 DISALLOW_COPY_AND_ASSIGN(NonChunkedUploadDataStream
);
518 // Fails to create a temporary file with the given error.
519 void CreateTemporaryError(
520 base::File::Error error
,
521 const CreateTemporaryFileStreamCallback
& callback
) {
522 base::ThreadTaskRunnerHandle::Get()->PostTask(
524 base::Bind(callback
, error
, base::Passed(scoped_ptr
<net::FileStream
>()),
525 scoped_refptr
<ShareableFileReference
>()));
530 class ResourceLoaderTest
: public testing::Test
,
531 public ResourceLoaderDelegate
{
534 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
535 resource_context_(&test_url_request_context_
),
536 raw_ptr_resource_handler_(NULL
),
537 raw_ptr_to_request_(NULL
) {
538 test_url_request_context_
.set_job_factory(&job_factory_
);
541 GURL
test_url() const { return net::URLRequestTestJob::test_url_1(); }
543 std::string
test_data() const {
544 return net::URLRequestTestJob::test_data_1();
547 virtual scoped_ptr
<net::URLRequestJobFactory::ProtocolHandler
>
548 CreateProtocolHandler() {
549 return net::URLRequestTestJob::CreateProtocolHandler();
552 virtual scoped_ptr
<ResourceHandler
> WrapResourceHandler(
553 scoped_ptr
<ResourceHandlerStub
> leaf_handler
,
554 net::URLRequest
* request
) {
555 return leaf_handler
.Pass();
558 // Replaces loader_ with a new one for |request|.
559 void SetUpResourceLoader(scoped_ptr
<net::URLRequest
> request
) {
560 raw_ptr_to_request_
= request
.get();
562 RenderFrameHost
* rfh
= web_contents_
->GetMainFrame();
563 ResourceRequestInfo::AllocateForTesting(
564 request
.get(), RESOURCE_TYPE_MAIN_FRAME
, &resource_context_
,
565 rfh
->GetProcess()->GetID(), rfh
->GetRenderViewHost()->GetRoutingID(),
566 rfh
->GetRoutingID(), true /* is_main_frame */,
567 false /* parent_is_main_frame */, true /* allow_download */,
568 false /* is_async */);
569 scoped_ptr
<ResourceHandlerStub
> resource_handler(
570 new ResourceHandlerStub(request
.get()));
571 raw_ptr_resource_handler_
= resource_handler
.get();
572 loader_
.reset(new ResourceLoader(
574 WrapResourceHandler(resource_handler
.Pass(), raw_ptr_to_request_
),
578 void SetUp() override
{
579 job_factory_
.SetProtocolHandler("test", CreateProtocolHandler());
581 browser_context_
.reset(new TestBrowserContext());
582 scoped_refptr
<SiteInstance
> site_instance
=
583 SiteInstance::Create(browser_context_
.get());
585 TestWebContents::Create(browser_context_
.get(), site_instance
.get()));
587 scoped_ptr
<net::URLRequest
> request(
588 resource_context_
.GetRequestContext()->CreateRequest(
590 net::DEFAULT_PRIORITY
,
591 nullptr /* delegate */));
592 SetUpResourceLoader(request
.Pass());
595 void TearDown() override
{
596 // Destroy the WebContents and pump the event loop before destroying
597 // |rvh_test_enabler_| and |thread_bundle_|. This lets asynchronous cleanup
599 web_contents_
.reset();
600 base::RunLoop().RunUntilIdle();
603 // ResourceLoaderDelegate:
604 ResourceDispatcherHostLoginDelegate
* CreateLoginDelegate(
605 ResourceLoader
* loader
,
606 net::AuthChallengeInfo
* auth_info
) override
{
609 bool HandleExternalProtocol(ResourceLoader
* loader
,
610 const GURL
& url
) override
{
613 void DidStartRequest(ResourceLoader
* loader
) override
{}
614 void DidReceiveRedirect(ResourceLoader
* loader
,
615 const GURL
& new_url
) override
{}
616 void DidReceiveResponse(ResourceLoader
* loader
) override
{}
617 void DidFinishLoading(ResourceLoader
* loader
) override
{}
619 TestBrowserThreadBundle thread_bundle_
;
620 RenderViewHostTestEnabler rvh_test_enabler_
;
622 net::URLRequestJobFactoryImpl job_factory_
;
623 net::TestURLRequestContext test_url_request_context_
;
624 ResourceContextStub resource_context_
;
625 scoped_ptr
<TestBrowserContext
> browser_context_
;
626 scoped_ptr
<TestWebContents
> web_contents_
;
628 // The ResourceLoader owns the URLRequest and the ResourceHandler.
629 ResourceHandlerStub
* raw_ptr_resource_handler_
;
630 net::URLRequest
* raw_ptr_to_request_
;
631 scoped_ptr
<ResourceLoader
> loader_
;
634 class ClientCertResourceLoaderTest
: public ResourceLoaderTest
{
636 scoped_ptr
<net::URLRequestJobFactory::ProtocolHandler
> CreateProtocolHandler()
638 return make_scoped_ptr(new MockClientCertJobProtocolHandler
);
642 // A ResourceLoaderTest that intercepts https://example.test and
643 // https://example-redirect.test URLs and sets SSL info on the
644 // responses. The latter serves a Location: header in the response.
645 class HTTPSSecurityInfoResourceLoaderTest
: public ResourceLoaderTest
{
647 HTTPSSecurityInfoResourceLoaderTest()
648 : ResourceLoaderTest(),
649 test_https_url_("https://example.test"),
650 test_https_redirect_url_("https://example-redirect.test") {}
652 ~HTTPSSecurityInfoResourceLoaderTest() override
{}
654 const GURL
& test_https_url() const { return test_https_url_
; }
655 const GURL
& test_https_redirect_url() const {
656 return test_https_redirect_url_
;
660 void SetUp() override
{
661 ResourceLoaderTest::SetUp();
662 net::URLRequestFilter::GetInstance()->ClearHandlers();
663 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
664 "https", "example.test",
665 scoped_ptr
<net::URLRequestInterceptor
>(
666 new MockHTTPSJobURLRequestInterceptor(false /* redirect */)));
667 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
668 "https", "example-redirect.test",
669 scoped_ptr
<net::URLRequestInterceptor
>(
670 new MockHTTPSJobURLRequestInterceptor(true /* redirect */)));
674 const GURL test_https_url_
;
675 const GURL test_https_redirect_url_
;
678 // Tests that client certificates are requested with ClientCertStore lookup.
679 TEST_F(ClientCertResourceLoaderTest
, WithStoreLookup
) {
680 // Set up the test client cert store.
681 int store_request_count
;
682 std::vector
<std::string
> store_requested_authorities
;
683 net::CertificateList
dummy_certs(1, scoped_refptr
<net::X509Certificate
>(
684 new net::X509Certificate("test", "test", base::Time(), base::Time())));
685 scoped_ptr
<ClientCertStoreStub
> test_store(new ClientCertStoreStub(
686 dummy_certs
, &store_request_count
, &store_requested_authorities
));
687 resource_context_
.SetClientCertStore(test_store
.Pass());
689 // Plug in test content browser client.
690 SelectCertificateBrowserClient test_client
;
691 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&test_client
);
693 // Start the request and wait for it to pause.
694 loader_
->StartRequest();
695 test_client
.WaitForSelectCertificate();
697 EXPECT_FALSE(raw_ptr_resource_handler_
->received_response_completed());
699 // Check if the test store was queried against correct |cert_authorities|.
700 EXPECT_EQ(1, store_request_count
);
701 EXPECT_EQ(MockClientCertURLRequestJob::test_authorities(),
702 store_requested_authorities
);
704 // Check if the retrieved certificates were passed to the content browser
706 EXPECT_EQ(1, test_client
.call_count());
707 EXPECT_EQ(dummy_certs
, test_client
.passed_certs());
709 // Continue the request.
710 test_client
.ContinueWithCertificate(dummy_certs
[0].get());
711 raw_ptr_resource_handler_
->WaitForResponseComplete();
712 EXPECT_EQ(net::OK
, raw_ptr_resource_handler_
->status().error());
714 // Restore the original content browser client.
715 SetBrowserClientForTesting(old_client
);
718 // Tests that client certificates are requested on a platform with NULL
720 TEST_F(ClientCertResourceLoaderTest
, WithNullStore
) {
721 // Plug in test content browser client.
722 SelectCertificateBrowserClient test_client
;
723 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&test_client
);
725 // Start the request and wait for it to pause.
726 loader_
->StartRequest();
727 test_client
.WaitForSelectCertificate();
729 // Check if the SelectClientCertificate was called on the content browser
731 EXPECT_EQ(1, test_client
.call_count());
732 EXPECT_EQ(net::CertificateList(), test_client
.passed_certs());
734 // Continue the request.
735 scoped_refptr
<net::X509Certificate
> cert(
736 new net::X509Certificate("test", "test", base::Time(), base::Time()));
737 test_client
.ContinueWithCertificate(cert
.get());
738 raw_ptr_resource_handler_
->WaitForResponseComplete();
739 EXPECT_EQ(net::OK
, raw_ptr_resource_handler_
->status().error());
741 // Restore the original content browser client.
742 SetBrowserClientForTesting(old_client
);
745 // Tests that the ContentBrowserClient may cancel a certificate request.
746 TEST_F(ClientCertResourceLoaderTest
, CancelSelection
) {
747 // Plug in test content browser client.
748 SelectCertificateBrowserClient test_client
;
749 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&test_client
);
751 // Start the request and wait for it to pause.
752 loader_
->StartRequest();
753 test_client
.WaitForSelectCertificate();
755 // Check if the SelectClientCertificate was called on the content browser
757 EXPECT_EQ(1, test_client
.call_count());
758 EXPECT_EQ(net::CertificateList(), test_client
.passed_certs());
760 // Cancel the request.
761 test_client
.CancelCertificateSelection();
762 raw_ptr_resource_handler_
->WaitForResponseComplete();
763 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
,
764 raw_ptr_resource_handler_
->status().error());
766 // Restore the original content browser client.
767 SetBrowserClientForTesting(old_client
);
770 // Verifies that requests without WebContents attached abort.
771 TEST_F(ClientCertResourceLoaderTest
, NoWebContents
) {
772 // Destroy the WebContents before starting the request.
773 web_contents_
.reset();
775 // Plug in test content browser client.
776 SelectCertificateBrowserClient test_client
;
777 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&test_client
);
779 // Start the request and wait for it to complete.
780 loader_
->StartRequest();
781 raw_ptr_resource_handler_
->WaitForResponseComplete();
783 // Check that SelectClientCertificate wasn't called and the request aborted.
784 EXPECT_EQ(0, test_client
.call_count());
785 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
,
786 raw_ptr_resource_handler_
->status().error());
788 // Restore the original content browser client.
789 SetBrowserClientForTesting(old_client
);
792 // Verifies that ClientCertStore's callback doesn't crash if called after the
793 // loader is destroyed.
794 TEST_F(ClientCertResourceLoaderTest
, StoreAsyncCancel
) {
795 base::RunLoop loader_destroyed_run_loop
;
796 LoaderDestroyingCertStore
* test_store
=
797 new LoaderDestroyingCertStore(&loader_
,
798 loader_destroyed_run_loop
.QuitClosure());
799 resource_context_
.SetClientCertStore(
800 make_scoped_ptr(test_store
));
802 loader_
->StartRequest();
803 loader_destroyed_run_loop
.Run();
804 EXPECT_FALSE(loader_
);
806 // Pump the event loop to ensure nothing asynchronous crashes either.
807 base::RunLoop().RunUntilIdle();
810 TEST_F(ResourceLoaderTest
, ResumeCancelledRequest
) {
811 raw_ptr_resource_handler_
->set_defer_request_on_will_start(true);
813 loader_
->StartRequest();
814 loader_
->CancelRequest(true);
815 static_cast<ResourceController
*>(loader_
.get())->Resume();
818 // Tests that no invariants are broken if a ResourceHandler cancels during
820 TEST_F(ResourceLoaderTest
, CancelOnReadCompleted
) {
821 raw_ptr_resource_handler_
->set_cancel_on_read_completed(true);
823 loader_
->StartRequest();
824 raw_ptr_resource_handler_
->WaitForResponseComplete();
826 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
827 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
828 raw_ptr_resource_handler_
->status().status());
831 // Tests that no invariants are broken if a ResourceHandler defers EOF.
832 TEST_F(ResourceLoaderTest
, DeferEOF
) {
833 raw_ptr_resource_handler_
->set_defer_eof(true);
835 loader_
->StartRequest();
836 raw_ptr_resource_handler_
->WaitForDeferredStep();
838 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
839 EXPECT_FALSE(raw_ptr_resource_handler_
->received_response_completed());
841 raw_ptr_resource_handler_
->Resume();
842 raw_ptr_resource_handler_
->WaitForResponseComplete();
843 EXPECT_EQ(net::URLRequestStatus::SUCCESS
,
844 raw_ptr_resource_handler_
->status().status());
847 class ResourceLoaderRedirectToFileTest
: public ResourceLoaderTest
{
849 ResourceLoaderRedirectToFileTest()
850 : file_stream_(NULL
),
851 redirect_to_file_resource_handler_(NULL
) {
854 ~ResourceLoaderRedirectToFileTest() override
{
855 // Releasing the loader should result in destroying the file asynchronously.
856 file_stream_
= nullptr;
857 deletable_file_
= nullptr;
860 // Wait for the task to delete the file to run, and make sure the file is
862 base::RunLoop().RunUntilIdle();
863 EXPECT_FALSE(base::PathExists(temp_path()));
866 base::FilePath
temp_path() const { return temp_path_
; }
867 ShareableFileReference
* deletable_file() const {
868 return deletable_file_
.get();
870 net::testing::MockFileStream
* file_stream() const { return file_stream_
; }
871 RedirectToFileResourceHandler
* redirect_to_file_resource_handler() const {
872 return redirect_to_file_resource_handler_
;
875 scoped_ptr
<ResourceHandler
> WrapResourceHandler(
876 scoped_ptr
<ResourceHandlerStub
> leaf_handler
,
877 net::URLRequest
* request
) override
{
878 leaf_handler
->set_expect_reads(false);
880 // Make a temporary file.
881 CHECK(base::CreateTemporaryFile(&temp_path_
));
882 int flags
= base::File::FLAG_WRITE
| base::File::FLAG_TEMPORARY
|
883 base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_ASYNC
;
884 base::File
file(temp_path_
, flags
);
885 CHECK(file
.IsValid());
887 // Create mock file streams and a ShareableFileReference.
888 scoped_ptr
<net::testing::MockFileStream
> file_stream(
889 new net::testing::MockFileStream(file
.Pass(),
890 base::ThreadTaskRunnerHandle::Get()));
891 file_stream_
= file_stream
.get();
892 deletable_file_
= ShareableFileReference::GetOrCreate(
894 ShareableFileReference::DELETE_ON_FINAL_RELEASE
,
895 BrowserThread::GetMessageLoopProxyForThread(
896 BrowserThread::FILE).get());
898 // Inject them into the handler.
899 scoped_ptr
<RedirectToFileResourceHandler
> handler(
900 new RedirectToFileResourceHandler(leaf_handler
.Pass(), request
));
901 redirect_to_file_resource_handler_
= handler
.get();
902 handler
->SetCreateTemporaryFileStreamFunctionForTesting(
903 base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback
,
904 base::Unretained(this),
905 base::Passed(&file_stream
)));
906 return handler
.Pass();
911 scoped_ptr
<net::FileStream
> file_stream
,
912 const CreateTemporaryFileStreamCallback
& callback
) {
913 base::ThreadTaskRunnerHandle::Get()->PostTask(
914 FROM_HERE
, base::Bind(callback
, base::File::FILE_OK
,
915 base::Passed(&file_stream
), deletable_file_
));
918 base::FilePath temp_path_
;
919 scoped_refptr
<ShareableFileReference
> deletable_file_
;
920 // These are owned by the ResourceLoader.
921 net::testing::MockFileStream
* file_stream_
;
922 RedirectToFileResourceHandler
* redirect_to_file_resource_handler_
;
925 // Tests that a RedirectToFileResourceHandler works and forwards everything
927 TEST_F(ResourceLoaderRedirectToFileTest
, Basic
) {
928 // Run it to completion.
929 loader_
->StartRequest();
930 raw_ptr_resource_handler_
->WaitForResponseComplete();
932 // Check that the handler forwarded all information to the downstream handler.
933 EXPECT_EQ(temp_path(),
934 raw_ptr_resource_handler_
->response()->head
.download_file_path
);
935 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
936 EXPECT_EQ(net::URLRequestStatus::SUCCESS
,
937 raw_ptr_resource_handler_
->status().status());
938 EXPECT_EQ(test_data().size(), static_cast<size_t>(
939 raw_ptr_resource_handler_
->total_bytes_downloaded()));
941 // Check that the data was written to the file.
942 std::string contents
;
943 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents
));
944 EXPECT_EQ(test_data(), contents
);
947 // Tests that RedirectToFileResourceHandler handles errors in creating the
949 TEST_F(ResourceLoaderRedirectToFileTest
, CreateTemporaryError
) {
950 // Swap out the create temporary function.
951 redirect_to_file_resource_handler()->
952 SetCreateTemporaryFileStreamFunctionForTesting(
953 base::Bind(&CreateTemporaryError
, base::File::FILE_ERROR_FAILED
));
955 // Run it to completion.
956 loader_
->StartRequest();
957 raw_ptr_resource_handler_
->WaitForResponseComplete();
959 // To downstream, the request was canceled.
960 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
961 raw_ptr_resource_handler_
->status().status());
962 EXPECT_EQ(0, raw_ptr_resource_handler_
->total_bytes_downloaded());
965 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
966 TEST_F(ResourceLoaderRedirectToFileTest
, WriteError
) {
967 file_stream()->set_forced_error(net::ERR_FAILED
);
969 // Run it to completion.
970 loader_
->StartRequest();
971 raw_ptr_resource_handler_
->WaitForResponseComplete();
973 // To downstream, the request was canceled sometime after it started, but
974 // before any data was written.
975 EXPECT_EQ(temp_path(),
976 raw_ptr_resource_handler_
->response()->head
.download_file_path
);
977 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
978 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
979 raw_ptr_resource_handler_
->status().status());
980 EXPECT_EQ(0, raw_ptr_resource_handler_
->total_bytes_downloaded());
983 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
984 TEST_F(ResourceLoaderRedirectToFileTest
, WriteErrorAsync
) {
985 file_stream()->set_forced_error_async(net::ERR_FAILED
);
987 // Run it to completion.
988 loader_
->StartRequest();
989 raw_ptr_resource_handler_
->WaitForResponseComplete();
991 // To downstream, the request was canceled sometime after it started, but
992 // before any data was written.
993 EXPECT_EQ(temp_path(),
994 raw_ptr_resource_handler_
->response()->head
.download_file_path
);
995 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
996 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
997 raw_ptr_resource_handler_
->status().status());
998 EXPECT_EQ(0, raw_ptr_resource_handler_
->total_bytes_downloaded());
1001 // Tests that RedirectToFileHandler defers completion if there are outstanding
1002 // writes and accounts for errors which occur in that time.
1003 TEST_F(ResourceLoaderRedirectToFileTest
, DeferCompletion
) {
1004 // Program the MockFileStream to error asynchronously, but throttle the
1006 file_stream()->set_forced_error_async(net::ERR_FAILED
);
1007 file_stream()->ThrottleCallbacks();
1009 // Run it as far as it will go.
1010 loader_
->StartRequest();
1011 base::RunLoop().RunUntilIdle();
1013 // At this point, the request should have completed.
1014 EXPECT_EQ(net::URLRequestStatus::SUCCESS
,
1015 raw_ptr_to_request_
->status().status());
1017 // However, the resource loader stack is stuck somewhere after receiving the
1019 EXPECT_EQ(temp_path(),
1020 raw_ptr_resource_handler_
->response()->head
.download_file_path
);
1021 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
1022 EXPECT_FALSE(raw_ptr_resource_handler_
->received_response_completed());
1023 EXPECT_EQ(0, raw_ptr_resource_handler_
->total_bytes_downloaded());
1025 // Now, release the floodgates.
1026 file_stream()->ReleaseCallbacks();
1027 raw_ptr_resource_handler_
->WaitForResponseComplete();
1029 // Although the URLRequest was successful, the leaf handler sees a failure
1030 // because the write never completed.
1031 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
1032 raw_ptr_resource_handler_
->status().status());
1035 // Tests that a RedirectToFileResourceHandler behaves properly when the
1036 // downstream handler defers OnWillStart.
1037 TEST_F(ResourceLoaderRedirectToFileTest
, DownstreamDeferStart
) {
1038 // Defer OnWillStart.
1039 raw_ptr_resource_handler_
->set_defer_request_on_will_start(true);
1041 // Run as far as we'll go.
1042 loader_
->StartRequest();
1043 raw_ptr_resource_handler_
->WaitForDeferredStep();
1045 // The request should have stopped at OnWillStart.
1046 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
1047 EXPECT_FALSE(raw_ptr_resource_handler_
->response());
1048 EXPECT_FALSE(raw_ptr_resource_handler_
->received_response_completed());
1049 EXPECT_EQ(0, raw_ptr_resource_handler_
->total_bytes_downloaded());
1051 // Now resume the request. Now we complete.
1052 raw_ptr_resource_handler_
->Resume();
1053 raw_ptr_resource_handler_
->WaitForResponseComplete();
1055 // Check that the handler forwarded all information to the downstream handler.
1056 EXPECT_EQ(temp_path(),
1057 raw_ptr_resource_handler_
->response()->head
.download_file_path
);
1058 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
1059 EXPECT_EQ(net::URLRequestStatus::SUCCESS
,
1060 raw_ptr_resource_handler_
->status().status());
1061 EXPECT_EQ(test_data().size(), static_cast<size_t>(
1062 raw_ptr_resource_handler_
->total_bytes_downloaded()));
1064 // Check that the data was written to the file.
1065 std::string contents
;
1066 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents
));
1067 EXPECT_EQ(test_data(), contents
);
1070 // Test that an HTTPS resource has the expected security info attached
1072 TEST_F(HTTPSSecurityInfoResourceLoaderTest
, SecurityInfoOnHTTPSResource
) {
1073 // Start the request and wait for it to finish.
1074 scoped_ptr
<net::URLRequest
> request(
1075 resource_context_
.GetRequestContext()->CreateRequest(
1076 test_https_url(), net::DEFAULT_PRIORITY
, nullptr /* delegate */));
1077 SetUpResourceLoader(request
.Pass());
1079 // Send the request and wait until it completes.
1080 loader_
->StartRequest();
1081 raw_ptr_resource_handler_
->WaitForResponseComplete();
1082 ASSERT_EQ(net::URLRequestStatus::SUCCESS
,
1083 raw_ptr_to_request_
->status().status());
1085 ResourceResponse
* response
= raw_ptr_resource_handler_
->response();
1086 ASSERT_TRUE(response
);
1088 // Deserialize the security info from the response and check that it
1090 SSLStatus deserialized
;
1092 DeserializeSecurityInfo(response
->head
.security_info
, &deserialized
));
1094 // Expect a BROKEN security style because the cert status has errors.
1095 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN
,
1096 deserialized
.security_style
);
1097 scoped_refptr
<net::X509Certificate
> cert
;
1099 CertStore::GetInstance()->RetrieveCert(deserialized
.cert_id
, &cert
));
1100 EXPECT_TRUE(cert
->Equals(GetTestCert().get()));
1102 EXPECT_EQ(kTestCertError
, deserialized
.cert_status
);
1103 EXPECT_EQ(kTestConnectionStatus
, deserialized
.connection_status
);
1104 EXPECT_EQ(kTestSecurityBits
, deserialized
.security_bits
);
1107 // Test that an HTTPS redirect response has the expected security info
1109 TEST_F(HTTPSSecurityInfoResourceLoaderTest
,
1110 SecurityInfoOnHTTPSRedirectResource
) {
1111 // Start the request and wait for it to finish.
1112 scoped_ptr
<net::URLRequest
> request(
1113 resource_context_
.GetRequestContext()->CreateRequest(
1114 test_https_redirect_url(), net::DEFAULT_PRIORITY
,
1115 nullptr /* delegate */));
1116 SetUpResourceLoader(request
.Pass());
1118 // Send the request and wait until it completes.
1119 loader_
->StartRequest();
1120 raw_ptr_resource_handler_
->WaitForResponseComplete();
1121 ASSERT_EQ(net::URLRequestStatus::SUCCESS
,
1122 raw_ptr_to_request_
->status().status());
1123 ASSERT_TRUE(raw_ptr_resource_handler_
->received_request_redirected());
1125 ResourceResponse
* redirect_response
=
1126 raw_ptr_resource_handler_
->redirect_response();
1127 ASSERT_TRUE(redirect_response
);
1129 // Deserialize the security info from the redirect response and check
1130 // that it is as expected.
1131 SSLStatus deserialized
;
1132 ASSERT_TRUE(DeserializeSecurityInfo(redirect_response
->head
.security_info
,
1135 // Expect a BROKEN security style because the cert status has errors.
1136 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN
,
1137 deserialized
.security_style
);
1138 scoped_refptr
<net::X509Certificate
> cert
;
1140 CertStore::GetInstance()->RetrieveCert(deserialized
.cert_id
, &cert
));
1141 EXPECT_TRUE(cert
->Equals(GetTestCert().get()));
1143 EXPECT_EQ(kTestCertError
, deserialized
.cert_status
);
1144 EXPECT_EQ(kTestConnectionStatus
, deserialized
.connection_status
);
1145 EXPECT_EQ(kTestSecurityBits
, deserialized
.security_bits
);
1148 } // namespace content