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/run_loop.h"
12 #include "base/single_thread_task_runner.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "content/browser/browser_thread_impl.h"
15 #include "content/browser/loader/redirect_to_file_resource_handler.h"
16 #include "content/browser/loader/resource_loader_delegate.h"
17 #include "content/common/ssl_status_serialization.h"
18 #include "content/public/browser/cert_store.h"
19 #include "content/public/browser/client_certificate_delegate.h"
20 #include "content/public/browser/resource_request_info.h"
21 #include "content/public/common/content_paths.h"
22 #include "content/public/common/resource_response.h"
23 #include "content/public/test/mock_resource_context.h"
24 #include "content/public/test/test_browser_context.h"
25 #include "content/public/test/test_browser_thread_bundle.h"
26 #include "content/public/test/test_renderer_host.h"
27 #include "content/test/test_content_browser_client.h"
28 #include "content/test/test_web_contents.h"
29 #include "ipc/ipc_message.h"
30 #include "net/base/chunked_upload_data_stream.h"
31 #include "net/base/io_buffer.h"
32 #include "net/base/mock_file_stream.h"
33 #include "net/base/net_errors.h"
34 #include "net/base/request_priority.h"
35 #include "net/base/test_data_directory.h"
36 #include "net/base/upload_bytes_element_reader.h"
37 #include "net/cert/x509_certificate.h"
38 #include "net/ssl/client_cert_store.h"
39 #include "net/ssl/ssl_cert_request_info.h"
40 #include "net/test/cert_test_util.h"
41 #include "net/test/embedded_test_server/embedded_test_server.h"
42 #include "net/url_request/url_request.h"
43 #include "net/url_request/url_request_filter.h"
44 #include "net/url_request/url_request_interceptor.h"
45 #include "net/url_request/url_request_job_factory.h"
46 #include "net/url_request/url_request_job_factory_impl.h"
47 #include "net/url_request/url_request_test_job.h"
48 #include "net/url_request/url_request_test_util.h"
49 #include "storage/browser/blob/shareable_file_reference.h"
50 #include "testing/gtest/include/gtest/gtest.h"
52 using storage::ShareableFileReference
;
57 // Stub client certificate store that returns a preset list of certificates for
58 // each request and records the arguments of the most recent request for later
60 class ClientCertStoreStub
: public net::ClientCertStore
{
62 // Creates a new ClientCertStoreStub that returns |response| on query. It
63 // saves the number of requests and most recently certificate authorities list
64 // in |requested_authorities| and |request_count|, respectively. The caller is
65 // responsible for ensuring those pointers outlive the ClientCertStoreStub.
67 // TODO(ppi): Make the stub independent from the internal representation of
68 // SSLCertRequestInfo. For now it seems that we can neither save the
69 // scoped_refptr<> (since it is never passed to us) nor copy the entire
70 // CertificateRequestInfo (since there is no copy constructor).
71 ClientCertStoreStub(const net::CertificateList
& response
,
73 std::vector
<std::string
>* requested_authorities
)
74 : response_(response
),
75 requested_authorities_(requested_authorities
),
76 request_count_(request_count
) {
77 requested_authorities_
->clear();
81 ~ClientCertStoreStub() override
{}
83 // net::ClientCertStore:
84 void GetClientCerts(const net::SSLCertRequestInfo
& cert_request_info
,
85 net::CertificateList
* selected_certs
,
86 const base::Closure
& callback
) override
{
87 *requested_authorities_
= cert_request_info
.cert_authorities
;
90 *selected_certs
= response_
;
95 const net::CertificateList response_
;
96 std::vector
<std::string
>* requested_authorities_
;
100 // Client certificate store which destroys its resource loader before the
101 // asynchronous GetClientCerts callback is called.
102 class LoaderDestroyingCertStore
: public net::ClientCertStore
{
104 // Creates a client certificate store which, when looked up, posts a task to
105 // reset |loader| and then call the callback. The caller is responsible for
106 // ensuring the pointers remain valid until the process is complete.
107 explicit LoaderDestroyingCertStore(scoped_ptr
<ResourceLoader
>* loader
)
110 // net::ClientCertStore:
111 void GetClientCerts(const net::SSLCertRequestInfo
& cert_request_info
,
112 net::CertificateList
* selected_certs
,
113 const base::Closure
& callback
) override
{
114 // Don't destroy |loader_| while it's on the stack.
115 base::ThreadTaskRunnerHandle::Get()->PostTask(
116 FROM_HERE
, base::Bind(&LoaderDestroyingCertStore::DoCallback
,
117 base::Unretained(loader_
), callback
));
121 static void DoCallback(scoped_ptr
<ResourceLoader
>* loader
,
122 const base::Closure
& callback
) {
127 scoped_ptr
<ResourceLoader
>* loader_
;
130 // A mock URLRequestJob which simulates an SSL client auth request.
131 class MockClientCertURLRequestJob
: public net::URLRequestTestJob
{
133 MockClientCertURLRequestJob(net::URLRequest
* request
,
134 net::NetworkDelegate
* network_delegate
)
135 : net::URLRequestTestJob(request
, network_delegate
) {}
137 static std::vector
<std::string
> test_authorities() {
138 return std::vector
<std::string
>(1, "dummy");
141 // net::URLRequestTestJob:
142 void Start() override
{
143 scoped_refptr
<net::SSLCertRequestInfo
> cert_request_info(
144 new net::SSLCertRequestInfo
);
145 cert_request_info
->cert_authorities
= test_authorities();
146 base::ThreadTaskRunnerHandle::Get()->PostTask(
148 base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested
,
149 this, cert_request_info
));
152 void ContinueWithCertificate(net::X509Certificate
* cert
) override
{
153 net::URLRequestTestJob::Start();
157 ~MockClientCertURLRequestJob() override
{}
159 DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob
);
162 class MockClientCertJobProtocolHandler
163 : public net::URLRequestJobFactory::ProtocolHandler
{
165 // URLRequestJobFactory::ProtocolHandler implementation:
166 net::URLRequestJob
* MaybeCreateJob(
167 net::URLRequest
* request
,
168 net::NetworkDelegate
* network_delegate
) const override
{
169 return new MockClientCertURLRequestJob(request
, network_delegate
);
173 // Set up dummy values to use in test HTTPS requests.
175 scoped_refptr
<net::X509Certificate
> GetTestCert() {
176 return net::ImportCertFromFile(net::GetTestCertsDirectory(),
177 "test_mail_google_com.pem");
180 const net::CertStatus kTestCertError
= net::CERT_STATUS_DATE_INVALID
;
181 const int kTestSecurityBits
= 256;
182 // SSL3 TLS_DHE_RSA_WITH_AES_256_CBC_SHA
183 const int kTestConnectionStatus
= 0x300039;
185 // A mock URLRequestJob which simulates an HTTPS request.
186 class MockHTTPSURLRequestJob
: public net::URLRequestTestJob
{
188 MockHTTPSURLRequestJob(net::URLRequest
* request
,
189 net::NetworkDelegate
* network_delegate
,
190 const std::string
& response_headers
,
191 const std::string
& response_data
,
193 : net::URLRequestTestJob(request
,
199 // net::URLRequestTestJob:
200 void GetResponseInfo(net::HttpResponseInfo
* info
) override
{
201 // Get the original response info, but override the SSL info.
202 net::URLRequestJob::GetResponseInfo(info
);
203 info
->ssl_info
.cert
= GetTestCert();
204 info
->ssl_info
.cert_status
= kTestCertError
;
205 info
->ssl_info
.security_bits
= kTestSecurityBits
;
206 info
->ssl_info
.connection_status
= kTestConnectionStatus
;
210 ~MockHTTPSURLRequestJob() override
{}
212 DISALLOW_COPY_AND_ASSIGN(MockHTTPSURLRequestJob
);
215 class MockHTTPSJobURLRequestInterceptor
: public net::URLRequestInterceptor
{
217 MockHTTPSJobURLRequestInterceptor() {}
218 ~MockHTTPSJobURLRequestInterceptor() override
{}
220 // net::URLRequestInterceptor:
221 net::URLRequestJob
* MaybeInterceptRequest(
222 net::URLRequest
* request
,
223 net::NetworkDelegate
* network_delegate
) const override
{
224 return new MockHTTPSURLRequestJob(request
, network_delegate
,
225 net::URLRequestTestJob::test_headers(),
226 "dummy response", true);
230 // Arbitrary read buffer size.
231 const int kReadBufSize
= 1024;
233 // Dummy implementation of ResourceHandler, instance of which is needed to
234 // initialize ResourceLoader.
235 class ResourceHandlerStub
: public ResourceHandler
{
237 explicit ResourceHandlerStub(net::URLRequest
* request
)
238 : ResourceHandler(request
),
239 read_buffer_(new net::IOBuffer(kReadBufSize
)),
240 defer_request_on_will_start_(false),
242 cancel_on_read_completed_(false),
244 received_on_will_read_(false),
245 received_eof_(false),
246 received_response_completed_(false),
247 total_bytes_downloaded_(0),
248 upload_position_(0) {
251 // If true, defers the resource load in OnWillStart.
252 void set_defer_request_on_will_start(bool defer_request_on_will_start
) {
253 defer_request_on_will_start_
= defer_request_on_will_start
;
256 // If true, expect OnWillRead / OnReadCompleted pairs for handling
257 // data. Otherwise, expect OnDataDownloaded.
258 void set_expect_reads(bool expect_reads
) { expect_reads_
= expect_reads
; }
260 // If true, cancel the request in OnReadCompleted by returning false.
261 void set_cancel_on_read_completed(bool cancel_on_read_completed
) {
262 cancel_on_read_completed_
= cancel_on_read_completed
;
265 // If true, cancel the request in OnReadCompleted by returning false.
266 void set_defer_eof(bool defer_eof
) { defer_eof_
= defer_eof
; }
268 const GURL
& start_url() const { return start_url_
; }
269 ResourceResponse
* response() const { return response_
.get(); }
270 bool received_response_completed() const {
271 return received_response_completed_
;
273 const net::URLRequestStatus
& status() const { return status_
; }
274 int total_bytes_downloaded() const { return total_bytes_downloaded_
; }
277 controller()->Resume();
280 // Waits until OnUploadProgress is called and returns the upload position.
281 uint64
WaitForUploadProgress() {
282 wait_for_progress_loop_
.reset(new base::RunLoop());
283 wait_for_progress_loop_
->Run();
284 wait_for_progress_loop_
.reset();
285 return upload_position_
;
288 // ResourceHandler implementation:
289 bool OnUploadProgress(uint64 position
, uint64 size
) override
{
290 EXPECT_LE(position
, size
);
291 EXPECT_GT(position
, upload_position_
);
292 upload_position_
= position
;
293 if (wait_for_progress_loop_
)
294 wait_for_progress_loop_
->Quit();
298 bool OnRequestRedirected(const net::RedirectInfo
& redirect_info
,
299 ResourceResponse
* response
,
300 bool* defer
) override
{
305 bool OnResponseStarted(ResourceResponse
* response
, bool* defer
) override
{
306 EXPECT_FALSE(response_
.get());
307 response_
= response
;
311 bool OnWillStart(const GURL
& url
, bool* defer
) override
{
312 EXPECT_TRUE(start_url_
.is_empty());
314 *defer
= defer_request_on_will_start_
;
318 bool OnBeforeNetworkStart(const GURL
& url
, bool* defer
) override
{
322 bool OnWillRead(scoped_refptr
<net::IOBuffer
>* buf
,
324 int min_size
) override
{
325 EXPECT_TRUE(expect_reads_
);
326 EXPECT_FALSE(received_on_will_read_
);
327 EXPECT_FALSE(received_eof_
);
328 EXPECT_FALSE(received_response_completed_
);
331 *buf_size
= kReadBufSize
;
332 received_on_will_read_
= true;
336 bool OnReadCompleted(int bytes_read
, bool* defer
) override
{
337 EXPECT_TRUE(received_on_will_read_
);
338 EXPECT_TRUE(expect_reads_
);
339 EXPECT_FALSE(received_response_completed_
);
341 if (bytes_read
== 0) {
342 received_eof_
= true;
349 // Need another OnWillRead() call before seeing an OnReadCompleted().
350 received_on_will_read_
= false;
352 return !cancel_on_read_completed_
;
355 void OnResponseCompleted(const net::URLRequestStatus
& status
,
356 const std::string
& security_info
,
357 bool* defer
) override
{
358 EXPECT_FALSE(received_response_completed_
);
359 if (status
.is_success() && expect_reads_
)
360 EXPECT_TRUE(received_eof_
);
362 received_response_completed_
= true;
366 void OnDataDownloaded(int bytes_downloaded
) override
{
367 EXPECT_FALSE(expect_reads_
);
368 total_bytes_downloaded_
+= bytes_downloaded
;
372 scoped_refptr
<net::IOBuffer
> read_buffer_
;
374 bool defer_request_on_will_start_
;
376 bool cancel_on_read_completed_
;
380 scoped_refptr
<ResourceResponse
> response_
;
381 bool received_on_will_read_
;
383 bool received_response_completed_
;
384 net::URLRequestStatus status_
;
385 int total_bytes_downloaded_
;
386 scoped_ptr
<base::RunLoop
> wait_for_progress_loop_
;
387 uint64 upload_position_
;
390 // Test browser client that captures calls to SelectClientCertificates and
391 // records the arguments of the most recent call for later inspection.
392 class SelectCertificateBrowserClient
: public TestContentBrowserClient
{
394 SelectCertificateBrowserClient() : call_count_(0) {}
396 void SelectClientCertificate(
397 WebContents
* web_contents
,
398 net::SSLCertRequestInfo
* cert_request_info
,
399 scoped_ptr
<ClientCertificateDelegate
> delegate
) override
{
401 passed_certs_
= cert_request_info
->client_certs
;
402 delegate_
= delegate
.Pass();
405 int call_count() { return call_count_
; }
406 net::CertificateList
passed_certs() { return passed_certs_
; }
408 void ContinueWithCertificate(net::X509Certificate
* cert
) {
409 delegate_
->ContinueWithCertificate(cert
);
413 void CancelCertificateSelection() { delegate_
.reset(); }
416 net::CertificateList passed_certs_
;
418 scoped_ptr
<ClientCertificateDelegate
> delegate_
;
421 class ResourceContextStub
: public MockResourceContext
{
423 explicit ResourceContextStub(net::URLRequestContext
* test_request_context
)
424 : MockResourceContext(test_request_context
) {}
426 scoped_ptr
<net::ClientCertStore
> CreateClientCertStore() override
{
427 return dummy_cert_store_
.Pass();
430 void SetClientCertStore(scoped_ptr
<net::ClientCertStore
> store
) {
431 dummy_cert_store_
= store
.Pass();
435 scoped_ptr
<net::ClientCertStore
> dummy_cert_store_
;
438 // Wraps a ChunkedUploadDataStream to behave as non-chunked to enable upload
439 // progress reporting.
440 class NonChunkedUploadDataStream
: public net::UploadDataStream
{
442 explicit NonChunkedUploadDataStream(uint64 size
)
443 : net::UploadDataStream(false, 0), stream_(0), size_(size
) {}
445 void AppendData(const char* data
) {
446 stream_
.AppendData(data
, strlen(data
), false);
450 int InitInternal() override
{
452 stream_
.Init(base::Bind(&NonChunkedUploadDataStream::OnInitCompleted
,
453 base::Unretained(this)));
457 int ReadInternal(net::IOBuffer
* buf
, int buf_len
) override
{
458 return stream_
.Read(buf
, buf_len
,
459 base::Bind(&NonChunkedUploadDataStream::OnReadCompleted
,
460 base::Unretained(this)));
463 void ResetInternal() override
{ stream_
.Reset(); }
465 net::ChunkedUploadDataStream stream_
;
468 DISALLOW_COPY_AND_ASSIGN(NonChunkedUploadDataStream
);
471 // Fails to create a temporary file with the given error.
472 void CreateTemporaryError(
473 base::File::Error error
,
474 const CreateTemporaryFileStreamCallback
& callback
) {
475 base::ThreadTaskRunnerHandle::Get()->PostTask(
477 base::Bind(callback
, error
, base::Passed(scoped_ptr
<net::FileStream
>()),
478 scoped_refptr
<ShareableFileReference
>()));
483 class ResourceLoaderTest
: public testing::Test
,
484 public ResourceLoaderDelegate
{
487 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP
),
488 resource_context_(&test_url_request_context_
),
489 raw_ptr_resource_handler_(NULL
),
490 raw_ptr_to_request_(NULL
) {
491 test_url_request_context_
.set_job_factory(&job_factory_
);
494 GURL
test_url() const { return net::URLRequestTestJob::test_url_1(); }
496 std::string
test_data() const {
497 return net::URLRequestTestJob::test_data_1();
500 // Waits until upload progress reaches |target_position|
501 void WaitForUploadProgress(uint64 target_position
) {
503 uint64 position
= raw_ptr_resource_handler_
->WaitForUploadProgress();
504 EXPECT_LE(position
, target_position
);
505 loader_
->OnUploadProgressACK();
506 if (position
== target_position
)
511 virtual net::URLRequestJobFactory::ProtocolHandler
* CreateProtocolHandler() {
512 return net::URLRequestTestJob::CreateProtocolHandler();
515 virtual scoped_ptr
<ResourceHandler
> WrapResourceHandler(
516 scoped_ptr
<ResourceHandlerStub
> leaf_handler
,
517 net::URLRequest
* request
) {
518 return leaf_handler
.Pass();
521 // Replaces loader_ with a new one for |request|.
522 void SetUpResourceLoader(scoped_ptr
<net::URLRequest
> request
) {
523 raw_ptr_to_request_
= request
.get();
525 RenderFrameHost
* rfh
= web_contents_
->GetMainFrame();
526 ResourceRequestInfo::AllocateForTesting(
527 request
.get(), RESOURCE_TYPE_MAIN_FRAME
, &resource_context_
,
528 rfh
->GetProcess()->GetID(), rfh
->GetRenderViewHost()->GetRoutingID(),
529 rfh
->GetRoutingID(), true /* is_main_frame */,
530 false /* parent_is_main_frame */, true /* allow_download */,
531 false /* is_async */);
532 scoped_ptr
<ResourceHandlerStub
> resource_handler(
533 new ResourceHandlerStub(request
.get()));
534 raw_ptr_resource_handler_
= resource_handler
.get();
535 loader_
.reset(new ResourceLoader(
537 WrapResourceHandler(resource_handler
.Pass(), raw_ptr_to_request_
),
541 void SetUp() override
{
542 job_factory_
.SetProtocolHandler("test", CreateProtocolHandler());
544 browser_context_
.reset(new TestBrowserContext());
545 scoped_refptr
<SiteInstance
> site_instance
=
546 SiteInstance::Create(browser_context_
.get());
548 TestWebContents::Create(browser_context_
.get(), site_instance
.get()));
550 scoped_ptr
<net::URLRequest
> request(
551 resource_context_
.GetRequestContext()->CreateRequest(
553 net::DEFAULT_PRIORITY
,
554 nullptr /* delegate */));
555 SetUpResourceLoader(request
.Pass());
558 void TearDown() override
{
559 // Destroy the WebContents and pump the event loop before destroying
560 // |rvh_test_enabler_| and |thread_bundle_|. This lets asynchronous cleanup
562 web_contents_
.reset();
563 base::RunLoop().RunUntilIdle();
566 // ResourceLoaderDelegate:
567 ResourceDispatcherHostLoginDelegate
* CreateLoginDelegate(
568 ResourceLoader
* loader
,
569 net::AuthChallengeInfo
* auth_info
) override
{
572 bool HandleExternalProtocol(ResourceLoader
* loader
,
573 const GURL
& url
) override
{
576 void DidStartRequest(ResourceLoader
* loader
) override
{}
577 void DidReceiveRedirect(ResourceLoader
* loader
,
578 const GURL
& new_url
) override
{}
579 void DidReceiveResponse(ResourceLoader
* loader
) override
{}
580 void DidFinishLoading(ResourceLoader
* loader
) override
{}
582 TestBrowserThreadBundle thread_bundle_
;
583 RenderViewHostTestEnabler rvh_test_enabler_
;
585 net::URLRequestJobFactoryImpl job_factory_
;
586 net::TestURLRequestContext test_url_request_context_
;
587 ResourceContextStub resource_context_
;
588 scoped_ptr
<TestBrowserContext
> browser_context_
;
589 scoped_ptr
<TestWebContents
> web_contents_
;
591 // The ResourceLoader owns the URLRequest and the ResourceHandler.
592 ResourceHandlerStub
* raw_ptr_resource_handler_
;
593 net::URLRequest
* raw_ptr_to_request_
;
594 scoped_ptr
<ResourceLoader
> loader_
;
597 class ClientCertResourceLoaderTest
: public ResourceLoaderTest
{
599 net::URLRequestJobFactory::ProtocolHandler
* CreateProtocolHandler() override
{
600 return new MockClientCertJobProtocolHandler
;
604 // A ResourceLoaderTest that intercepts https://example.test URLs and
605 // sets SSL info on the responses.
606 class HTTPSSecurityInfoResourceLoaderTest
: public ResourceLoaderTest
{
608 HTTPSSecurityInfoResourceLoaderTest()
609 : ResourceLoaderTest(), test_https_url_("https://example.test") {}
611 ~HTTPSSecurityInfoResourceLoaderTest() override
{}
613 const GURL
& test_https_url() { return test_https_url_
; }
616 void SetUp() override
{
617 ResourceLoaderTest::SetUp();
618 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
619 "https", "example.test", scoped_ptr
<net::URLRequestInterceptor
>(
620 new MockHTTPSJobURLRequestInterceptor
));
624 const GURL test_https_url_
;
627 // Tests that client certificates are requested with ClientCertStore lookup.
628 TEST_F(ClientCertResourceLoaderTest
, WithStoreLookup
) {
629 // Set up the test client cert store.
630 int store_request_count
;
631 std::vector
<std::string
> store_requested_authorities
;
632 net::CertificateList
dummy_certs(1, scoped_refptr
<net::X509Certificate
>(
633 new net::X509Certificate("test", "test", base::Time(), base::Time())));
634 scoped_ptr
<ClientCertStoreStub
> test_store(new ClientCertStoreStub(
635 dummy_certs
, &store_request_count
, &store_requested_authorities
));
636 resource_context_
.SetClientCertStore(test_store
.Pass());
638 // Plug in test content browser client.
639 SelectCertificateBrowserClient test_client
;
640 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&test_client
);
642 // Start the request and wait for it to pause.
643 loader_
->StartRequest();
644 base::RunLoop().RunUntilIdle();
646 EXPECT_FALSE(raw_ptr_resource_handler_
->received_response_completed());
648 // Check if the test store was queried against correct |cert_authorities|.
649 EXPECT_EQ(1, store_request_count
);
650 EXPECT_EQ(MockClientCertURLRequestJob::test_authorities(),
651 store_requested_authorities
);
653 // Check if the retrieved certificates were passed to the content browser
655 EXPECT_EQ(1, test_client
.call_count());
656 EXPECT_EQ(dummy_certs
, test_client
.passed_certs());
658 // Continue the request.
659 test_client
.ContinueWithCertificate(dummy_certs
[0].get());
660 base::RunLoop().RunUntilIdle();
661 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
662 EXPECT_EQ(net::OK
, raw_ptr_resource_handler_
->status().error());
664 // Restore the original content browser client.
665 SetBrowserClientForTesting(old_client
);
668 // Tests that client certificates are requested on a platform with NULL
670 TEST_F(ClientCertResourceLoaderTest
, WithNullStore
) {
671 // Plug in test content browser client.
672 SelectCertificateBrowserClient test_client
;
673 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&test_client
);
675 // Start the request and wait for it to pause.
676 loader_
->StartRequest();
677 base::RunLoop().RunUntilIdle();
679 // Check if the SelectClientCertificate was called on the content browser
681 EXPECT_EQ(1, test_client
.call_count());
682 EXPECT_EQ(net::CertificateList(), test_client
.passed_certs());
684 // Continue the request.
685 scoped_refptr
<net::X509Certificate
> cert(
686 new net::X509Certificate("test", "test", base::Time(), base::Time()));
687 test_client
.ContinueWithCertificate(cert
.get());
688 base::RunLoop().RunUntilIdle();
689 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
690 EXPECT_EQ(net::OK
, raw_ptr_resource_handler_
->status().error());
692 // Restore the original content browser client.
693 SetBrowserClientForTesting(old_client
);
696 // Tests that the ContentBrowserClient may cancel a certificate request.
697 TEST_F(ClientCertResourceLoaderTest
, CancelSelection
) {
698 // Plug in test content browser client.
699 SelectCertificateBrowserClient test_client
;
700 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&test_client
);
702 // Start the request and wait for it to pause.
703 loader_
->StartRequest();
704 base::RunLoop().RunUntilIdle();
706 // Check if the SelectClientCertificate was called on the content browser
708 EXPECT_EQ(1, test_client
.call_count());
709 EXPECT_EQ(net::CertificateList(), test_client
.passed_certs());
711 // Cancel the request.
712 test_client
.CancelCertificateSelection();
713 base::RunLoop().RunUntilIdle();
714 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
715 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
,
716 raw_ptr_resource_handler_
->status().error());
718 // Restore the original content browser client.
719 SetBrowserClientForTesting(old_client
);
722 // Verifies that requests without WebContents attached abort.
723 TEST_F(ClientCertResourceLoaderTest
, NoWebContents
) {
724 // Destroy the WebContents before starting the request.
725 web_contents_
.reset();
727 // Plug in test content browser client.
728 SelectCertificateBrowserClient test_client
;
729 ContentBrowserClient
* old_client
= SetBrowserClientForTesting(&test_client
);
731 // Start the request and wait for it to pause.
732 loader_
->StartRequest();
733 base::RunLoop().RunUntilIdle();
735 // Check that SelectClientCertificate wasn't called and the request aborted.
736 EXPECT_EQ(0, test_client
.call_count());
737 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
738 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED
,
739 raw_ptr_resource_handler_
->status().error());
741 // Restore the original content browser client.
742 SetBrowserClientForTesting(old_client
);
745 // Verifies that ClientCertStore's callback doesn't crash if called after the
746 // loader is destroyed.
747 TEST_F(ClientCertResourceLoaderTest
, StoreAsyncCancel
) {
748 scoped_ptr
<LoaderDestroyingCertStore
> test_store(
749 new LoaderDestroyingCertStore(&loader_
));
750 resource_context_
.SetClientCertStore(test_store
.Pass());
752 loader_
->StartRequest();
753 base::RunLoop().RunUntilIdle();
754 EXPECT_FALSE(loader_
);
756 // Pump the event loop to ensure nothing asynchronous crashes either.
757 base::RunLoop().RunUntilIdle();
760 TEST_F(ResourceLoaderTest
, ResumeCancelledRequest
) {
761 raw_ptr_resource_handler_
->set_defer_request_on_will_start(true);
763 loader_
->StartRequest();
764 loader_
->CancelRequest(true);
765 static_cast<ResourceController
*>(loader_
.get())->Resume();
768 // Tests that no invariants are broken if a ResourceHandler cancels during
770 TEST_F(ResourceLoaderTest
, CancelOnReadCompleted
) {
771 raw_ptr_resource_handler_
->set_cancel_on_read_completed(true);
773 loader_
->StartRequest();
774 base::RunLoop().RunUntilIdle();
776 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
777 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
778 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
779 raw_ptr_resource_handler_
->status().status());
782 // Tests that no invariants are broken if a ResourceHandler defers EOF.
783 TEST_F(ResourceLoaderTest
, DeferEOF
) {
784 raw_ptr_resource_handler_
->set_defer_eof(true);
786 loader_
->StartRequest();
787 base::RunLoop().RunUntilIdle();
789 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
790 EXPECT_FALSE(raw_ptr_resource_handler_
->received_response_completed());
792 raw_ptr_resource_handler_
->Resume();
793 base::RunLoop().RunUntilIdle();
795 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
796 EXPECT_EQ(net::URLRequestStatus::SUCCESS
,
797 raw_ptr_resource_handler_
->status().status());
800 // Tests that progress is reported correctly while uploading.
801 // TODO(andresantoso): Add test for the redirect case.
802 TEST_F(ResourceLoaderTest
, UploadProgress
) {
803 // Set up a test server.
804 net::test_server::EmbeddedTestServer server
;
805 ASSERT_TRUE(server
.InitializeAndWaitUntilReady());
807 PathService::Get(content::DIR_TEST_DATA
, &path
);
808 server
.ServeFilesFromDirectory(path
);
810 scoped_ptr
<net::URLRequest
> request(
811 resource_context_
.GetRequestContext()->CreateRequest(
812 server
.GetURL("/title1.html"),
813 net::DEFAULT_PRIORITY
,
814 nullptr /* delegate */));
817 auto stream
= new NonChunkedUploadDataStream(10);
818 request
->set_upload(make_scoped_ptr(stream
));
820 SetUpResourceLoader(request
.Pass());
821 loader_
->StartRequest();
823 stream
->AppendData("xx");
824 WaitForUploadProgress(2);
826 stream
->AppendData("yyy");
827 WaitForUploadProgress(5);
829 stream
->AppendData("zzzzz");
830 WaitForUploadProgress(10);
833 class ResourceLoaderRedirectToFileTest
: public ResourceLoaderTest
{
835 ResourceLoaderRedirectToFileTest()
836 : file_stream_(NULL
),
837 redirect_to_file_resource_handler_(NULL
) {
840 base::FilePath
temp_path() const { return temp_path_
; }
841 ShareableFileReference
* deletable_file() const {
842 return deletable_file_
.get();
844 net::testing::MockFileStream
* file_stream() const { return file_stream_
; }
845 RedirectToFileResourceHandler
* redirect_to_file_resource_handler() const {
846 return redirect_to_file_resource_handler_
;
849 void ReleaseLoader() {
851 deletable_file_
= NULL
;
855 scoped_ptr
<ResourceHandler
> WrapResourceHandler(
856 scoped_ptr
<ResourceHandlerStub
> leaf_handler
,
857 net::URLRequest
* request
) override
{
858 leaf_handler
->set_expect_reads(false);
860 // Make a temporary file.
861 CHECK(base::CreateTemporaryFile(&temp_path_
));
862 int flags
= base::File::FLAG_WRITE
| base::File::FLAG_TEMPORARY
|
863 base::File::FLAG_CREATE_ALWAYS
| base::File::FLAG_ASYNC
;
864 base::File
file(temp_path_
, flags
);
865 CHECK(file
.IsValid());
867 // Create mock file streams and a ShareableFileReference.
868 scoped_ptr
<net::testing::MockFileStream
> file_stream(
869 new net::testing::MockFileStream(file
.Pass(),
870 base::ThreadTaskRunnerHandle::Get()));
871 file_stream_
= file_stream
.get();
872 deletable_file_
= ShareableFileReference::GetOrCreate(
874 ShareableFileReference::DELETE_ON_FINAL_RELEASE
,
875 BrowserThread::GetMessageLoopProxyForThread(
876 BrowserThread::FILE).get());
878 // Inject them into the handler.
879 scoped_ptr
<RedirectToFileResourceHandler
> handler(
880 new RedirectToFileResourceHandler(leaf_handler
.Pass(), request
));
881 redirect_to_file_resource_handler_
= handler
.get();
882 handler
->SetCreateTemporaryFileStreamFunctionForTesting(
883 base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback
,
884 base::Unretained(this),
885 base::Passed(&file_stream
)));
886 return handler
.Pass();
891 scoped_ptr
<net::FileStream
> file_stream
,
892 const CreateTemporaryFileStreamCallback
& callback
) {
893 base::ThreadTaskRunnerHandle::Get()->PostTask(
894 FROM_HERE
, base::Bind(callback
, base::File::FILE_OK
,
895 base::Passed(&file_stream
), deletable_file_
));
898 base::FilePath temp_path_
;
899 scoped_refptr
<ShareableFileReference
> deletable_file_
;
900 // These are owned by the ResourceLoader.
901 net::testing::MockFileStream
* file_stream_
;
902 RedirectToFileResourceHandler
* redirect_to_file_resource_handler_
;
905 // Tests that a RedirectToFileResourceHandler works and forwards everything
907 TEST_F(ResourceLoaderRedirectToFileTest
, Basic
) {
908 // Run it to completion.
909 loader_
->StartRequest();
910 base::RunLoop().RunUntilIdle();
912 // Check that the handler forwarded all information to the downstream handler.
913 EXPECT_EQ(temp_path(),
914 raw_ptr_resource_handler_
->response()->head
.download_file_path
);
915 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
916 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
917 EXPECT_EQ(net::URLRequestStatus::SUCCESS
,
918 raw_ptr_resource_handler_
->status().status());
919 EXPECT_EQ(test_data().size(), static_cast<size_t>(
920 raw_ptr_resource_handler_
->total_bytes_downloaded()));
922 // Check that the data was written to the file.
923 std::string contents
;
924 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents
));
925 EXPECT_EQ(test_data(), contents
);
927 // Release the loader and the saved reference to file. The file should be gone
930 base::RunLoop().RunUntilIdle();
931 EXPECT_FALSE(base::PathExists(temp_path()));
934 // Tests that RedirectToFileResourceHandler handles errors in creating the
936 TEST_F(ResourceLoaderRedirectToFileTest
, CreateTemporaryError
) {
937 // Swap out the create temporary function.
938 redirect_to_file_resource_handler()->
939 SetCreateTemporaryFileStreamFunctionForTesting(
940 base::Bind(&CreateTemporaryError
, base::File::FILE_ERROR_FAILED
));
942 // Run it to completion.
943 loader_
->StartRequest();
944 base::RunLoop().RunUntilIdle();
946 // To downstream, the request was canceled.
947 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
948 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
949 raw_ptr_resource_handler_
->status().status());
950 EXPECT_EQ(0, raw_ptr_resource_handler_
->total_bytes_downloaded());
953 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
954 TEST_F(ResourceLoaderRedirectToFileTest
, WriteError
) {
955 file_stream()->set_forced_error(net::ERR_FAILED
);
957 // Run it to completion.
958 loader_
->StartRequest();
959 base::RunLoop().RunUntilIdle();
961 // To downstream, the request was canceled sometime after it started, but
962 // before any data was written.
963 EXPECT_EQ(temp_path(),
964 raw_ptr_resource_handler_
->response()->head
.download_file_path
);
965 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
966 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
967 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
968 raw_ptr_resource_handler_
->status().status());
969 EXPECT_EQ(0, raw_ptr_resource_handler_
->total_bytes_downloaded());
971 // Release the loader. The file should be gone now.
973 base::RunLoop().RunUntilIdle();
974 EXPECT_FALSE(base::PathExists(temp_path()));
977 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
978 TEST_F(ResourceLoaderRedirectToFileTest
, WriteErrorAsync
) {
979 file_stream()->set_forced_error_async(net::ERR_FAILED
);
981 // Run it to completion.
982 loader_
->StartRequest();
983 base::RunLoop().RunUntilIdle();
985 // To downstream, the request was canceled sometime after it started, but
986 // before any data was written.
987 EXPECT_EQ(temp_path(),
988 raw_ptr_resource_handler_
->response()->head
.download_file_path
);
989 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
990 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
991 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
992 raw_ptr_resource_handler_
->status().status());
993 EXPECT_EQ(0, raw_ptr_resource_handler_
->total_bytes_downloaded());
995 // Release the loader. The file should be gone now.
997 base::RunLoop().RunUntilIdle();
998 EXPECT_FALSE(base::PathExists(temp_path()));
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 base::RunLoop().RunUntilIdle();
1029 // Although the URLRequest was successful, the leaf handler sees a failure
1030 // because the write never completed.
1031 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
1032 EXPECT_EQ(net::URLRequestStatus::CANCELED
,
1033 raw_ptr_resource_handler_
->status().status());
1035 // Release the loader. The file should be gone now.
1037 base::RunLoop().RunUntilIdle();
1038 EXPECT_FALSE(base::PathExists(temp_path()));
1041 // Tests that a RedirectToFileResourceHandler behaves properly when the
1042 // downstream handler defers OnWillStart.
1043 TEST_F(ResourceLoaderRedirectToFileTest
, DownstreamDeferStart
) {
1044 // Defer OnWillStart.
1045 raw_ptr_resource_handler_
->set_defer_request_on_will_start(true);
1047 // Run as far as we'll go.
1048 loader_
->StartRequest();
1049 base::RunLoop().RunUntilIdle();
1051 // The request should have stopped at OnWillStart.
1052 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
1053 EXPECT_FALSE(raw_ptr_resource_handler_
->response());
1054 EXPECT_FALSE(raw_ptr_resource_handler_
->received_response_completed());
1055 EXPECT_EQ(0, raw_ptr_resource_handler_
->total_bytes_downloaded());
1057 // Now resume the request. Now we complete.
1058 raw_ptr_resource_handler_
->Resume();
1059 base::RunLoop().RunUntilIdle();
1061 // Check that the handler forwarded all information to the downstream handler.
1062 EXPECT_EQ(temp_path(),
1063 raw_ptr_resource_handler_
->response()->head
.download_file_path
);
1064 EXPECT_EQ(test_url(), raw_ptr_resource_handler_
->start_url());
1065 EXPECT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
1066 EXPECT_EQ(net::URLRequestStatus::SUCCESS
,
1067 raw_ptr_resource_handler_
->status().status());
1068 EXPECT_EQ(test_data().size(), static_cast<size_t>(
1069 raw_ptr_resource_handler_
->total_bytes_downloaded()));
1071 // Check that the data was written to the file.
1072 std::string contents
;
1073 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents
));
1074 EXPECT_EQ(test_data(), contents
);
1076 // Release the loader. The file should be gone now.
1078 base::RunLoop().RunUntilIdle();
1079 EXPECT_FALSE(base::PathExists(temp_path()));
1082 // Test that an HTTPS resource has the expected security info attached
1084 TEST_F(HTTPSSecurityInfoResourceLoaderTest
, SecurityInfoOnHTTPSResource
) {
1085 // Start the request and wait for it to finish.
1086 scoped_ptr
<net::URLRequest
> request(
1087 resource_context_
.GetRequestContext()->CreateRequest(
1088 test_https_url(), net::DEFAULT_PRIORITY
, nullptr /* delegate */));
1089 SetUpResourceLoader(request
.Pass());
1091 // Send the request and wait until it completes.
1092 loader_
->StartRequest();
1093 base::RunLoop().RunUntilIdle();
1094 ASSERT_EQ(net::URLRequestStatus::SUCCESS
,
1095 raw_ptr_to_request_
->status().status());
1096 ASSERT_TRUE(raw_ptr_resource_handler_
->received_response_completed());
1098 ResourceResponse
* response
= raw_ptr_resource_handler_
->response();
1099 ASSERT_TRUE(response
);
1101 // Deserialize the security info from the response and check that it
1103 SSLStatus deserialized
;
1105 DeserializeSecurityInfo(response
->head
.security_info
, &deserialized
));
1107 // Expect a BROKEN security style because the cert status has errors.
1108 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN
,
1109 deserialized
.security_style
);
1110 scoped_refptr
<net::X509Certificate
> cert
;
1112 CertStore::GetInstance()->RetrieveCert(deserialized
.cert_id
, &cert
));
1113 EXPECT_TRUE(cert
->Equals(GetTestCert().get()));
1115 EXPECT_EQ(kTestCertError
, deserialized
.cert_status
);
1116 EXPECT_EQ(kTestConnectionStatus
, deserialized
.connection_status
);
1117 EXPECT_EQ(kTestSecurityBits
, deserialized
.security_bits
);
1120 } // namespace content