Roll src/third_party/WebKit 3a0ba1e:fcd7003 (svn 191141:191149)
[chromium-blink-merge.git] / content / browser / loader / resource_loader_unittest.cc
blob92241b68d0beab40f4d03c6512289017c9578e5b
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/message_loop/message_loop_proxy.h"
10 #include "base/run_loop.h"
11 #include "content/browser/browser_thread_impl.h"
12 #include "content/browser/loader/redirect_to_file_resource_handler.h"
13 #include "content/browser/loader/resource_loader_delegate.h"
14 #include "content/public/browser/resource_request_info.h"
15 #include "content/public/common/resource_response.h"
16 #include "content/public/test/mock_resource_context.h"
17 #include "content/public/test/test_browser_thread_bundle.h"
18 #include "content/test/test_content_browser_client.h"
19 #include "ipc/ipc_message.h"
20 #include "net/base/io_buffer.h"
21 #include "net/base/mock_file_stream.h"
22 #include "net/base/request_priority.h"
23 #include "net/cert/x509_certificate.h"
24 #include "net/ssl/client_cert_store.h"
25 #include "net/ssl/ssl_cert_request_info.h"
26 #include "net/url_request/url_request.h"
27 #include "net/url_request/url_request_job_factory_impl.h"
28 #include "net/url_request/url_request_test_job.h"
29 #include "net/url_request/url_request_test_util.h"
30 #include "storage/browser/blob/shareable_file_reference.h"
31 #include "testing/gtest/include/gtest/gtest.h"
33 using storage::ShareableFileReference;
35 namespace content {
36 namespace {
38 // Stub client certificate store that returns a preset list of certificates for
39 // each request and records the arguments of the most recent request for later
40 // inspection.
41 class ClientCertStoreStub : public net::ClientCertStore {
42 public:
43 // Creates a new ClientCertStoreStub that returns |response| on query. It
44 // saves the number of requests and most recently certificate authorities list
45 // in |requested_authorities| and |request_count|, respectively. The caller is
46 // responsible for ensuring those pointers outlive the ClientCertStoreStub.
48 // TODO(ppi): Make the stub independent from the internal representation of
49 // SSLCertRequestInfo. For now it seems that we can neither save the
50 // scoped_refptr<> (since it is never passed to us) nor copy the entire
51 // CertificateRequestInfo (since there is no copy constructor).
52 ClientCertStoreStub(const net::CertificateList& response,
53 int* request_count,
54 std::vector<std::string>* requested_authorities)
55 : response_(response),
56 async_(false),
57 requested_authorities_(requested_authorities),
58 request_count_(request_count) {
59 requested_authorities_->clear();
60 *request_count_ = 0;
63 ~ClientCertStoreStub() override {}
65 // Configures whether the certificates are returned asynchronously or not.
66 void set_async(bool async) { async_ = async; }
68 // net::ClientCertStore:
69 void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
70 net::CertificateList* selected_certs,
71 const base::Closure& callback) override {
72 *requested_authorities_ = cert_request_info.cert_authorities;
73 ++(*request_count_);
75 *selected_certs = response_;
76 if (async_) {
77 base::MessageLoop::current()->PostTask(FROM_HERE, callback);
78 } else {
79 callback.Run();
83 private:
84 const net::CertificateList response_;
85 bool async_;
86 std::vector<std::string>* requested_authorities_;
87 int* request_count_;
90 // Arbitrary read buffer size.
91 const int kReadBufSize = 1024;
93 // Dummy implementation of ResourceHandler, instance of which is needed to
94 // initialize ResourceLoader.
95 class ResourceHandlerStub : public ResourceHandler {
96 public:
97 explicit ResourceHandlerStub(net::URLRequest* request)
98 : ResourceHandler(request),
99 read_buffer_(new net::IOBuffer(kReadBufSize)),
100 defer_request_on_will_start_(false),
101 expect_reads_(true),
102 cancel_on_read_completed_(false),
103 defer_eof_(false),
104 received_on_will_read_(false),
105 received_eof_(false),
106 received_response_completed_(false),
107 total_bytes_downloaded_(0) {
110 // If true, defers the resource load in OnWillStart.
111 void set_defer_request_on_will_start(bool defer_request_on_will_start) {
112 defer_request_on_will_start_ = defer_request_on_will_start;
115 // If true, expect OnWillRead / OnReadCompleted pairs for handling
116 // data. Otherwise, expect OnDataDownloaded.
117 void set_expect_reads(bool expect_reads) { expect_reads_ = expect_reads; }
119 // If true, cancel the request in OnReadCompleted by returning false.
120 void set_cancel_on_read_completed(bool cancel_on_read_completed) {
121 cancel_on_read_completed_ = cancel_on_read_completed;
124 // If true, cancel the request in OnReadCompleted by returning false.
125 void set_defer_eof(bool defer_eof) { defer_eof_ = defer_eof; }
127 const GURL& start_url() const { return start_url_; }
128 ResourceResponse* response() const { return response_.get(); }
129 bool received_response_completed() const {
130 return received_response_completed_;
132 const net::URLRequestStatus& status() const { return status_; }
133 int total_bytes_downloaded() const { return total_bytes_downloaded_; }
135 void Resume() {
136 controller()->Resume();
139 // ResourceHandler implementation:
140 bool OnUploadProgress(uint64 position, uint64 size) override {
141 NOTREACHED();
142 return true;
145 bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
146 ResourceResponse* response,
147 bool* defer) override {
148 NOTREACHED();
149 return true;
152 bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
153 EXPECT_FALSE(response_.get());
154 response_ = response;
155 return true;
158 bool OnWillStart(const GURL& url, bool* defer) override {
159 EXPECT_TRUE(start_url_.is_empty());
160 start_url_ = url;
161 *defer = defer_request_on_will_start_;
162 return true;
165 bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
166 return true;
169 bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
170 int* buf_size,
171 int min_size) override {
172 EXPECT_TRUE(expect_reads_);
173 EXPECT_FALSE(received_on_will_read_);
174 EXPECT_FALSE(received_eof_);
175 EXPECT_FALSE(received_response_completed_);
177 *buf = read_buffer_;
178 *buf_size = kReadBufSize;
179 received_on_will_read_ = true;
180 return true;
183 bool OnReadCompleted(int bytes_read, bool* defer) override {
184 EXPECT_TRUE(received_on_will_read_);
185 EXPECT_TRUE(expect_reads_);
186 EXPECT_FALSE(received_response_completed_);
188 if (bytes_read == 0) {
189 received_eof_ = true;
190 if (defer_eof_) {
191 defer_eof_ = false;
192 *defer = true;
196 // Need another OnWillRead() call before seeing an OnReadCompleted().
197 received_on_will_read_ = false;
199 return !cancel_on_read_completed_;
202 void OnResponseCompleted(const net::URLRequestStatus& status,
203 const std::string& security_info,
204 bool* defer) override {
205 EXPECT_FALSE(received_response_completed_);
206 if (status.is_success() && expect_reads_)
207 EXPECT_TRUE(received_eof_);
209 received_response_completed_ = true;
210 status_ = status;
213 void OnDataDownloaded(int bytes_downloaded) override {
214 EXPECT_FALSE(expect_reads_);
215 total_bytes_downloaded_ += bytes_downloaded;
218 private:
219 scoped_refptr<net::IOBuffer> read_buffer_;
221 bool defer_request_on_will_start_;
222 bool expect_reads_;
223 bool cancel_on_read_completed_;
224 bool defer_eof_;
226 GURL start_url_;
227 scoped_refptr<ResourceResponse> response_;
228 bool received_on_will_read_;
229 bool received_eof_;
230 bool received_response_completed_;
231 net::URLRequestStatus status_;
232 int total_bytes_downloaded_;
235 // Test browser client that captures calls to SelectClientCertificates and
236 // records the arguments of the most recent call for later inspection.
237 class SelectCertificateBrowserClient : public TestContentBrowserClient {
238 public:
239 SelectCertificateBrowserClient() : call_count_(0) {}
241 void SelectClientCertificate(
242 int render_process_id,
243 int render_view_id,
244 net::SSLCertRequestInfo* cert_request_info,
245 const base::Callback<void(net::X509Certificate*)>& callback) override {
246 ++call_count_;
247 passed_certs_ = cert_request_info->client_certs;
250 int call_count() {
251 return call_count_;
254 net::CertificateList passed_certs() {
255 return passed_certs_;
258 private:
259 net::CertificateList passed_certs_;
260 int call_count_;
263 class ResourceContextStub : public MockResourceContext {
264 public:
265 explicit ResourceContextStub(net::URLRequestContext* test_request_context)
266 : MockResourceContext(test_request_context) {}
268 scoped_ptr<net::ClientCertStore> CreateClientCertStore() override {
269 return dummy_cert_store_.Pass();
272 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
273 dummy_cert_store_ = store.Pass();
276 private:
277 scoped_ptr<net::ClientCertStore> dummy_cert_store_;
280 // Fails to create a temporary file with the given error.
281 void CreateTemporaryError(
282 base::File::Error error,
283 const CreateTemporaryFileStreamCallback& callback) {
284 base::MessageLoop::current()->PostTask(
285 FROM_HERE,
286 base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
287 scoped_refptr<ShareableFileReference>()));
290 } // namespace
292 class ResourceLoaderTest : public testing::Test,
293 public ResourceLoaderDelegate {
294 protected:
295 ResourceLoaderTest()
296 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
297 resource_context_(&test_url_request_context_),
298 raw_ptr_resource_handler_(NULL),
299 raw_ptr_to_request_(NULL) {
300 job_factory_.SetProtocolHandler(
301 "test", net::URLRequestTestJob::CreateProtocolHandler());
302 test_url_request_context_.set_job_factory(&job_factory_);
305 GURL test_url() const {
306 return net::URLRequestTestJob::test_url_1();
309 std::string test_data() const {
310 return net::URLRequestTestJob::test_data_1();
313 virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
314 scoped_ptr<ResourceHandlerStub> leaf_handler,
315 net::URLRequest* request) {
316 return leaf_handler.Pass();
319 void SetUp() override {
320 const int kRenderProcessId = 1;
321 const int kRenderViewId = 2;
323 scoped_ptr<net::URLRequest> request(
324 resource_context_.GetRequestContext()->CreateRequest(
325 test_url(),
326 net::DEFAULT_PRIORITY,
327 NULL /* delegate */,
328 NULL /* cookie_store */));
329 raw_ptr_to_request_ = request.get();
330 ResourceRequestInfo::AllocateForTesting(request.get(),
331 RESOURCE_TYPE_MAIN_FRAME,
332 &resource_context_,
333 kRenderProcessId,
334 kRenderViewId,
335 MSG_ROUTING_NONE,
336 true, // is_main_frame
337 false, // parent_is_main_frame
338 true, // allow_download
339 false); // is_async
340 scoped_ptr<ResourceHandlerStub> resource_handler(
341 new ResourceHandlerStub(request.get()));
342 raw_ptr_resource_handler_ = resource_handler.get();
343 loader_.reset(new ResourceLoader(
344 request.Pass(),
345 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
346 this));
349 // ResourceLoaderDelegate:
350 ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
351 ResourceLoader* loader,
352 net::AuthChallengeInfo* auth_info) override {
353 return NULL;
355 bool HandleExternalProtocol(ResourceLoader* loader,
356 const GURL& url) override {
357 return false;
359 void DidStartRequest(ResourceLoader* loader) override {}
360 void DidReceiveRedirect(ResourceLoader* loader,
361 const GURL& new_url) override {}
362 void DidReceiveResponse(ResourceLoader* loader) override {}
363 void DidFinishLoading(ResourceLoader* loader) override {}
365 content::TestBrowserThreadBundle thread_bundle_;
367 net::URLRequestJobFactoryImpl job_factory_;
368 net::TestURLRequestContext test_url_request_context_;
369 ResourceContextStub resource_context_;
371 // The ResourceLoader owns the URLRequest and the ResourceHandler.
372 ResourceHandlerStub* raw_ptr_resource_handler_;
373 net::URLRequest* raw_ptr_to_request_;
374 scoped_ptr<ResourceLoader> loader_;
377 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested()
378 // causes client cert store to be queried for certificates and if the returned
379 // certificates are correctly passed to the content browser client for
380 // selection.
381 TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
382 // Set up the test client cert store.
383 int store_request_count;
384 std::vector<std::string> store_requested_authorities;
385 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
386 new net::X509Certificate("test", "test", base::Time(), base::Time())));
387 scoped_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub(
388 dummy_certs, &store_request_count, &store_requested_authorities));
389 resource_context_.SetClientCertStore(test_store.Pass());
391 // Prepare a dummy certificate request.
392 scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
393 new net::SSLCertRequestInfo());
394 std::vector<std::string> dummy_authority(1, "dummy");
395 cert_request_info->cert_authorities = dummy_authority;
397 // Plug in test content browser client.
398 SelectCertificateBrowserClient test_client;
399 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
401 // Everything is set up. Trigger the resource loader certificate request event
402 // and run the message loop.
403 loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get());
404 base::RunLoop().RunUntilIdle();
406 // Restore the original content browser client.
407 SetBrowserClientForTesting(old_client);
409 // Check if the test store was queried against correct |cert_authorities|.
410 EXPECT_EQ(1, store_request_count);
411 EXPECT_EQ(dummy_authority, store_requested_authorities);
413 // Check if the retrieved certificates were passed to the content browser
414 // client.
415 EXPECT_EQ(1, test_client.call_count());
416 EXPECT_EQ(dummy_certs, test_client.passed_certs());
419 // Verifies if a call to net::URLRequest::Delegate::OnCertificateRequested()
420 // on a platform with a NULL client cert store still calls the content browser
421 // client for selection.
422 TEST_F(ResourceLoaderTest, ClientCertStoreNull) {
423 // Prepare a dummy certificate request.
424 scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
425 new net::SSLCertRequestInfo());
426 std::vector<std::string> dummy_authority(1, "dummy");
427 cert_request_info->cert_authorities = dummy_authority;
429 // Plug in test content browser client.
430 SelectCertificateBrowserClient test_client;
431 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
433 // Everything is set up. Trigger the resource loader certificate request event
434 // and run the message loop.
435 loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get());
436 base::RunLoop().RunUntilIdle();
438 // Restore the original content browser client.
439 SetBrowserClientForTesting(old_client);
441 // Check if the SelectClientCertificate was called on the content browser
442 // client.
443 EXPECT_EQ(1, test_client.call_count());
444 EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
447 TEST_F(ResourceLoaderTest, ClientCertStoreAsyncCancel) {
448 // Set up the test client cert store.
449 int store_request_count;
450 std::vector<std::string> store_requested_authorities;
451 scoped_ptr<ClientCertStoreStub> test_store(
452 new ClientCertStoreStub(net::CertificateList(), &store_request_count,
453 &store_requested_authorities));
454 test_store->set_async(true);
455 EXPECT_EQ(0, store_request_count);
456 resource_context_.SetClientCertStore(test_store.Pass());
458 // Prepare a dummy certificate request.
459 scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
460 new net::SSLCertRequestInfo());
461 std::vector<std::string> dummy_authority(1, "dummy");
462 cert_request_info->cert_authorities = dummy_authority;
464 // Everything is set up. Trigger the resource loader certificate request
465 // event.
466 loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get());
468 // Check if the test store was queried against correct |cert_authorities|.
469 EXPECT_EQ(1, store_request_count);
470 EXPECT_EQ(dummy_authority, store_requested_authorities);
472 // Cancel the request before the store calls the callback.
473 loader_.reset();
475 // Pump the event loop. There shouldn't be a crash when the callback is run.
476 base::RunLoop().RunUntilIdle();
479 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) {
480 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
482 loader_->StartRequest();
483 loader_->CancelRequest(true);
484 static_cast<ResourceController*>(loader_.get())->Resume();
487 // Tests that no invariants are broken if a ResourceHandler cancels during
488 // OnReadCompleted.
489 TEST_F(ResourceLoaderTest, CancelOnReadCompleted) {
490 raw_ptr_resource_handler_->set_cancel_on_read_completed(true);
492 loader_->StartRequest();
493 base::RunLoop().RunUntilIdle();
495 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
496 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
497 EXPECT_EQ(net::URLRequestStatus::CANCELED,
498 raw_ptr_resource_handler_->status().status());
501 // Tests that no invariants are broken if a ResourceHandler defers EOF.
502 TEST_F(ResourceLoaderTest, DeferEOF) {
503 raw_ptr_resource_handler_->set_defer_eof(true);
505 loader_->StartRequest();
506 base::RunLoop().RunUntilIdle();
508 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
509 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
511 raw_ptr_resource_handler_->Resume();
512 base::RunLoop().RunUntilIdle();
514 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
515 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
516 raw_ptr_resource_handler_->status().status());
519 class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
520 public:
521 ResourceLoaderRedirectToFileTest()
522 : file_stream_(NULL),
523 redirect_to_file_resource_handler_(NULL) {
526 base::FilePath temp_path() const { return temp_path_; }
527 ShareableFileReference* deletable_file() const {
528 return deletable_file_.get();
530 net::testing::MockFileStream* file_stream() const { return file_stream_; }
531 RedirectToFileResourceHandler* redirect_to_file_resource_handler() const {
532 return redirect_to_file_resource_handler_;
535 void ReleaseLoader() {
536 file_stream_ = NULL;
537 deletable_file_ = NULL;
538 loader_.reset();
541 scoped_ptr<ResourceHandler> WrapResourceHandler(
542 scoped_ptr<ResourceHandlerStub> leaf_handler,
543 net::URLRequest* request) override {
544 leaf_handler->set_expect_reads(false);
546 // Make a temporary file.
547 CHECK(base::CreateTemporaryFile(&temp_path_));
548 int flags = base::File::FLAG_WRITE | base::File::FLAG_TEMPORARY |
549 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_ASYNC;
550 base::File file(temp_path_, flags);
551 CHECK(file.IsValid());
553 // Create mock file streams and a ShareableFileReference.
554 scoped_ptr<net::testing::MockFileStream> file_stream(
555 new net::testing::MockFileStream(file.Pass(),
556 base::MessageLoopProxy::current()));
557 file_stream_ = file_stream.get();
558 deletable_file_ = ShareableFileReference::GetOrCreate(
559 temp_path_,
560 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
561 BrowserThread::GetMessageLoopProxyForThread(
562 BrowserThread::FILE).get());
564 // Inject them into the handler.
565 scoped_ptr<RedirectToFileResourceHandler> handler(
566 new RedirectToFileResourceHandler(leaf_handler.Pass(), request));
567 redirect_to_file_resource_handler_ = handler.get();
568 handler->SetCreateTemporaryFileStreamFunctionForTesting(
569 base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback,
570 base::Unretained(this),
571 base::Passed(&file_stream)));
572 return handler.Pass();
575 private:
576 void PostCallback(
577 scoped_ptr<net::FileStream> file_stream,
578 const CreateTemporaryFileStreamCallback& callback) {
579 base::MessageLoop::current()->PostTask(
580 FROM_HERE,
581 base::Bind(callback, base::File::FILE_OK,
582 base::Passed(&file_stream), deletable_file_));
585 base::FilePath temp_path_;
586 scoped_refptr<ShareableFileReference> deletable_file_;
587 // These are owned by the ResourceLoader.
588 net::testing::MockFileStream* file_stream_;
589 RedirectToFileResourceHandler* redirect_to_file_resource_handler_;
592 // Tests that a RedirectToFileResourceHandler works and forwards everything
593 // downstream.
594 TEST_F(ResourceLoaderRedirectToFileTest, Basic) {
595 // Run it to completion.
596 loader_->StartRequest();
597 base::RunLoop().RunUntilIdle();
599 // Check that the handler forwarded all information to the downstream handler.
600 EXPECT_EQ(temp_path(),
601 raw_ptr_resource_handler_->response()->head.download_file_path);
602 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
603 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
604 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
605 raw_ptr_resource_handler_->status().status());
606 EXPECT_EQ(test_data().size(), static_cast<size_t>(
607 raw_ptr_resource_handler_->total_bytes_downloaded()));
609 // Check that the data was written to the file.
610 std::string contents;
611 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
612 EXPECT_EQ(test_data(), contents);
614 // Release the loader and the saved reference to file. The file should be gone
615 // now.
616 ReleaseLoader();
617 base::RunLoop().RunUntilIdle();
618 EXPECT_FALSE(base::PathExists(temp_path()));
621 // Tests that RedirectToFileResourceHandler handles errors in creating the
622 // temporary file.
623 TEST_F(ResourceLoaderRedirectToFileTest, CreateTemporaryError) {
624 // Swap out the create temporary function.
625 redirect_to_file_resource_handler()->
626 SetCreateTemporaryFileStreamFunctionForTesting(
627 base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED));
629 // Run it to completion.
630 loader_->StartRequest();
631 base::RunLoop().RunUntilIdle();
633 // To downstream, the request was canceled.
634 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
635 EXPECT_EQ(net::URLRequestStatus::CANCELED,
636 raw_ptr_resource_handler_->status().status());
637 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
640 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
641 TEST_F(ResourceLoaderRedirectToFileTest, WriteError) {
642 file_stream()->set_forced_error(net::ERR_FAILED);
644 // Run it to completion.
645 loader_->StartRequest();
646 base::RunLoop().RunUntilIdle();
648 // To downstream, the request was canceled sometime after it started, but
649 // before any data was written.
650 EXPECT_EQ(temp_path(),
651 raw_ptr_resource_handler_->response()->head.download_file_path);
652 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
653 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
654 EXPECT_EQ(net::URLRequestStatus::CANCELED,
655 raw_ptr_resource_handler_->status().status());
656 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
658 // Release the loader. The file should be gone now.
659 ReleaseLoader();
660 base::RunLoop().RunUntilIdle();
661 EXPECT_FALSE(base::PathExists(temp_path()));
664 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
665 TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) {
666 file_stream()->set_forced_error_async(net::ERR_FAILED);
668 // Run it to completion.
669 loader_->StartRequest();
670 base::RunLoop().RunUntilIdle();
672 // To downstream, the request was canceled sometime after it started, but
673 // before any data was written.
674 EXPECT_EQ(temp_path(),
675 raw_ptr_resource_handler_->response()->head.download_file_path);
676 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
677 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
678 EXPECT_EQ(net::URLRequestStatus::CANCELED,
679 raw_ptr_resource_handler_->status().status());
680 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
682 // Release the loader. The file should be gone now.
683 ReleaseLoader();
684 base::RunLoop().RunUntilIdle();
685 EXPECT_FALSE(base::PathExists(temp_path()));
688 // Tests that RedirectToFileHandler defers completion if there are outstanding
689 // writes and accounts for errors which occur in that time.
690 TEST_F(ResourceLoaderRedirectToFileTest, DeferCompletion) {
691 // Program the MockFileStream to error asynchronously, but throttle the
692 // callback.
693 file_stream()->set_forced_error_async(net::ERR_FAILED);
694 file_stream()->ThrottleCallbacks();
696 // Run it as far as it will go.
697 loader_->StartRequest();
698 base::RunLoop().RunUntilIdle();
700 // At this point, the request should have completed.
701 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
702 raw_ptr_to_request_->status().status());
704 // However, the resource loader stack is stuck somewhere after receiving the
705 // response.
706 EXPECT_EQ(temp_path(),
707 raw_ptr_resource_handler_->response()->head.download_file_path);
708 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
709 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
710 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
712 // Now, release the floodgates.
713 file_stream()->ReleaseCallbacks();
714 base::RunLoop().RunUntilIdle();
716 // Although the URLRequest was successful, the leaf handler sees a failure
717 // because the write never completed.
718 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
719 EXPECT_EQ(net::URLRequestStatus::CANCELED,
720 raw_ptr_resource_handler_->status().status());
722 // Release the loader. The file should be gone now.
723 ReleaseLoader();
724 base::RunLoop().RunUntilIdle();
725 EXPECT_FALSE(base::PathExists(temp_path()));
728 // Tests that a RedirectToFileResourceHandler behaves properly when the
729 // downstream handler defers OnWillStart.
730 TEST_F(ResourceLoaderRedirectToFileTest, DownstreamDeferStart) {
731 // Defer OnWillStart.
732 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
734 // Run as far as we'll go.
735 loader_->StartRequest();
736 base::RunLoop().RunUntilIdle();
738 // The request should have stopped at OnWillStart.
739 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
740 EXPECT_FALSE(raw_ptr_resource_handler_->response());
741 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
742 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
744 // Now resume the request. Now we complete.
745 raw_ptr_resource_handler_->Resume();
746 base::RunLoop().RunUntilIdle();
748 // Check that the handler forwarded all information to the downstream handler.
749 EXPECT_EQ(temp_path(),
750 raw_ptr_resource_handler_->response()->head.download_file_path);
751 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
752 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
753 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
754 raw_ptr_resource_handler_->status().status());
755 EXPECT_EQ(test_data().size(), static_cast<size_t>(
756 raw_ptr_resource_handler_->total_bytes_downloaded()));
758 // Check that the data was written to the file.
759 std::string contents;
760 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
761 EXPECT_EQ(test_data(), contents);
763 // Release the loader. The file should be gone now.
764 ReleaseLoader();
765 base::RunLoop().RunUntilIdle();
766 EXPECT_FALSE(base::PathExists(temp_path()));
769 } // namespace content