[refactor] More post-NSS WebCrypto cleanups (utility functions).
[chromium-blink-merge.git] / content / browser / loader / resource_loader_unittest.cc
blob90418f3f11444a38a1140a3973e67d9e51ef5a4c
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;
55 namespace content {
56 namespace {
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
60 // inspection.
61 class ClientCertStoreStub : public net::ClientCertStore {
62 public:
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,
73 int* request_count,
74 std::vector<std::string>* requested_authorities)
75 : response_(response),
76 requested_authorities_(requested_authorities),
77 request_count_(request_count) {
78 requested_authorities_->clear();
79 *request_count_ = 0;
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;
89 ++(*request_count_);
91 *selected_certs = response_;
92 callback.Run();
95 private:
96 const net::CertificateList response_;
97 std::vector<std::string>* requested_authorities_;
98 int* request_count_;
101 // Client certificate store which destroys its resource loader before the
102 // asynchronous GetClientCerts callback is called.
103 class LoaderDestroyingCertStore : public net::ClientCertStore {
104 public:
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)
110 : loader_(loader),
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_));
126 private:
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) {
133 loader->reset();
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 {
146 public:
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(
161 FROM_HERE,
162 base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
163 this, cert_request_info));
166 void ContinueWithCertificate(net::X509Certificate* cert) override {
167 net::URLRequestTestJob::Start();
170 private:
171 ~MockClientCertURLRequestJob() override {}
173 DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob);
176 class MockClientCertJobProtocolHandler
177 : public net::URLRequestJobFactory::ProtocolHandler {
178 public:
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 {
201 public:
202 MockHTTPSURLRequestJob(net::URLRequest* request,
203 net::NetworkDelegate* network_delegate,
204 const std::string& response_headers,
205 const std::string& response_data,
206 bool auto_advance)
207 : net::URLRequestTestJob(request,
208 network_delegate,
209 response_headers,
210 response_data,
211 auto_advance) {}
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;
223 private:
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"
232 "\0";
234 class MockHTTPSJobURLRequestInterceptor : public net::URLRequestInterceptor {
235 public:
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);
250 private:
251 bool redirect_;
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 {
260 public:
261 explicit ResourceHandlerStub(net::URLRequest* request)
262 : ResourceHandler(request),
263 read_buffer_(new net::IOBuffer(kReadBufSize)),
264 defer_request_on_will_start_(false),
265 expect_reads_(true),
266 cancel_on_read_completed_(false),
267 defer_eof_(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_; }
305 void Resume() {
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;
314 return true;
317 bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
318 EXPECT_FALSE(response_.get());
319 response_ = response;
320 return true;
323 bool OnWillStart(const GURL& url, bool* defer) override {
324 EXPECT_TRUE(start_url_.is_empty());
325 start_url_ = url;
326 if (defer_request_on_will_start_) {
327 *defer = true;
328 deferred_run_loop_.Quit();
330 return true;
333 bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
334 return true;
337 bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
338 int* buf_size,
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_);
345 *buf = read_buffer_;
346 *buf_size = kReadBufSize;
347 received_on_will_read_ = true;
348 return 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;
358 if (defer_eof_) {
359 defer_eof_ = false;
360 *defer = 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;
379 status_ = status;
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_);
400 private:
401 scoped_refptr<net::IOBuffer> read_buffer_;
403 bool defer_request_on_will_start_;
404 bool expect_reads_;
405 bool cancel_on_read_completed_;
406 bool defer_eof_;
408 GURL start_url_;
409 scoped_refptr<ResourceResponse> response_;
410 scoped_refptr<ResourceResponse> redirect_response_;
411 bool received_on_will_read_;
412 bool received_eof_;
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 {
425 public:
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());
442 ++call_count_;
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);
453 delegate_.reset();
456 void CancelCertificateSelection() { delegate_.reset(); }
458 private:
459 net::CertificateList passed_certs_;
460 int call_count_;
461 scoped_ptr<ClientCertificateDelegate> delegate_;
463 base::RunLoop select_certificate_run_loop_;
465 DISALLOW_COPY_AND_ASSIGN(SelectCertificateBrowserClient);
468 class ResourceContextStub : public MockResourceContext {
469 public:
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();
481 private:
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 {
488 public:
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);
496 private:
497 int InitInternal() override {
498 SetSize(size_);
499 stream_.Init(base::Bind(&NonChunkedUploadDataStream::OnInitCompleted,
500 base::Unretained(this)));
501 return net::OK;
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_;
513 uint64 size_;
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(
523 FROM_HERE,
524 base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
525 scoped_refptr<ShareableFileReference>()));
528 } // namespace
530 class ResourceLoaderTest : public testing::Test,
531 public ResourceLoaderDelegate {
532 protected:
533 ResourceLoaderTest()
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(
573 request.Pass(),
574 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
575 this));
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());
584 web_contents_.reset(
585 TestWebContents::Create(browser_context_.get(), site_instance.get()));
587 scoped_ptr<net::URLRequest> request(
588 resource_context_.GetRequestContext()->CreateRequest(
589 test_url(),
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
598 // tasks complete.
599 web_contents_.reset();
600 base::RunLoop().RunUntilIdle();
603 // ResourceLoaderDelegate:
604 ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
605 ResourceLoader* loader,
606 net::AuthChallengeInfo* auth_info) override {
607 return NULL;
609 bool HandleExternalProtocol(ResourceLoader* loader,
610 const GURL& url) override {
611 return false;
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 {
635 protected:
636 scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> CreateProtocolHandler()
637 override {
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 {
646 public:
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_;
659 protected:
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 */)));
673 private:
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
705 // client.
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
719 // ClientCertStore.
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
730 // client.
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
756 // client.
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
819 // OnReadCompleted.
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 {
848 public:
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;
858 loader_.reset();
860 // Wait for the task to delete the file to run, and make sure the file is
861 // cleaned up.
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(
893 temp_path_,
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();
909 private:
910 void PostCallback(
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
926 // downstream.
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
948 // temporary file.
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
1005 // callback.
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
1018 // response.
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
1071 // to it.
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
1089 // is as expected.
1090 SSLStatus deserialized;
1091 ASSERT_TRUE(
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;
1098 ASSERT_TRUE(
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
1108 // attached to it.
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,
1133 &deserialized));
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;
1139 ASSERT_TRUE(
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