Update broken references to image assets
[chromium-blink-merge.git] / content / browser / loader / resource_loader_unittest.cc
blob0131f2f7448ee5712b99d60bfc2806ef11ad661e
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;
54 namespace content {
55 namespace {
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
59 // inspection.
60 class ClientCertStoreStub : public net::ClientCertStore {
61 public:
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,
72 int* request_count,
73 std::vector<std::string>* requested_authorities)
74 : response_(response),
75 requested_authorities_(requested_authorities),
76 request_count_(request_count) {
77 requested_authorities_->clear();
78 *request_count_ = 0;
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;
88 ++(*request_count_);
90 *selected_certs = response_;
91 callback.Run();
94 private:
95 const net::CertificateList response_;
96 std::vector<std::string>* requested_authorities_;
97 int* request_count_;
100 // Client certificate store which destroys its resource loader before the
101 // asynchronous GetClientCerts callback is called.
102 class LoaderDestroyingCertStore : public net::ClientCertStore {
103 public:
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)
108 : loader_(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));
120 private:
121 static void DoCallback(scoped_ptr<ResourceLoader>* loader,
122 const base::Closure& callback) {
123 loader->reset();
124 callback.Run();
127 scoped_ptr<ResourceLoader>* loader_;
130 // A mock URLRequestJob which simulates an SSL client auth request.
131 class MockClientCertURLRequestJob : public net::URLRequestTestJob {
132 public:
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(
147 FROM_HERE,
148 base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
149 this, cert_request_info));
152 void ContinueWithCertificate(net::X509Certificate* cert) override {
153 net::URLRequestTestJob::Start();
156 private:
157 ~MockClientCertURLRequestJob() override {}
159 DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob);
162 class MockClientCertJobProtocolHandler
163 : public net::URLRequestJobFactory::ProtocolHandler {
164 public:
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 {
187 public:
188 MockHTTPSURLRequestJob(net::URLRequest* request,
189 net::NetworkDelegate* network_delegate,
190 const std::string& response_headers,
191 const std::string& response_data,
192 bool auto_advance)
193 : net::URLRequestTestJob(request,
194 network_delegate,
195 response_headers,
196 response_data,
197 auto_advance) {}
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;
209 private:
210 ~MockHTTPSURLRequestJob() override {}
212 DISALLOW_COPY_AND_ASSIGN(MockHTTPSURLRequestJob);
215 const char kRedirectHeaders[] =
216 "HTTP/1.1 302 Found\0"
217 "Location: https://example.test\0"
218 "\0";
220 class MockHTTPSJobURLRequestInterceptor : public net::URLRequestInterceptor {
221 public:
222 MockHTTPSJobURLRequestInterceptor(bool redirect) : redirect_(redirect) {}
223 ~MockHTTPSJobURLRequestInterceptor() override {}
225 // net::URLRequestInterceptor:
226 net::URLRequestJob* MaybeInterceptRequest(
227 net::URLRequest* request,
228 net::NetworkDelegate* network_delegate) const override {
229 std::string headers =
230 redirect_ ? std::string(kRedirectHeaders, arraysize(kRedirectHeaders))
231 : net::URLRequestTestJob::test_headers();
232 return new MockHTTPSURLRequestJob(request, network_delegate, headers,
233 "dummy response", true);
236 private:
237 bool redirect_;
240 // Arbitrary read buffer size.
241 const int kReadBufSize = 1024;
243 // Dummy implementation of ResourceHandler, instance of which is needed to
244 // initialize ResourceLoader.
245 class ResourceHandlerStub : public ResourceHandler {
246 public:
247 explicit ResourceHandlerStub(net::URLRequest* request)
248 : ResourceHandler(request),
249 read_buffer_(new net::IOBuffer(kReadBufSize)),
250 defer_request_on_will_start_(false),
251 expect_reads_(true),
252 cancel_on_read_completed_(false),
253 defer_eof_(false),
254 received_on_will_read_(false),
255 received_eof_(false),
256 received_response_completed_(false),
257 received_request_redirected_(false),
258 total_bytes_downloaded_(0),
259 upload_position_(0) {}
261 // If true, defers the resource load in OnWillStart.
262 void set_defer_request_on_will_start(bool defer_request_on_will_start) {
263 defer_request_on_will_start_ = defer_request_on_will_start;
266 // If true, expect OnWillRead / OnReadCompleted pairs for handling
267 // data. Otherwise, expect OnDataDownloaded.
268 void set_expect_reads(bool expect_reads) { expect_reads_ = expect_reads; }
270 // If true, cancel the request in OnReadCompleted by returning false.
271 void set_cancel_on_read_completed(bool cancel_on_read_completed) {
272 cancel_on_read_completed_ = cancel_on_read_completed;
275 // If true, cancel the request in OnReadCompleted by returning false.
276 void set_defer_eof(bool defer_eof) { defer_eof_ = defer_eof; }
278 const GURL& start_url() const { return start_url_; }
279 ResourceResponse* response() const { return response_.get(); }
280 ResourceResponse* redirect_response() const {
281 return redirect_response_.get();
283 bool received_response_completed() const {
284 return received_response_completed_;
286 bool received_request_redirected() const {
287 return received_request_redirected_;
289 const net::URLRequestStatus& status() const { return status_; }
290 int total_bytes_downloaded() const { return total_bytes_downloaded_; }
292 void Resume() {
293 controller()->Resume();
296 // Waits until OnUploadProgress is called and returns the upload position.
297 uint64 WaitForUploadProgress() {
298 wait_for_progress_loop_.reset(new base::RunLoop());
299 wait_for_progress_loop_->Run();
300 wait_for_progress_loop_.reset();
301 return upload_position_;
304 // ResourceHandler implementation:
305 bool OnUploadProgress(uint64 position, uint64 size) override {
306 EXPECT_LE(position, size);
307 EXPECT_GT(position, upload_position_);
308 upload_position_ = position;
309 if (wait_for_progress_loop_)
310 wait_for_progress_loop_->Quit();
311 return true;
314 bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
315 ResourceResponse* response,
316 bool* defer) override {
317 redirect_response_ = response;
318 received_request_redirected_ = true;
319 return true;
322 bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
323 EXPECT_FALSE(response_.get());
324 response_ = response;
325 return true;
328 bool OnWillStart(const GURL& url, bool* defer) override {
329 EXPECT_TRUE(start_url_.is_empty());
330 start_url_ = url;
331 *defer = defer_request_on_will_start_;
332 return true;
335 bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
336 return true;
339 bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
340 int* buf_size,
341 int min_size) override {
342 EXPECT_TRUE(expect_reads_);
343 EXPECT_FALSE(received_on_will_read_);
344 EXPECT_FALSE(received_eof_);
345 EXPECT_FALSE(received_response_completed_);
347 *buf = read_buffer_;
348 *buf_size = kReadBufSize;
349 received_on_will_read_ = true;
350 return true;
353 bool OnReadCompleted(int bytes_read, bool* defer) override {
354 EXPECT_TRUE(received_on_will_read_);
355 EXPECT_TRUE(expect_reads_);
356 EXPECT_FALSE(received_response_completed_);
358 if (bytes_read == 0) {
359 received_eof_ = true;
360 if (defer_eof_) {
361 defer_eof_ = false;
362 *defer = true;
366 // Need another OnWillRead() call before seeing an OnReadCompleted().
367 received_on_will_read_ = false;
369 return !cancel_on_read_completed_;
372 void OnResponseCompleted(const net::URLRequestStatus& status,
373 const std::string& security_info,
374 bool* defer) override {
375 EXPECT_FALSE(received_response_completed_);
376 if (status.is_success() && expect_reads_)
377 EXPECT_TRUE(received_eof_);
379 received_response_completed_ = true;
380 status_ = status;
383 void OnDataDownloaded(int bytes_downloaded) override {
384 EXPECT_FALSE(expect_reads_);
385 total_bytes_downloaded_ += bytes_downloaded;
388 private:
389 scoped_refptr<net::IOBuffer> read_buffer_;
391 bool defer_request_on_will_start_;
392 bool expect_reads_;
393 bool cancel_on_read_completed_;
394 bool defer_eof_;
396 GURL start_url_;
397 scoped_refptr<ResourceResponse> response_;
398 scoped_refptr<ResourceResponse> redirect_response_;
399 bool received_on_will_read_;
400 bool received_eof_;
401 bool received_response_completed_;
402 bool received_request_redirected_;
403 net::URLRequestStatus status_;
404 int total_bytes_downloaded_;
405 scoped_ptr<base::RunLoop> wait_for_progress_loop_;
406 uint64 upload_position_;
409 // Test browser client that captures calls to SelectClientCertificates and
410 // records the arguments of the most recent call for later inspection.
411 class SelectCertificateBrowserClient : public TestContentBrowserClient {
412 public:
413 SelectCertificateBrowserClient() : call_count_(0) {}
415 void SelectClientCertificate(
416 WebContents* web_contents,
417 net::SSLCertRequestInfo* cert_request_info,
418 scoped_ptr<ClientCertificateDelegate> delegate) override {
419 ++call_count_;
420 passed_certs_ = cert_request_info->client_certs;
421 delegate_ = delegate.Pass();
424 int call_count() { return call_count_; }
425 net::CertificateList passed_certs() { return passed_certs_; }
427 void ContinueWithCertificate(net::X509Certificate* cert) {
428 delegate_->ContinueWithCertificate(cert);
429 delegate_.reset();
432 void CancelCertificateSelection() { delegate_.reset(); }
434 private:
435 net::CertificateList passed_certs_;
436 int call_count_;
437 scoped_ptr<ClientCertificateDelegate> delegate_;
440 class ResourceContextStub : public MockResourceContext {
441 public:
442 explicit ResourceContextStub(net::URLRequestContext* test_request_context)
443 : MockResourceContext(test_request_context) {}
445 scoped_ptr<net::ClientCertStore> CreateClientCertStore() override {
446 return dummy_cert_store_.Pass();
449 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
450 dummy_cert_store_ = store.Pass();
453 private:
454 scoped_ptr<net::ClientCertStore> dummy_cert_store_;
457 // Wraps a ChunkedUploadDataStream to behave as non-chunked to enable upload
458 // progress reporting.
459 class NonChunkedUploadDataStream : public net::UploadDataStream {
460 public:
461 explicit NonChunkedUploadDataStream(uint64 size)
462 : net::UploadDataStream(false, 0), stream_(0), size_(size) {}
464 void AppendData(const char* data) {
465 stream_.AppendData(data, strlen(data), false);
468 private:
469 int InitInternal() override {
470 SetSize(size_);
471 stream_.Init(base::Bind(&NonChunkedUploadDataStream::OnInitCompleted,
472 base::Unretained(this)));
473 return net::OK;
476 int ReadInternal(net::IOBuffer* buf, int buf_len) override {
477 return stream_.Read(buf, buf_len,
478 base::Bind(&NonChunkedUploadDataStream::OnReadCompleted,
479 base::Unretained(this)));
482 void ResetInternal() override { stream_.Reset(); }
484 net::ChunkedUploadDataStream stream_;
485 uint64 size_;
487 DISALLOW_COPY_AND_ASSIGN(NonChunkedUploadDataStream);
490 // Fails to create a temporary file with the given error.
491 void CreateTemporaryError(
492 base::File::Error error,
493 const CreateTemporaryFileStreamCallback& callback) {
494 base::ThreadTaskRunnerHandle::Get()->PostTask(
495 FROM_HERE,
496 base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
497 scoped_refptr<ShareableFileReference>()));
500 } // namespace
502 class ResourceLoaderTest : public testing::Test,
503 public ResourceLoaderDelegate {
504 protected:
505 ResourceLoaderTest()
506 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
507 resource_context_(&test_url_request_context_),
508 raw_ptr_resource_handler_(NULL),
509 raw_ptr_to_request_(NULL) {
510 test_url_request_context_.set_job_factory(&job_factory_);
513 GURL test_url() const { return net::URLRequestTestJob::test_url_1(); }
515 std::string test_data() const {
516 return net::URLRequestTestJob::test_data_1();
519 // Waits until upload progress reaches |target_position|
520 void WaitForUploadProgress(uint64 target_position) {
521 while (true) {
522 uint64 position = raw_ptr_resource_handler_->WaitForUploadProgress();
523 EXPECT_LE(position, target_position);
524 loader_->OnUploadProgressACK();
525 if (position == target_position)
526 break;
530 virtual net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler() {
531 return net::URLRequestTestJob::CreateProtocolHandler();
534 virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
535 scoped_ptr<ResourceHandlerStub> leaf_handler,
536 net::URLRequest* request) {
537 return leaf_handler.Pass();
540 // Replaces loader_ with a new one for |request|.
541 void SetUpResourceLoader(scoped_ptr<net::URLRequest> request) {
542 raw_ptr_to_request_ = request.get();
544 RenderFrameHost* rfh = web_contents_->GetMainFrame();
545 ResourceRequestInfo::AllocateForTesting(
546 request.get(), RESOURCE_TYPE_MAIN_FRAME, &resource_context_,
547 rfh->GetProcess()->GetID(), rfh->GetRenderViewHost()->GetRoutingID(),
548 rfh->GetRoutingID(), true /* is_main_frame */,
549 false /* parent_is_main_frame */, true /* allow_download */,
550 false /* is_async */);
551 scoped_ptr<ResourceHandlerStub> resource_handler(
552 new ResourceHandlerStub(request.get()));
553 raw_ptr_resource_handler_ = resource_handler.get();
554 loader_.reset(new ResourceLoader(
555 request.Pass(),
556 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
557 this));
560 void SetUp() override {
561 job_factory_.SetProtocolHandler("test", CreateProtocolHandler());
563 browser_context_.reset(new TestBrowserContext());
564 scoped_refptr<SiteInstance> site_instance =
565 SiteInstance::Create(browser_context_.get());
566 web_contents_.reset(
567 TestWebContents::Create(browser_context_.get(), site_instance.get()));
569 scoped_ptr<net::URLRequest> request(
570 resource_context_.GetRequestContext()->CreateRequest(
571 test_url(),
572 net::DEFAULT_PRIORITY,
573 nullptr /* delegate */));
574 SetUpResourceLoader(request.Pass());
577 void TearDown() override {
578 // Destroy the WebContents and pump the event loop before destroying
579 // |rvh_test_enabler_| and |thread_bundle_|. This lets asynchronous cleanup
580 // tasks complete.
581 web_contents_.reset();
582 base::RunLoop().RunUntilIdle();
585 // ResourceLoaderDelegate:
586 ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
587 ResourceLoader* loader,
588 net::AuthChallengeInfo* auth_info) override {
589 return NULL;
591 bool HandleExternalProtocol(ResourceLoader* loader,
592 const GURL& url) override {
593 return false;
595 void DidStartRequest(ResourceLoader* loader) override {}
596 void DidReceiveRedirect(ResourceLoader* loader,
597 const GURL& new_url) override {}
598 void DidReceiveResponse(ResourceLoader* loader) override {}
599 void DidFinishLoading(ResourceLoader* loader) override {}
601 TestBrowserThreadBundle thread_bundle_;
602 RenderViewHostTestEnabler rvh_test_enabler_;
604 net::URLRequestJobFactoryImpl job_factory_;
605 net::TestURLRequestContext test_url_request_context_;
606 ResourceContextStub resource_context_;
607 scoped_ptr<TestBrowserContext> browser_context_;
608 scoped_ptr<TestWebContents> web_contents_;
610 // The ResourceLoader owns the URLRequest and the ResourceHandler.
611 ResourceHandlerStub* raw_ptr_resource_handler_;
612 net::URLRequest* raw_ptr_to_request_;
613 scoped_ptr<ResourceLoader> loader_;
616 class ClientCertResourceLoaderTest : public ResourceLoaderTest {
617 protected:
618 net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler() override {
619 return new MockClientCertJobProtocolHandler;
623 // A ResourceLoaderTest that intercepts https://example.test and
624 // https://example-redirect.test URLs and sets SSL info on the
625 // responses. The latter serves a Location: header in the response.
626 class HTTPSSecurityInfoResourceLoaderTest : public ResourceLoaderTest {
627 public:
628 HTTPSSecurityInfoResourceLoaderTest()
629 : ResourceLoaderTest(),
630 test_https_url_("https://example.test"),
631 test_https_redirect_url_("https://example-redirect.test") {}
633 ~HTTPSSecurityInfoResourceLoaderTest() override {}
635 const GURL& test_https_url() const { return test_https_url_; }
636 const GURL& test_https_redirect_url() const {
637 return test_https_redirect_url_;
640 protected:
641 void SetUp() override {
642 ResourceLoaderTest::SetUp();
643 net::URLRequestFilter::GetInstance()->ClearHandlers();
644 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
645 "https", "example.test",
646 scoped_ptr<net::URLRequestInterceptor>(
647 new MockHTTPSJobURLRequestInterceptor(false /* redirect */)));
648 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
649 "https", "example-redirect.test",
650 scoped_ptr<net::URLRequestInterceptor>(
651 new MockHTTPSJobURLRequestInterceptor(true /* redirect */)));
654 private:
655 const GURL test_https_url_;
656 const GURL test_https_redirect_url_;
659 // Tests that client certificates are requested with ClientCertStore lookup.
660 TEST_F(ClientCertResourceLoaderTest, WithStoreLookup) {
661 // Set up the test client cert store.
662 int store_request_count;
663 std::vector<std::string> store_requested_authorities;
664 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
665 new net::X509Certificate("test", "test", base::Time(), base::Time())));
666 scoped_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub(
667 dummy_certs, &store_request_count, &store_requested_authorities));
668 resource_context_.SetClientCertStore(test_store.Pass());
670 // Plug in test content browser client.
671 SelectCertificateBrowserClient test_client;
672 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
674 // Start the request and wait for it to pause.
675 loader_->StartRequest();
676 base::RunLoop().RunUntilIdle();
678 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
680 // Check if the test store was queried against correct |cert_authorities|.
681 EXPECT_EQ(1, store_request_count);
682 EXPECT_EQ(MockClientCertURLRequestJob::test_authorities(),
683 store_requested_authorities);
685 // Check if the retrieved certificates were passed to the content browser
686 // client.
687 EXPECT_EQ(1, test_client.call_count());
688 EXPECT_EQ(dummy_certs, test_client.passed_certs());
690 // Continue the request.
691 test_client.ContinueWithCertificate(dummy_certs[0].get());
692 base::RunLoop().RunUntilIdle();
693 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
694 EXPECT_EQ(net::OK, raw_ptr_resource_handler_->status().error());
696 // Restore the original content browser client.
697 SetBrowserClientForTesting(old_client);
700 // Tests that client certificates are requested on a platform with NULL
701 // ClientCertStore.
702 TEST_F(ClientCertResourceLoaderTest, WithNullStore) {
703 // Plug in test content browser client.
704 SelectCertificateBrowserClient test_client;
705 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
707 // Start the request and wait for it to pause.
708 loader_->StartRequest();
709 base::RunLoop().RunUntilIdle();
711 // Check if the SelectClientCertificate was called on the content browser
712 // client.
713 EXPECT_EQ(1, test_client.call_count());
714 EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
716 // Continue the request.
717 scoped_refptr<net::X509Certificate> cert(
718 new net::X509Certificate("test", "test", base::Time(), base::Time()));
719 test_client.ContinueWithCertificate(cert.get());
720 base::RunLoop().RunUntilIdle();
721 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
722 EXPECT_EQ(net::OK, raw_ptr_resource_handler_->status().error());
724 // Restore the original content browser client.
725 SetBrowserClientForTesting(old_client);
728 // Tests that the ContentBrowserClient may cancel a certificate request.
729 TEST_F(ClientCertResourceLoaderTest, CancelSelection) {
730 // Plug in test content browser client.
731 SelectCertificateBrowserClient test_client;
732 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
734 // Start the request and wait for it to pause.
735 loader_->StartRequest();
736 base::RunLoop().RunUntilIdle();
738 // Check if the SelectClientCertificate was called on the content browser
739 // client.
740 EXPECT_EQ(1, test_client.call_count());
741 EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
743 // Cancel the request.
744 test_client.CancelCertificateSelection();
745 base::RunLoop().RunUntilIdle();
746 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
747 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
748 raw_ptr_resource_handler_->status().error());
750 // Restore the original content browser client.
751 SetBrowserClientForTesting(old_client);
754 // Verifies that requests without WebContents attached abort.
755 TEST_F(ClientCertResourceLoaderTest, NoWebContents) {
756 // Destroy the WebContents before starting the request.
757 web_contents_.reset();
759 // Plug in test content browser client.
760 SelectCertificateBrowserClient test_client;
761 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
763 // Start the request and wait for it to pause.
764 loader_->StartRequest();
765 base::RunLoop().RunUntilIdle();
767 // Check that SelectClientCertificate wasn't called and the request aborted.
768 EXPECT_EQ(0, test_client.call_count());
769 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
770 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
771 raw_ptr_resource_handler_->status().error());
773 // Restore the original content browser client.
774 SetBrowserClientForTesting(old_client);
777 // Verifies that ClientCertStore's callback doesn't crash if called after the
778 // loader is destroyed.
779 TEST_F(ClientCertResourceLoaderTest, StoreAsyncCancel) {
780 scoped_ptr<LoaderDestroyingCertStore> test_store(
781 new LoaderDestroyingCertStore(&loader_));
782 resource_context_.SetClientCertStore(test_store.Pass());
784 loader_->StartRequest();
785 base::RunLoop().RunUntilIdle();
786 EXPECT_FALSE(loader_);
788 // Pump the event loop to ensure nothing asynchronous crashes either.
789 base::RunLoop().RunUntilIdle();
792 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) {
793 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
795 loader_->StartRequest();
796 loader_->CancelRequest(true);
797 static_cast<ResourceController*>(loader_.get())->Resume();
800 // Tests that no invariants are broken if a ResourceHandler cancels during
801 // OnReadCompleted.
802 TEST_F(ResourceLoaderTest, CancelOnReadCompleted) {
803 raw_ptr_resource_handler_->set_cancel_on_read_completed(true);
805 loader_->StartRequest();
806 base::RunLoop().RunUntilIdle();
808 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
809 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
810 EXPECT_EQ(net::URLRequestStatus::CANCELED,
811 raw_ptr_resource_handler_->status().status());
814 // Tests that no invariants are broken if a ResourceHandler defers EOF.
815 TEST_F(ResourceLoaderTest, DeferEOF) {
816 raw_ptr_resource_handler_->set_defer_eof(true);
818 loader_->StartRequest();
819 base::RunLoop().RunUntilIdle();
821 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
822 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
824 raw_ptr_resource_handler_->Resume();
825 base::RunLoop().RunUntilIdle();
827 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
828 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
829 raw_ptr_resource_handler_->status().status());
832 // Tests that progress is reported correctly while uploading.
833 // TODO(andresantoso): Add test for the redirect case.
834 TEST_F(ResourceLoaderTest, UploadProgress) {
835 // Set up a test server.
836 net::test_server::EmbeddedTestServer server;
837 ASSERT_TRUE(server.InitializeAndWaitUntilReady());
838 base::FilePath path;
839 PathService::Get(content::DIR_TEST_DATA, &path);
840 server.ServeFilesFromDirectory(path);
842 scoped_ptr<net::URLRequest> request(
843 resource_context_.GetRequestContext()->CreateRequest(
844 server.GetURL("/title1.html"),
845 net::DEFAULT_PRIORITY,
846 nullptr /* delegate */));
848 // Start an upload.
849 auto stream = new NonChunkedUploadDataStream(10);
850 request->set_upload(make_scoped_ptr(stream));
852 SetUpResourceLoader(request.Pass());
853 loader_->StartRequest();
855 stream->AppendData("xx");
856 WaitForUploadProgress(2);
858 stream->AppendData("yyy");
859 WaitForUploadProgress(5);
861 stream->AppendData("zzzzz");
862 WaitForUploadProgress(10);
865 class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
866 public:
867 ResourceLoaderRedirectToFileTest()
868 : file_stream_(NULL),
869 redirect_to_file_resource_handler_(NULL) {
872 base::FilePath temp_path() const { return temp_path_; }
873 ShareableFileReference* deletable_file() const {
874 return deletable_file_.get();
876 net::testing::MockFileStream* file_stream() const { return file_stream_; }
877 RedirectToFileResourceHandler* redirect_to_file_resource_handler() const {
878 return redirect_to_file_resource_handler_;
881 void ReleaseLoader() {
882 file_stream_ = NULL;
883 deletable_file_ = NULL;
884 loader_.reset();
887 scoped_ptr<ResourceHandler> WrapResourceHandler(
888 scoped_ptr<ResourceHandlerStub> leaf_handler,
889 net::URLRequest* request) override {
890 leaf_handler->set_expect_reads(false);
892 // Make a temporary file.
893 CHECK(base::CreateTemporaryFile(&temp_path_));
894 int flags = base::File::FLAG_WRITE | base::File::FLAG_TEMPORARY |
895 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_ASYNC;
896 base::File file(temp_path_, flags);
897 CHECK(file.IsValid());
899 // Create mock file streams and a ShareableFileReference.
900 scoped_ptr<net::testing::MockFileStream> file_stream(
901 new net::testing::MockFileStream(file.Pass(),
902 base::ThreadTaskRunnerHandle::Get()));
903 file_stream_ = file_stream.get();
904 deletable_file_ = ShareableFileReference::GetOrCreate(
905 temp_path_,
906 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
907 BrowserThread::GetMessageLoopProxyForThread(
908 BrowserThread::FILE).get());
910 // Inject them into the handler.
911 scoped_ptr<RedirectToFileResourceHandler> handler(
912 new RedirectToFileResourceHandler(leaf_handler.Pass(), request));
913 redirect_to_file_resource_handler_ = handler.get();
914 handler->SetCreateTemporaryFileStreamFunctionForTesting(
915 base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback,
916 base::Unretained(this),
917 base::Passed(&file_stream)));
918 return handler.Pass();
921 private:
922 void PostCallback(
923 scoped_ptr<net::FileStream> file_stream,
924 const CreateTemporaryFileStreamCallback& callback) {
925 base::ThreadTaskRunnerHandle::Get()->PostTask(
926 FROM_HERE, base::Bind(callback, base::File::FILE_OK,
927 base::Passed(&file_stream), deletable_file_));
930 base::FilePath temp_path_;
931 scoped_refptr<ShareableFileReference> deletable_file_;
932 // These are owned by the ResourceLoader.
933 net::testing::MockFileStream* file_stream_;
934 RedirectToFileResourceHandler* redirect_to_file_resource_handler_;
937 // Tests that a RedirectToFileResourceHandler works and forwards everything
938 // downstream.
939 TEST_F(ResourceLoaderRedirectToFileTest, Basic) {
940 // Run it to completion.
941 loader_->StartRequest();
942 base::RunLoop().RunUntilIdle();
944 // Check that the handler forwarded all information to the downstream handler.
945 EXPECT_EQ(temp_path(),
946 raw_ptr_resource_handler_->response()->head.download_file_path);
947 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
948 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
949 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
950 raw_ptr_resource_handler_->status().status());
951 EXPECT_EQ(test_data().size(), static_cast<size_t>(
952 raw_ptr_resource_handler_->total_bytes_downloaded()));
954 // Check that the data was written to the file.
955 std::string contents;
956 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
957 EXPECT_EQ(test_data(), contents);
959 // Release the loader and the saved reference to file. The file should be gone
960 // now.
961 ReleaseLoader();
962 base::RunLoop().RunUntilIdle();
963 EXPECT_FALSE(base::PathExists(temp_path()));
966 // Tests that RedirectToFileResourceHandler handles errors in creating the
967 // temporary file.
968 TEST_F(ResourceLoaderRedirectToFileTest, CreateTemporaryError) {
969 // Swap out the create temporary function.
970 redirect_to_file_resource_handler()->
971 SetCreateTemporaryFileStreamFunctionForTesting(
972 base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED));
974 // Run it to completion.
975 loader_->StartRequest();
976 base::RunLoop().RunUntilIdle();
978 // To downstream, the request was canceled.
979 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
980 EXPECT_EQ(net::URLRequestStatus::CANCELED,
981 raw_ptr_resource_handler_->status().status());
982 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
985 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
986 TEST_F(ResourceLoaderRedirectToFileTest, WriteError) {
987 file_stream()->set_forced_error(net::ERR_FAILED);
989 // Run it to completion.
990 loader_->StartRequest();
991 base::RunLoop().RunUntilIdle();
993 // To downstream, the request was canceled sometime after it started, but
994 // before any data was written.
995 EXPECT_EQ(temp_path(),
996 raw_ptr_resource_handler_->response()->head.download_file_path);
997 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
998 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
999 EXPECT_EQ(net::URLRequestStatus::CANCELED,
1000 raw_ptr_resource_handler_->status().status());
1001 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
1003 // Release the loader. The file should be gone now.
1004 ReleaseLoader();
1005 base::RunLoop().RunUntilIdle();
1006 EXPECT_FALSE(base::PathExists(temp_path()));
1009 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
1010 TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) {
1011 file_stream()->set_forced_error_async(net::ERR_FAILED);
1013 // Run it to completion.
1014 loader_->StartRequest();
1015 base::RunLoop().RunUntilIdle();
1017 // To downstream, the request was canceled sometime after it started, but
1018 // before any data was written.
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_TRUE(raw_ptr_resource_handler_->received_response_completed());
1023 EXPECT_EQ(net::URLRequestStatus::CANCELED,
1024 raw_ptr_resource_handler_->status().status());
1025 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
1027 // Release the loader. The file should be gone now.
1028 ReleaseLoader();
1029 base::RunLoop().RunUntilIdle();
1030 EXPECT_FALSE(base::PathExists(temp_path()));
1033 // Tests that RedirectToFileHandler defers completion if there are outstanding
1034 // writes and accounts for errors which occur in that time.
1035 TEST_F(ResourceLoaderRedirectToFileTest, DeferCompletion) {
1036 // Program the MockFileStream to error asynchronously, but throttle the
1037 // callback.
1038 file_stream()->set_forced_error_async(net::ERR_FAILED);
1039 file_stream()->ThrottleCallbacks();
1041 // Run it as far as it will go.
1042 loader_->StartRequest();
1043 base::RunLoop().RunUntilIdle();
1045 // At this point, the request should have completed.
1046 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
1047 raw_ptr_to_request_->status().status());
1049 // However, the resource loader stack is stuck somewhere after receiving the
1050 // response.
1051 EXPECT_EQ(temp_path(),
1052 raw_ptr_resource_handler_->response()->head.download_file_path);
1053 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
1054 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
1055 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
1057 // Now, release the floodgates.
1058 file_stream()->ReleaseCallbacks();
1059 base::RunLoop().RunUntilIdle();
1061 // Although the URLRequest was successful, the leaf handler sees a failure
1062 // because the write never completed.
1063 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
1064 EXPECT_EQ(net::URLRequestStatus::CANCELED,
1065 raw_ptr_resource_handler_->status().status());
1067 // Release the loader. The file should be gone now.
1068 ReleaseLoader();
1069 base::RunLoop().RunUntilIdle();
1070 EXPECT_FALSE(base::PathExists(temp_path()));
1073 // Tests that a RedirectToFileResourceHandler behaves properly when the
1074 // downstream handler defers OnWillStart.
1075 TEST_F(ResourceLoaderRedirectToFileTest, DownstreamDeferStart) {
1076 // Defer OnWillStart.
1077 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
1079 // Run as far as we'll go.
1080 loader_->StartRequest();
1081 base::RunLoop().RunUntilIdle();
1083 // The request should have stopped at OnWillStart.
1084 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
1085 EXPECT_FALSE(raw_ptr_resource_handler_->response());
1086 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
1087 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
1089 // Now resume the request. Now we complete.
1090 raw_ptr_resource_handler_->Resume();
1091 base::RunLoop().RunUntilIdle();
1093 // Check that the handler forwarded all information to the downstream handler.
1094 EXPECT_EQ(temp_path(),
1095 raw_ptr_resource_handler_->response()->head.download_file_path);
1096 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
1097 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
1098 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
1099 raw_ptr_resource_handler_->status().status());
1100 EXPECT_EQ(test_data().size(), static_cast<size_t>(
1101 raw_ptr_resource_handler_->total_bytes_downloaded()));
1103 // Check that the data was written to the file.
1104 std::string contents;
1105 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
1106 EXPECT_EQ(test_data(), contents);
1108 // Release the loader. The file should be gone now.
1109 ReleaseLoader();
1110 base::RunLoop().RunUntilIdle();
1111 EXPECT_FALSE(base::PathExists(temp_path()));
1114 // Test that an HTTPS resource has the expected security info attached
1115 // to it.
1116 TEST_F(HTTPSSecurityInfoResourceLoaderTest, SecurityInfoOnHTTPSResource) {
1117 // Start the request and wait for it to finish.
1118 scoped_ptr<net::URLRequest> request(
1119 resource_context_.GetRequestContext()->CreateRequest(
1120 test_https_url(), net::DEFAULT_PRIORITY, nullptr /* delegate */));
1121 SetUpResourceLoader(request.Pass());
1123 // Send the request and wait until it completes.
1124 loader_->StartRequest();
1125 base::RunLoop().RunUntilIdle();
1126 ASSERT_EQ(net::URLRequestStatus::SUCCESS,
1127 raw_ptr_to_request_->status().status());
1128 ASSERT_TRUE(raw_ptr_resource_handler_->received_response_completed());
1130 ResourceResponse* response = raw_ptr_resource_handler_->response();
1131 ASSERT_TRUE(response);
1133 // Deserialize the security info from the response and check that it
1134 // is as expected.
1135 SSLStatus deserialized;
1136 ASSERT_TRUE(
1137 DeserializeSecurityInfo(response->head.security_info, &deserialized));
1139 // Expect a BROKEN security style because the cert status has errors.
1140 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN,
1141 deserialized.security_style);
1142 scoped_refptr<net::X509Certificate> cert;
1143 ASSERT_TRUE(
1144 CertStore::GetInstance()->RetrieveCert(deserialized.cert_id, &cert));
1145 EXPECT_TRUE(cert->Equals(GetTestCert().get()));
1147 EXPECT_EQ(kTestCertError, deserialized.cert_status);
1148 EXPECT_EQ(kTestConnectionStatus, deserialized.connection_status);
1149 EXPECT_EQ(kTestSecurityBits, deserialized.security_bits);
1152 // Test that an HTTPS redirect response has the expected security info
1153 // attached to it.
1154 TEST_F(HTTPSSecurityInfoResourceLoaderTest,
1155 SecurityInfoOnHTTPSRedirectResource) {
1156 // Start the request and wait for it to finish.
1157 scoped_ptr<net::URLRequest> request(
1158 resource_context_.GetRequestContext()->CreateRequest(
1159 test_https_redirect_url(), net::DEFAULT_PRIORITY,
1160 nullptr /* delegate */));
1161 SetUpResourceLoader(request.Pass());
1163 // Send the request and wait until it completes.
1164 loader_->StartRequest();
1165 base::RunLoop().RunUntilIdle();
1166 ASSERT_EQ(net::URLRequestStatus::SUCCESS,
1167 raw_ptr_to_request_->status().status());
1168 ASSERT_TRUE(raw_ptr_resource_handler_->received_response_completed());
1169 ASSERT_TRUE(raw_ptr_resource_handler_->received_request_redirected());
1171 ResourceResponse* redirect_response =
1172 raw_ptr_resource_handler_->redirect_response();
1173 ASSERT_TRUE(redirect_response);
1175 // Deserialize the security info from the redirect response and check
1176 // that it is as expected.
1177 SSLStatus deserialized;
1178 ASSERT_TRUE(DeserializeSecurityInfo(redirect_response->head.security_info,
1179 &deserialized));
1181 // Expect a BROKEN security style because the cert status has errors.
1182 EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN,
1183 deserialized.security_style);
1184 scoped_refptr<net::X509Certificate> cert;
1185 ASSERT_TRUE(
1186 CertStore::GetInstance()->RetrieveCert(deserialized.cert_id, &cert));
1187 EXPECT_TRUE(cert->Equals(GetTestCert().get()));
1189 EXPECT_EQ(kTestCertError, deserialized.cert_status);
1190 EXPECT_EQ(kTestConnectionStatus, deserialized.connection_status);
1191 EXPECT_EQ(kTestSecurityBits, deserialized.security_bits);
1194 } // namespace content