Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / content / browser / loader / resource_loader_unittest.cc
blob7b4000e3e3344ff3dbb4114d3b5eae8c2c5f3c6c
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/public/browser/client_certificate_delegate.h"
18 #include "content/public/browser/resource_request_info.h"
19 #include "content/public/common/content_paths.h"
20 #include "content/public/common/resource_response.h"
21 #include "content/public/test/mock_resource_context.h"
22 #include "content/public/test/test_browser_context.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "content/public/test/test_renderer_host.h"
25 #include "content/test/test_content_browser_client.h"
26 #include "content/test/test_web_contents.h"
27 #include "ipc/ipc_message.h"
28 #include "net/base/chunked_upload_data_stream.h"
29 #include "net/base/io_buffer.h"
30 #include "net/base/mock_file_stream.h"
31 #include "net/base/net_errors.h"
32 #include "net/base/request_priority.h"
33 #include "net/base/upload_bytes_element_reader.h"
34 #include "net/cert/x509_certificate.h"
35 #include "net/ssl/client_cert_store.h"
36 #include "net/ssl/ssl_cert_request_info.h"
37 #include "net/test/embedded_test_server/embedded_test_server.h"
38 #include "net/url_request/url_request.h"
39 #include "net/url_request/url_request_job_factory.h"
40 #include "net/url_request/url_request_job_factory_impl.h"
41 #include "net/url_request/url_request_test_job.h"
42 #include "net/url_request/url_request_test_util.h"
43 #include "storage/browser/blob/shareable_file_reference.h"
44 #include "testing/gtest/include/gtest/gtest.h"
46 using storage::ShareableFileReference;
48 namespace content {
49 namespace {
51 // Stub client certificate store that returns a preset list of certificates for
52 // each request and records the arguments of the most recent request for later
53 // inspection.
54 class ClientCertStoreStub : public net::ClientCertStore {
55 public:
56 // Creates a new ClientCertStoreStub that returns |response| on query. It
57 // saves the number of requests and most recently certificate authorities list
58 // in |requested_authorities| and |request_count|, respectively. The caller is
59 // responsible for ensuring those pointers outlive the ClientCertStoreStub.
61 // TODO(ppi): Make the stub independent from the internal representation of
62 // SSLCertRequestInfo. For now it seems that we can neither save the
63 // scoped_refptr<> (since it is never passed to us) nor copy the entire
64 // CertificateRequestInfo (since there is no copy constructor).
65 ClientCertStoreStub(const net::CertificateList& response,
66 int* request_count,
67 std::vector<std::string>* requested_authorities)
68 : response_(response),
69 requested_authorities_(requested_authorities),
70 request_count_(request_count) {
71 requested_authorities_->clear();
72 *request_count_ = 0;
75 ~ClientCertStoreStub() override {}
77 // net::ClientCertStore:
78 void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
79 net::CertificateList* selected_certs,
80 const base::Closure& callback) override {
81 *requested_authorities_ = cert_request_info.cert_authorities;
82 ++(*request_count_);
84 *selected_certs = response_;
85 callback.Run();
88 private:
89 const net::CertificateList response_;
90 std::vector<std::string>* requested_authorities_;
91 int* request_count_;
94 // Client certificate store which destroys its resource loader before the
95 // asynchronous GetClientCerts callback is called.
96 class LoaderDestroyingCertStore : public net::ClientCertStore {
97 public:
98 // Creates a client certificate store which, when looked up, posts a task to
99 // reset |loader| and then call the callback. The caller is responsible for
100 // ensuring the pointers remain valid until the process is complete.
101 explicit LoaderDestroyingCertStore(scoped_ptr<ResourceLoader>* loader)
102 : loader_(loader) {}
104 // net::ClientCertStore:
105 void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
106 net::CertificateList* selected_certs,
107 const base::Closure& callback) override {
108 // Don't destroy |loader_| while it's on the stack.
109 base::ThreadTaskRunnerHandle::Get()->PostTask(
110 FROM_HERE, base::Bind(&LoaderDestroyingCertStore::DoCallback,
111 base::Unretained(loader_), callback));
114 private:
115 static void DoCallback(scoped_ptr<ResourceLoader>* loader,
116 const base::Closure& callback) {
117 loader->reset();
118 callback.Run();
121 scoped_ptr<ResourceLoader>* loader_;
124 // A mock URLRequestJob which simulates an SSL client auth request.
125 class MockClientCertURLRequestJob : public net::URLRequestTestJob {
126 public:
127 MockClientCertURLRequestJob(net::URLRequest* request,
128 net::NetworkDelegate* network_delegate)
129 : net::URLRequestTestJob(request, network_delegate) {}
131 static std::vector<std::string> test_authorities() {
132 return std::vector<std::string>(1, "dummy");
135 // net::URLRequestTestJob:
136 void Start() override {
137 scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
138 new net::SSLCertRequestInfo);
139 cert_request_info->cert_authorities = test_authorities();
140 base::ThreadTaskRunnerHandle::Get()->PostTask(
141 FROM_HERE,
142 base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
143 this, cert_request_info));
146 void ContinueWithCertificate(net::X509Certificate* cert) override {
147 net::URLRequestTestJob::Start();
150 private:
151 ~MockClientCertURLRequestJob() override {}
153 DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob);
156 class MockClientCertJobProtocolHandler
157 : public net::URLRequestJobFactory::ProtocolHandler {
158 public:
159 // URLRequestJobFactory::ProtocolHandler implementation:
160 net::URLRequestJob* MaybeCreateJob(
161 net::URLRequest* request,
162 net::NetworkDelegate* network_delegate) const override {
163 return new MockClientCertURLRequestJob(request, network_delegate);
167 // Arbitrary read buffer size.
168 const int kReadBufSize = 1024;
170 // Dummy implementation of ResourceHandler, instance of which is needed to
171 // initialize ResourceLoader.
172 class ResourceHandlerStub : public ResourceHandler {
173 public:
174 explicit ResourceHandlerStub(net::URLRequest* request)
175 : ResourceHandler(request),
176 read_buffer_(new net::IOBuffer(kReadBufSize)),
177 defer_request_on_will_start_(false),
178 expect_reads_(true),
179 cancel_on_read_completed_(false),
180 defer_eof_(false),
181 received_on_will_read_(false),
182 received_eof_(false),
183 received_response_completed_(false),
184 total_bytes_downloaded_(0),
185 upload_position_(0) {
188 // If true, defers the resource load in OnWillStart.
189 void set_defer_request_on_will_start(bool defer_request_on_will_start) {
190 defer_request_on_will_start_ = defer_request_on_will_start;
193 // If true, expect OnWillRead / OnReadCompleted pairs for handling
194 // data. Otherwise, expect OnDataDownloaded.
195 void set_expect_reads(bool expect_reads) { expect_reads_ = expect_reads; }
197 // If true, cancel the request in OnReadCompleted by returning false.
198 void set_cancel_on_read_completed(bool cancel_on_read_completed) {
199 cancel_on_read_completed_ = cancel_on_read_completed;
202 // If true, cancel the request in OnReadCompleted by returning false.
203 void set_defer_eof(bool defer_eof) { defer_eof_ = defer_eof; }
205 const GURL& start_url() const { return start_url_; }
206 ResourceResponse* response() const { return response_.get(); }
207 bool received_response_completed() const {
208 return received_response_completed_;
210 const net::URLRequestStatus& status() const { return status_; }
211 int total_bytes_downloaded() const { return total_bytes_downloaded_; }
213 void Resume() {
214 controller()->Resume();
217 // Waits until OnUploadProgress is called and returns the upload position.
218 uint64 WaitForUploadProgress() {
219 wait_for_progress_loop_.reset(new base::RunLoop());
220 wait_for_progress_loop_->Run();
221 wait_for_progress_loop_.reset();
222 return upload_position_;
225 // ResourceHandler implementation:
226 bool OnUploadProgress(uint64 position, uint64 size) override {
227 EXPECT_LE(position, size);
228 EXPECT_GT(position, upload_position_);
229 upload_position_ = position;
230 if (wait_for_progress_loop_)
231 wait_for_progress_loop_->Quit();
232 return true;
235 bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
236 ResourceResponse* response,
237 bool* defer) override {
238 NOTREACHED();
239 return true;
242 bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
243 EXPECT_FALSE(response_.get());
244 response_ = response;
245 return true;
248 bool OnWillStart(const GURL& url, bool* defer) override {
249 EXPECT_TRUE(start_url_.is_empty());
250 start_url_ = url;
251 *defer = defer_request_on_will_start_;
252 return true;
255 bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
256 return true;
259 bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
260 int* buf_size,
261 int min_size) override {
262 EXPECT_TRUE(expect_reads_);
263 EXPECT_FALSE(received_on_will_read_);
264 EXPECT_FALSE(received_eof_);
265 EXPECT_FALSE(received_response_completed_);
267 *buf = read_buffer_;
268 *buf_size = kReadBufSize;
269 received_on_will_read_ = true;
270 return true;
273 bool OnReadCompleted(int bytes_read, bool* defer) override {
274 EXPECT_TRUE(received_on_will_read_);
275 EXPECT_TRUE(expect_reads_);
276 EXPECT_FALSE(received_response_completed_);
278 if (bytes_read == 0) {
279 received_eof_ = true;
280 if (defer_eof_) {
281 defer_eof_ = false;
282 *defer = true;
286 // Need another OnWillRead() call before seeing an OnReadCompleted().
287 received_on_will_read_ = false;
289 return !cancel_on_read_completed_;
292 void OnResponseCompleted(const net::URLRequestStatus& status,
293 const std::string& security_info,
294 bool* defer) override {
295 EXPECT_FALSE(received_response_completed_);
296 if (status.is_success() && expect_reads_)
297 EXPECT_TRUE(received_eof_);
299 received_response_completed_ = true;
300 status_ = status;
303 void OnDataDownloaded(int bytes_downloaded) override {
304 EXPECT_FALSE(expect_reads_);
305 total_bytes_downloaded_ += bytes_downloaded;
308 private:
309 scoped_refptr<net::IOBuffer> read_buffer_;
311 bool defer_request_on_will_start_;
312 bool expect_reads_;
313 bool cancel_on_read_completed_;
314 bool defer_eof_;
316 GURL start_url_;
317 scoped_refptr<ResourceResponse> response_;
318 bool received_on_will_read_;
319 bool received_eof_;
320 bool received_response_completed_;
321 net::URLRequestStatus status_;
322 int total_bytes_downloaded_;
323 scoped_ptr<base::RunLoop> wait_for_progress_loop_;
324 uint64 upload_position_;
327 // Test browser client that captures calls to SelectClientCertificates and
328 // records the arguments of the most recent call for later inspection.
329 class SelectCertificateBrowserClient : public TestContentBrowserClient {
330 public:
331 SelectCertificateBrowserClient() : call_count_(0) {}
333 void SelectClientCertificate(
334 WebContents* web_contents,
335 net::SSLCertRequestInfo* cert_request_info,
336 scoped_ptr<ClientCertificateDelegate> delegate) override {
337 ++call_count_;
338 passed_certs_ = cert_request_info->client_certs;
339 delegate_ = delegate.Pass();
342 int call_count() { return call_count_; }
343 net::CertificateList passed_certs() { return passed_certs_; }
345 void ContinueWithCertificate(net::X509Certificate* cert) {
346 delegate_->ContinueWithCertificate(cert);
347 delegate_.reset();
350 void CancelCertificateSelection() { delegate_.reset(); }
352 private:
353 net::CertificateList passed_certs_;
354 int call_count_;
355 scoped_ptr<ClientCertificateDelegate> delegate_;
358 class ResourceContextStub : public MockResourceContext {
359 public:
360 explicit ResourceContextStub(net::URLRequestContext* test_request_context)
361 : MockResourceContext(test_request_context) {}
363 scoped_ptr<net::ClientCertStore> CreateClientCertStore() override {
364 return dummy_cert_store_.Pass();
367 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
368 dummy_cert_store_ = store.Pass();
371 private:
372 scoped_ptr<net::ClientCertStore> dummy_cert_store_;
375 // Wraps a ChunkedUploadDataStream to behave as non-chunked to enable upload
376 // progress reporting.
377 class NonChunkedUploadDataStream : public net::UploadDataStream {
378 public:
379 explicit NonChunkedUploadDataStream(uint64 size)
380 : net::UploadDataStream(false, 0), stream_(0), size_(size) {}
382 void AppendData(const char* data) {
383 stream_.AppendData(data, strlen(data), false);
386 private:
387 int InitInternal() override {
388 SetSize(size_);
389 stream_.Init(base::Bind(&NonChunkedUploadDataStream::OnInitCompleted,
390 base::Unretained(this)));
391 return net::OK;
394 int ReadInternal(net::IOBuffer* buf, int buf_len) override {
395 return stream_.Read(buf, buf_len,
396 base::Bind(&NonChunkedUploadDataStream::OnReadCompleted,
397 base::Unretained(this)));
400 void ResetInternal() override { stream_.Reset(); }
402 net::ChunkedUploadDataStream stream_;
403 uint64 size_;
405 DISALLOW_COPY_AND_ASSIGN(NonChunkedUploadDataStream);
408 // Fails to create a temporary file with the given error.
409 void CreateTemporaryError(
410 base::File::Error error,
411 const CreateTemporaryFileStreamCallback& callback) {
412 base::ThreadTaskRunnerHandle::Get()->PostTask(
413 FROM_HERE,
414 base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
415 scoped_refptr<ShareableFileReference>()));
418 } // namespace
420 class ResourceLoaderTest : public testing::Test,
421 public ResourceLoaderDelegate {
422 protected:
423 ResourceLoaderTest()
424 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
425 resource_context_(&test_url_request_context_),
426 raw_ptr_resource_handler_(NULL),
427 raw_ptr_to_request_(NULL) {
428 test_url_request_context_.set_job_factory(&job_factory_);
431 GURL test_url() const { return net::URLRequestTestJob::test_url_1(); }
433 std::string test_data() const {
434 return net::URLRequestTestJob::test_data_1();
437 // Waits until upload progress reaches |target_position|
438 void WaitForUploadProgress(uint64 target_position) {
439 while (true) {
440 uint64 position = raw_ptr_resource_handler_->WaitForUploadProgress();
441 EXPECT_LE(position, target_position);
442 loader_->OnUploadProgressACK();
443 if (position == target_position)
444 break;
448 virtual net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler() {
449 return net::URLRequestTestJob::CreateProtocolHandler();
452 virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
453 scoped_ptr<ResourceHandlerStub> leaf_handler,
454 net::URLRequest* request) {
455 return leaf_handler.Pass();
458 // Replaces loader_ with a new one for |request|.
459 void SetUpResourceLoader(scoped_ptr<net::URLRequest> request) {
460 raw_ptr_to_request_ = request.get();
462 RenderFrameHost* rfh = web_contents_->GetMainFrame();
463 ResourceRequestInfo::AllocateForTesting(
464 request.get(), RESOURCE_TYPE_MAIN_FRAME, &resource_context_,
465 rfh->GetProcess()->GetID(), rfh->GetRenderViewHost()->GetRoutingID(),
466 rfh->GetRoutingID(), true /* is_main_frame */,
467 false /* parent_is_main_frame */, true /* allow_download */,
468 false /* is_async */);
469 scoped_ptr<ResourceHandlerStub> resource_handler(
470 new ResourceHandlerStub(request.get()));
471 raw_ptr_resource_handler_ = resource_handler.get();
472 loader_.reset(new ResourceLoader(
473 request.Pass(),
474 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
475 this));
478 void SetUp() override {
479 job_factory_.SetProtocolHandler("test", CreateProtocolHandler());
481 browser_context_.reset(new TestBrowserContext());
482 scoped_refptr<SiteInstance> site_instance =
483 SiteInstance::Create(browser_context_.get());
484 web_contents_.reset(
485 TestWebContents::Create(browser_context_.get(), site_instance.get()));
487 scoped_ptr<net::URLRequest> request(
488 resource_context_.GetRequestContext()->CreateRequest(
489 test_url(),
490 net::DEFAULT_PRIORITY,
491 nullptr /* delegate */));
492 SetUpResourceLoader(request.Pass());
495 void TearDown() override {
496 // Destroy the WebContents and pump the event loop before destroying
497 // |rvh_test_enabler_| and |thread_bundle_|. This lets asynchronous cleanup
498 // tasks complete.
499 web_contents_.reset();
500 base::RunLoop().RunUntilIdle();
503 // ResourceLoaderDelegate:
504 ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
505 ResourceLoader* loader,
506 net::AuthChallengeInfo* auth_info) override {
507 return NULL;
509 bool HandleExternalProtocol(ResourceLoader* loader,
510 const GURL& url) override {
511 return false;
513 void DidStartRequest(ResourceLoader* loader) override {}
514 void DidReceiveRedirect(ResourceLoader* loader,
515 const GURL& new_url) override {}
516 void DidReceiveResponse(ResourceLoader* loader) override {}
517 void DidFinishLoading(ResourceLoader* loader) override {}
519 TestBrowserThreadBundle thread_bundle_;
520 RenderViewHostTestEnabler rvh_test_enabler_;
522 net::URLRequestJobFactoryImpl job_factory_;
523 net::TestURLRequestContext test_url_request_context_;
524 ResourceContextStub resource_context_;
525 scoped_ptr<TestBrowserContext> browser_context_;
526 scoped_ptr<TestWebContents> web_contents_;
528 // The ResourceLoader owns the URLRequest and the ResourceHandler.
529 ResourceHandlerStub* raw_ptr_resource_handler_;
530 net::URLRequest* raw_ptr_to_request_;
531 scoped_ptr<ResourceLoader> loader_;
534 class ClientCertResourceLoaderTest : public ResourceLoaderTest {
535 protected:
536 net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler() override {
537 return new MockClientCertJobProtocolHandler;
541 // Tests that client certificates are requested with ClientCertStore lookup.
542 TEST_F(ClientCertResourceLoaderTest, WithStoreLookup) {
543 // Set up the test client cert store.
544 int store_request_count;
545 std::vector<std::string> store_requested_authorities;
546 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
547 new net::X509Certificate("test", "test", base::Time(), base::Time())));
548 scoped_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub(
549 dummy_certs, &store_request_count, &store_requested_authorities));
550 resource_context_.SetClientCertStore(test_store.Pass());
552 // Plug in test content browser client.
553 SelectCertificateBrowserClient test_client;
554 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
556 // Start the request and wait for it to pause.
557 loader_->StartRequest();
558 base::RunLoop().RunUntilIdle();
560 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
562 // Check if the test store was queried against correct |cert_authorities|.
563 EXPECT_EQ(1, store_request_count);
564 EXPECT_EQ(MockClientCertURLRequestJob::test_authorities(),
565 store_requested_authorities);
567 // Check if the retrieved certificates were passed to the content browser
568 // client.
569 EXPECT_EQ(1, test_client.call_count());
570 EXPECT_EQ(dummy_certs, test_client.passed_certs());
572 // Continue the request.
573 test_client.ContinueWithCertificate(dummy_certs[0].get());
574 base::RunLoop().RunUntilIdle();
575 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
576 EXPECT_EQ(net::OK, raw_ptr_resource_handler_->status().error());
578 // Restore the original content browser client.
579 SetBrowserClientForTesting(old_client);
582 // Tests that client certificates are requested on a platform with NULL
583 // ClientCertStore.
584 TEST_F(ClientCertResourceLoaderTest, WithNullStore) {
585 // Plug in test content browser client.
586 SelectCertificateBrowserClient test_client;
587 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
589 // Start the request and wait for it to pause.
590 loader_->StartRequest();
591 base::RunLoop().RunUntilIdle();
593 // Check if the SelectClientCertificate was called on the content browser
594 // client.
595 EXPECT_EQ(1, test_client.call_count());
596 EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
598 // Continue the request.
599 scoped_refptr<net::X509Certificate> cert(
600 new net::X509Certificate("test", "test", base::Time(), base::Time()));
601 test_client.ContinueWithCertificate(cert.get());
602 base::RunLoop().RunUntilIdle();
603 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
604 EXPECT_EQ(net::OK, raw_ptr_resource_handler_->status().error());
606 // Restore the original content browser client.
607 SetBrowserClientForTesting(old_client);
610 // Tests that the ContentBrowserClient may cancel a certificate request.
611 TEST_F(ClientCertResourceLoaderTest, CancelSelection) {
612 // Plug in test content browser client.
613 SelectCertificateBrowserClient test_client;
614 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
616 // Start the request and wait for it to pause.
617 loader_->StartRequest();
618 base::RunLoop().RunUntilIdle();
620 // Check if the SelectClientCertificate was called on the content browser
621 // client.
622 EXPECT_EQ(1, test_client.call_count());
623 EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
625 // Cancel the request.
626 test_client.CancelCertificateSelection();
627 base::RunLoop().RunUntilIdle();
628 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
629 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
630 raw_ptr_resource_handler_->status().error());
632 // Restore the original content browser client.
633 SetBrowserClientForTesting(old_client);
636 // Verifies that requests without WebContents attached abort.
637 TEST_F(ClientCertResourceLoaderTest, NoWebContents) {
638 // Destroy the WebContents before starting the request.
639 web_contents_.reset();
641 // Plug in test content browser client.
642 SelectCertificateBrowserClient test_client;
643 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
645 // Start the request and wait for it to pause.
646 loader_->StartRequest();
647 base::RunLoop().RunUntilIdle();
649 // Check that SelectClientCertificate wasn't called and the request aborted.
650 EXPECT_EQ(0, test_client.call_count());
651 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
652 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
653 raw_ptr_resource_handler_->status().error());
655 // Restore the original content browser client.
656 SetBrowserClientForTesting(old_client);
659 // Verifies that ClientCertStore's callback doesn't crash if called after the
660 // loader is destroyed.
661 TEST_F(ClientCertResourceLoaderTest, StoreAsyncCancel) {
662 scoped_ptr<LoaderDestroyingCertStore> test_store(
663 new LoaderDestroyingCertStore(&loader_));
664 resource_context_.SetClientCertStore(test_store.Pass());
666 loader_->StartRequest();
667 base::RunLoop().RunUntilIdle();
668 EXPECT_FALSE(loader_);
670 // Pump the event loop to ensure nothing asynchronous crashes either.
671 base::RunLoop().RunUntilIdle();
674 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) {
675 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
677 loader_->StartRequest();
678 loader_->CancelRequest(true);
679 static_cast<ResourceController*>(loader_.get())->Resume();
682 // Tests that no invariants are broken if a ResourceHandler cancels during
683 // OnReadCompleted.
684 TEST_F(ResourceLoaderTest, CancelOnReadCompleted) {
685 raw_ptr_resource_handler_->set_cancel_on_read_completed(true);
687 loader_->StartRequest();
688 base::RunLoop().RunUntilIdle();
690 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
691 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
692 EXPECT_EQ(net::URLRequestStatus::CANCELED,
693 raw_ptr_resource_handler_->status().status());
696 // Tests that no invariants are broken if a ResourceHandler defers EOF.
697 TEST_F(ResourceLoaderTest, DeferEOF) {
698 raw_ptr_resource_handler_->set_defer_eof(true);
700 loader_->StartRequest();
701 base::RunLoop().RunUntilIdle();
703 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
704 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
706 raw_ptr_resource_handler_->Resume();
707 base::RunLoop().RunUntilIdle();
709 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
710 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
711 raw_ptr_resource_handler_->status().status());
714 // Tests that progress is reported correctly while uploading.
715 // TODO(andresantoso): Add test for the redirect case.
716 TEST_F(ResourceLoaderTest, UploadProgress) {
717 // Set up a test server.
718 net::test_server::EmbeddedTestServer server;
719 ASSERT_TRUE(server.InitializeAndWaitUntilReady());
720 base::FilePath path;
721 PathService::Get(content::DIR_TEST_DATA, &path);
722 server.ServeFilesFromDirectory(path);
724 scoped_ptr<net::URLRequest> request(
725 resource_context_.GetRequestContext()->CreateRequest(
726 server.GetURL("/title1.html"),
727 net::DEFAULT_PRIORITY,
728 nullptr /* delegate */));
730 // Start an upload.
731 auto stream = new NonChunkedUploadDataStream(10);
732 request->set_upload(make_scoped_ptr(stream));
734 SetUpResourceLoader(request.Pass());
735 loader_->StartRequest();
737 stream->AppendData("xx");
738 WaitForUploadProgress(2);
740 stream->AppendData("yyy");
741 WaitForUploadProgress(5);
743 stream->AppendData("zzzzz");
744 WaitForUploadProgress(10);
747 class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
748 public:
749 ResourceLoaderRedirectToFileTest()
750 : file_stream_(NULL),
751 redirect_to_file_resource_handler_(NULL) {
754 base::FilePath temp_path() const { return temp_path_; }
755 ShareableFileReference* deletable_file() const {
756 return deletable_file_.get();
758 net::testing::MockFileStream* file_stream() const { return file_stream_; }
759 RedirectToFileResourceHandler* redirect_to_file_resource_handler() const {
760 return redirect_to_file_resource_handler_;
763 void ReleaseLoader() {
764 file_stream_ = NULL;
765 deletable_file_ = NULL;
766 loader_.reset();
769 scoped_ptr<ResourceHandler> WrapResourceHandler(
770 scoped_ptr<ResourceHandlerStub> leaf_handler,
771 net::URLRequest* request) override {
772 leaf_handler->set_expect_reads(false);
774 // Make a temporary file.
775 CHECK(base::CreateTemporaryFile(&temp_path_));
776 int flags = base::File::FLAG_WRITE | base::File::FLAG_TEMPORARY |
777 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_ASYNC;
778 base::File file(temp_path_, flags);
779 CHECK(file.IsValid());
781 // Create mock file streams and a ShareableFileReference.
782 scoped_ptr<net::testing::MockFileStream> file_stream(
783 new net::testing::MockFileStream(file.Pass(),
784 base::ThreadTaskRunnerHandle::Get()));
785 file_stream_ = file_stream.get();
786 deletable_file_ = ShareableFileReference::GetOrCreate(
787 temp_path_,
788 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
789 BrowserThread::GetMessageLoopProxyForThread(
790 BrowserThread::FILE).get());
792 // Inject them into the handler.
793 scoped_ptr<RedirectToFileResourceHandler> handler(
794 new RedirectToFileResourceHandler(leaf_handler.Pass(), request));
795 redirect_to_file_resource_handler_ = handler.get();
796 handler->SetCreateTemporaryFileStreamFunctionForTesting(
797 base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback,
798 base::Unretained(this),
799 base::Passed(&file_stream)));
800 return handler.Pass();
803 private:
804 void PostCallback(
805 scoped_ptr<net::FileStream> file_stream,
806 const CreateTemporaryFileStreamCallback& callback) {
807 base::ThreadTaskRunnerHandle::Get()->PostTask(
808 FROM_HERE, base::Bind(callback, base::File::FILE_OK,
809 base::Passed(&file_stream), deletable_file_));
812 base::FilePath temp_path_;
813 scoped_refptr<ShareableFileReference> deletable_file_;
814 // These are owned by the ResourceLoader.
815 net::testing::MockFileStream* file_stream_;
816 RedirectToFileResourceHandler* redirect_to_file_resource_handler_;
819 // Tests that a RedirectToFileResourceHandler works and forwards everything
820 // downstream.
821 TEST_F(ResourceLoaderRedirectToFileTest, Basic) {
822 // Run it to completion.
823 loader_->StartRequest();
824 base::RunLoop().RunUntilIdle();
826 // Check that the handler forwarded all information to the downstream handler.
827 EXPECT_EQ(temp_path(),
828 raw_ptr_resource_handler_->response()->head.download_file_path);
829 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
830 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
831 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
832 raw_ptr_resource_handler_->status().status());
833 EXPECT_EQ(test_data().size(), static_cast<size_t>(
834 raw_ptr_resource_handler_->total_bytes_downloaded()));
836 // Check that the data was written to the file.
837 std::string contents;
838 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
839 EXPECT_EQ(test_data(), contents);
841 // Release the loader and the saved reference to file. The file should be gone
842 // now.
843 ReleaseLoader();
844 base::RunLoop().RunUntilIdle();
845 EXPECT_FALSE(base::PathExists(temp_path()));
848 // Tests that RedirectToFileResourceHandler handles errors in creating the
849 // temporary file.
850 TEST_F(ResourceLoaderRedirectToFileTest, CreateTemporaryError) {
851 // Swap out the create temporary function.
852 redirect_to_file_resource_handler()->
853 SetCreateTemporaryFileStreamFunctionForTesting(
854 base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED));
856 // Run it to completion.
857 loader_->StartRequest();
858 base::RunLoop().RunUntilIdle();
860 // To downstream, the request was canceled.
861 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
862 EXPECT_EQ(net::URLRequestStatus::CANCELED,
863 raw_ptr_resource_handler_->status().status());
864 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
867 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
868 TEST_F(ResourceLoaderRedirectToFileTest, WriteError) {
869 file_stream()->set_forced_error(net::ERR_FAILED);
871 // Run it to completion.
872 loader_->StartRequest();
873 base::RunLoop().RunUntilIdle();
875 // To downstream, the request was canceled sometime after it started, but
876 // before any data was written.
877 EXPECT_EQ(temp_path(),
878 raw_ptr_resource_handler_->response()->head.download_file_path);
879 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
880 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
881 EXPECT_EQ(net::URLRequestStatus::CANCELED,
882 raw_ptr_resource_handler_->status().status());
883 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
885 // Release the loader. The file should be gone now.
886 ReleaseLoader();
887 base::RunLoop().RunUntilIdle();
888 EXPECT_FALSE(base::PathExists(temp_path()));
891 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
892 TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) {
893 file_stream()->set_forced_error_async(net::ERR_FAILED);
895 // Run it to completion.
896 loader_->StartRequest();
897 base::RunLoop().RunUntilIdle();
899 // To downstream, the request was canceled sometime after it started, but
900 // before any data was written.
901 EXPECT_EQ(temp_path(),
902 raw_ptr_resource_handler_->response()->head.download_file_path);
903 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
904 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
905 EXPECT_EQ(net::URLRequestStatus::CANCELED,
906 raw_ptr_resource_handler_->status().status());
907 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
909 // Release the loader. The file should be gone now.
910 ReleaseLoader();
911 base::RunLoop().RunUntilIdle();
912 EXPECT_FALSE(base::PathExists(temp_path()));
915 // Tests that RedirectToFileHandler defers completion if there are outstanding
916 // writes and accounts for errors which occur in that time.
917 TEST_F(ResourceLoaderRedirectToFileTest, DeferCompletion) {
918 // Program the MockFileStream to error asynchronously, but throttle the
919 // callback.
920 file_stream()->set_forced_error_async(net::ERR_FAILED);
921 file_stream()->ThrottleCallbacks();
923 // Run it as far as it will go.
924 loader_->StartRequest();
925 base::RunLoop().RunUntilIdle();
927 // At this point, the request should have completed.
928 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
929 raw_ptr_to_request_->status().status());
931 // However, the resource loader stack is stuck somewhere after receiving the
932 // response.
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_FALSE(raw_ptr_resource_handler_->received_response_completed());
937 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
939 // Now, release the floodgates.
940 file_stream()->ReleaseCallbacks();
941 base::RunLoop().RunUntilIdle();
943 // Although the URLRequest was successful, the leaf handler sees a failure
944 // because the write never completed.
945 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
946 EXPECT_EQ(net::URLRequestStatus::CANCELED,
947 raw_ptr_resource_handler_->status().status());
949 // Release the loader. The file should be gone now.
950 ReleaseLoader();
951 base::RunLoop().RunUntilIdle();
952 EXPECT_FALSE(base::PathExists(temp_path()));
955 // Tests that a RedirectToFileResourceHandler behaves properly when the
956 // downstream handler defers OnWillStart.
957 TEST_F(ResourceLoaderRedirectToFileTest, DownstreamDeferStart) {
958 // Defer OnWillStart.
959 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
961 // Run as far as we'll go.
962 loader_->StartRequest();
963 base::RunLoop().RunUntilIdle();
965 // The request should have stopped at OnWillStart.
966 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
967 EXPECT_FALSE(raw_ptr_resource_handler_->response());
968 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
969 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
971 // Now resume the request. Now we complete.
972 raw_ptr_resource_handler_->Resume();
973 base::RunLoop().RunUntilIdle();
975 // Check that the handler forwarded all information to the downstream handler.
976 EXPECT_EQ(temp_path(),
977 raw_ptr_resource_handler_->response()->head.download_file_path);
978 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
979 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
980 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
981 raw_ptr_resource_handler_->status().status());
982 EXPECT_EQ(test_data().size(), static_cast<size_t>(
983 raw_ptr_resource_handler_->total_bytes_downloaded()));
985 // Check that the data was written to the file.
986 std::string contents;
987 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
988 EXPECT_EQ(test_data(), contents);
990 // Release the loader. The file should be gone now.
991 ReleaseLoader();
992 base::RunLoop().RunUntilIdle();
993 EXPECT_FALSE(base::PathExists(temp_path()));
996 } // namespace content