base/threading: remove ScopedTracker placed for experiments
[chromium-blink-merge.git] / content / browser / loader / resource_loader_unittest.cc
blob14ee69b784479c82f7f7ee209f2011214209e94c
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 class MockHTTPSJobURLRequestInterceptor : public net::URLRequestInterceptor {
216 public:
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 {
236 public:
237 explicit ResourceHandlerStub(net::URLRequest* request)
238 : ResourceHandler(request),
239 read_buffer_(new net::IOBuffer(kReadBufSize)),
240 defer_request_on_will_start_(false),
241 expect_reads_(true),
242 cancel_on_read_completed_(false),
243 defer_eof_(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_; }
276 void Resume() {
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();
295 return true;
298 bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
299 ResourceResponse* response,
300 bool* defer) override {
301 NOTREACHED();
302 return true;
305 bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
306 EXPECT_FALSE(response_.get());
307 response_ = response;
308 return true;
311 bool OnWillStart(const GURL& url, bool* defer) override {
312 EXPECT_TRUE(start_url_.is_empty());
313 start_url_ = url;
314 *defer = defer_request_on_will_start_;
315 return true;
318 bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
319 return true;
322 bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
323 int* buf_size,
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_);
330 *buf = read_buffer_;
331 *buf_size = kReadBufSize;
332 received_on_will_read_ = true;
333 return 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;
343 if (defer_eof_) {
344 defer_eof_ = false;
345 *defer = 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;
363 status_ = status;
366 void OnDataDownloaded(int bytes_downloaded) override {
367 EXPECT_FALSE(expect_reads_);
368 total_bytes_downloaded_ += bytes_downloaded;
371 private:
372 scoped_refptr<net::IOBuffer> read_buffer_;
374 bool defer_request_on_will_start_;
375 bool expect_reads_;
376 bool cancel_on_read_completed_;
377 bool defer_eof_;
379 GURL start_url_;
380 scoped_refptr<ResourceResponse> response_;
381 bool received_on_will_read_;
382 bool received_eof_;
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 {
393 public:
394 SelectCertificateBrowserClient() : call_count_(0) {}
396 void SelectClientCertificate(
397 WebContents* web_contents,
398 net::SSLCertRequestInfo* cert_request_info,
399 scoped_ptr<ClientCertificateDelegate> delegate) override {
400 ++call_count_;
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);
410 delegate_.reset();
413 void CancelCertificateSelection() { delegate_.reset(); }
415 private:
416 net::CertificateList passed_certs_;
417 int call_count_;
418 scoped_ptr<ClientCertificateDelegate> delegate_;
421 class ResourceContextStub : public MockResourceContext {
422 public:
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();
434 private:
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 {
441 public:
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);
449 private:
450 int InitInternal() override {
451 SetSize(size_);
452 stream_.Init(base::Bind(&NonChunkedUploadDataStream::OnInitCompleted,
453 base::Unretained(this)));
454 return net::OK;
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_;
466 uint64 size_;
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(
476 FROM_HERE,
477 base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
478 scoped_refptr<ShareableFileReference>()));
481 } // namespace
483 class ResourceLoaderTest : public testing::Test,
484 public ResourceLoaderDelegate {
485 protected:
486 ResourceLoaderTest()
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) {
502 while (true) {
503 uint64 position = raw_ptr_resource_handler_->WaitForUploadProgress();
504 EXPECT_LE(position, target_position);
505 loader_->OnUploadProgressACK();
506 if (position == target_position)
507 break;
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(
536 request.Pass(),
537 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
538 this));
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());
547 web_contents_.reset(
548 TestWebContents::Create(browser_context_.get(), site_instance.get()));
550 scoped_ptr<net::URLRequest> request(
551 resource_context_.GetRequestContext()->CreateRequest(
552 test_url(),
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
561 // tasks complete.
562 web_contents_.reset();
563 base::RunLoop().RunUntilIdle();
566 // ResourceLoaderDelegate:
567 ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
568 ResourceLoader* loader,
569 net::AuthChallengeInfo* auth_info) override {
570 return NULL;
572 bool HandleExternalProtocol(ResourceLoader* loader,
573 const GURL& url) override {
574 return false;
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 {
598 protected:
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 {
607 public:
608 HTTPSSecurityInfoResourceLoaderTest()
609 : ResourceLoaderTest(), test_https_url_("https://example.test") {}
611 ~HTTPSSecurityInfoResourceLoaderTest() override {}
613 const GURL& test_https_url() { return test_https_url_; }
615 protected:
616 void SetUp() override {
617 ResourceLoaderTest::SetUp();
618 net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
619 "https", "example.test", scoped_ptr<net::URLRequestInterceptor>(
620 new MockHTTPSJobURLRequestInterceptor));
623 private:
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
654 // client.
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
669 // ClientCertStore.
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
680 // client.
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
707 // client.
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
769 // OnReadCompleted.
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());
806 base::FilePath path;
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 */));
816 // Start an upload.
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 {
834 public:
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() {
850 file_stream_ = NULL;
851 deletable_file_ = NULL;
852 loader_.reset();
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(
873 temp_path_,
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();
889 private:
890 void PostCallback(
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
906 // downstream.
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
928 // now.
929 ReleaseLoader();
930 base::RunLoop().RunUntilIdle();
931 EXPECT_FALSE(base::PathExists(temp_path()));
934 // Tests that RedirectToFileResourceHandler handles errors in creating the
935 // temporary file.
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.
972 ReleaseLoader();
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.
996 ReleaseLoader();
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
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 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.
1036 ReleaseLoader();
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.
1077 ReleaseLoader();
1078 base::RunLoop().RunUntilIdle();
1079 EXPECT_FALSE(base::PathExists(temp_path()));
1082 // Test that an HTTPS resource has the expected security info attached
1083 // to it.
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
1102 // is as expected.
1103 SSLStatus deserialized;
1104 ASSERT_TRUE(
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;
1111 ASSERT_TRUE(
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