Apply _RELATIVE relocations ahead of others.
[chromium-blink-merge.git] / content / browser / loader / resource_loader_unittest.cc
blob635f566f7dd1b446a6169e63a70d9449d3dd5be4
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/common/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 ClientCertStoreStub(const net::CertificateList& certs)
44 : response_(certs),
45 request_count_(0) {}
47 ~ClientCertStoreStub() override {}
49 // Returns |cert_authorities| field of the certificate request passed in the
50 // most recent call to GetClientCerts().
51 // TODO(ppi): Make the stub independent from the internal representation of
52 // SSLCertRequestInfo. For now it seems that we cannot neither save the
53 // scoped_refptr<> (since it is never passed to us) nor copy the entire
54 // CertificateRequestInfo (since there is no copy constructor).
55 std::vector<std::string> requested_authorities() {
56 return requested_authorities_;
59 // Returns the number of calls to GetClientCerts().
60 int request_count() {
61 return request_count_;
64 // net::ClientCertStore:
65 void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
66 net::CertificateList* selected_certs,
67 const base::Closure& callback) override {
68 ++request_count_;
69 requested_authorities_ = cert_request_info.cert_authorities;
70 *selected_certs = response_;
71 callback.Run();
74 private:
75 const net::CertificateList response_;
76 int request_count_;
77 std::vector<std::string> requested_authorities_;
80 // Arbitrary read buffer size.
81 const int kReadBufSize = 1024;
83 // Dummy implementation of ResourceHandler, instance of which is needed to
84 // initialize ResourceLoader.
85 class ResourceHandlerStub : public ResourceHandler {
86 public:
87 explicit ResourceHandlerStub(net::URLRequest* request)
88 : ResourceHandler(request),
89 read_buffer_(new net::IOBuffer(kReadBufSize)),
90 defer_request_on_will_start_(false),
91 expect_reads_(true),
92 cancel_on_read_completed_(false),
93 defer_eof_(false),
94 received_on_will_read_(false),
95 received_eof_(false),
96 received_response_completed_(false),
97 total_bytes_downloaded_(0) {
100 // If true, defers the resource load in OnWillStart.
101 void set_defer_request_on_will_start(bool defer_request_on_will_start) {
102 defer_request_on_will_start_ = defer_request_on_will_start;
105 // If true, expect OnWillRead / OnReadCompleted pairs for handling
106 // data. Otherwise, expect OnDataDownloaded.
107 void set_expect_reads(bool expect_reads) { expect_reads_ = expect_reads; }
109 // If true, cancel the request in OnReadCompleted by returning false.
110 void set_cancel_on_read_completed(bool cancel_on_read_completed) {
111 cancel_on_read_completed_ = cancel_on_read_completed;
114 // If true, cancel the request in OnReadCompleted by returning false.
115 void set_defer_eof(bool defer_eof) { defer_eof_ = defer_eof; }
117 const GURL& start_url() const { return start_url_; }
118 ResourceResponse* response() const { return response_.get(); }
119 bool received_response_completed() const {
120 return received_response_completed_;
122 const net::URLRequestStatus& status() const { return status_; }
123 int total_bytes_downloaded() const { return total_bytes_downloaded_; }
125 void Resume() {
126 controller()->Resume();
129 // ResourceHandler implementation:
130 bool OnUploadProgress(uint64 position, uint64 size) override {
131 NOTREACHED();
132 return true;
135 bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
136 ResourceResponse* response,
137 bool* defer) override {
138 NOTREACHED();
139 return true;
142 bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
143 EXPECT_FALSE(response_.get());
144 response_ = response;
145 return true;
148 bool OnWillStart(const GURL& url, bool* defer) override {
149 EXPECT_TRUE(start_url_.is_empty());
150 start_url_ = url;
151 *defer = defer_request_on_will_start_;
152 return true;
155 bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
156 return true;
159 bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
160 int* buf_size,
161 int min_size) override {
162 EXPECT_TRUE(expect_reads_);
163 EXPECT_FALSE(received_on_will_read_);
164 EXPECT_FALSE(received_eof_);
165 EXPECT_FALSE(received_response_completed_);
167 *buf = read_buffer_;
168 *buf_size = kReadBufSize;
169 received_on_will_read_ = true;
170 return true;
173 bool OnReadCompleted(int bytes_read, bool* defer) override {
174 EXPECT_TRUE(received_on_will_read_);
175 EXPECT_TRUE(expect_reads_);
176 EXPECT_FALSE(received_response_completed_);
178 if (bytes_read == 0) {
179 received_eof_ = true;
180 if (defer_eof_) {
181 defer_eof_ = false;
182 *defer = true;
186 // Need another OnWillRead() call before seeing an OnReadCompleted().
187 received_on_will_read_ = false;
189 return !cancel_on_read_completed_;
192 void OnResponseCompleted(const net::URLRequestStatus& status,
193 const std::string& security_info,
194 bool* defer) override {
195 EXPECT_FALSE(received_response_completed_);
196 if (status.is_success() && expect_reads_)
197 EXPECT_TRUE(received_eof_);
199 received_response_completed_ = true;
200 status_ = status;
203 void OnDataDownloaded(int bytes_downloaded) override {
204 EXPECT_FALSE(expect_reads_);
205 total_bytes_downloaded_ += bytes_downloaded;
208 private:
209 scoped_refptr<net::IOBuffer> read_buffer_;
211 bool defer_request_on_will_start_;
212 bool expect_reads_;
213 bool cancel_on_read_completed_;
214 bool defer_eof_;
216 GURL start_url_;
217 scoped_refptr<ResourceResponse> response_;
218 bool received_on_will_read_;
219 bool received_eof_;
220 bool received_response_completed_;
221 net::URLRequestStatus status_;
222 int total_bytes_downloaded_;
225 // Test browser client that captures calls to SelectClientCertificates and
226 // records the arguments of the most recent call for later inspection.
227 class SelectCertificateBrowserClient : public TestContentBrowserClient {
228 public:
229 SelectCertificateBrowserClient() : call_count_(0) {}
231 void SelectClientCertificate(
232 int render_process_id,
233 int render_view_id,
234 net::SSLCertRequestInfo* cert_request_info,
235 const base::Callback<void(net::X509Certificate*)>& callback) override {
236 ++call_count_;
237 passed_certs_ = cert_request_info->client_certs;
240 int call_count() {
241 return call_count_;
244 net::CertificateList passed_certs() {
245 return passed_certs_;
248 private:
249 net::CertificateList passed_certs_;
250 int call_count_;
253 class ResourceContextStub : public MockResourceContext {
254 public:
255 explicit ResourceContextStub(net::URLRequestContext* test_request_context)
256 : MockResourceContext(test_request_context) {}
258 scoped_ptr<net::ClientCertStore> CreateClientCertStore() override {
259 return dummy_cert_store_.Pass();
262 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
263 dummy_cert_store_ = store.Pass();
266 private:
267 scoped_ptr<net::ClientCertStore> dummy_cert_store_;
270 // Fails to create a temporary file with the given error.
271 void CreateTemporaryError(
272 base::File::Error error,
273 const CreateTemporaryFileStreamCallback& callback) {
274 base::MessageLoop::current()->PostTask(
275 FROM_HERE,
276 base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
277 scoped_refptr<ShareableFileReference>()));
280 } // namespace
282 class ResourceLoaderTest : public testing::Test,
283 public ResourceLoaderDelegate {
284 protected:
285 ResourceLoaderTest()
286 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
287 resource_context_(&test_url_request_context_),
288 raw_ptr_resource_handler_(NULL),
289 raw_ptr_to_request_(NULL) {
290 job_factory_.SetProtocolHandler(
291 "test", net::URLRequestTestJob::CreateProtocolHandler());
292 test_url_request_context_.set_job_factory(&job_factory_);
295 GURL test_url() const {
296 return net::URLRequestTestJob::test_url_1();
299 std::string test_data() const {
300 return net::URLRequestTestJob::test_data_1();
303 virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
304 scoped_ptr<ResourceHandlerStub> leaf_handler,
305 net::URLRequest* request) {
306 return leaf_handler.Pass();
309 void SetUp() override {
310 const int kRenderProcessId = 1;
311 const int kRenderViewId = 2;
313 scoped_ptr<net::URLRequest> request(
314 resource_context_.GetRequestContext()->CreateRequest(
315 test_url(),
316 net::DEFAULT_PRIORITY,
317 NULL /* delegate */,
318 NULL /* cookie_store */));
319 raw_ptr_to_request_ = request.get();
320 ResourceRequestInfo::AllocateForTesting(request.get(),
321 RESOURCE_TYPE_MAIN_FRAME,
322 &resource_context_,
323 kRenderProcessId,
324 kRenderViewId,
325 MSG_ROUTING_NONE,
326 false);
327 scoped_ptr<ResourceHandlerStub> resource_handler(
328 new ResourceHandlerStub(request.get()));
329 raw_ptr_resource_handler_ = resource_handler.get();
330 loader_.reset(new ResourceLoader(
331 request.Pass(),
332 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
333 this));
336 // ResourceLoaderDelegate:
337 ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
338 ResourceLoader* loader,
339 net::AuthChallengeInfo* auth_info) override {
340 return NULL;
342 bool HandleExternalProtocol(ResourceLoader* loader,
343 const GURL& url) override {
344 return false;
346 void DidStartRequest(ResourceLoader* loader) override {}
347 void DidReceiveRedirect(ResourceLoader* loader,
348 const GURL& new_url) override {}
349 void DidReceiveResponse(ResourceLoader* loader) override {}
350 void DidFinishLoading(ResourceLoader* loader) override {}
352 content::TestBrowserThreadBundle thread_bundle_;
354 net::URLRequestJobFactoryImpl job_factory_;
355 net::TestURLRequestContext test_url_request_context_;
356 ResourceContextStub resource_context_;
358 // The ResourceLoader owns the URLRequest and the ResourceHandler.
359 ResourceHandlerStub* raw_ptr_resource_handler_;
360 net::URLRequest* raw_ptr_to_request_;
361 scoped_ptr<ResourceLoader> loader_;
364 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested()
365 // causes client cert store to be queried for certificates and if the returned
366 // certificates are correctly passed to the content browser client for
367 // selection.
368 TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
369 // Set up the test client cert store.
370 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
371 new net::X509Certificate("test", "test", base::Time(), base::Time())));
372 scoped_ptr<ClientCertStoreStub> test_store(
373 new ClientCertStoreStub(dummy_certs));
374 EXPECT_EQ(0, test_store->request_count());
376 // Ownership of the |test_store| is about to be turned over to ResourceLoader.
377 // We need to keep raw pointer copies to access these objects later.
378 ClientCertStoreStub* raw_ptr_to_store = test_store.get();
379 resource_context_.SetClientCertStore(test_store.Pass());
381 // Prepare a dummy certificate request.
382 scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
383 new net::SSLCertRequestInfo());
384 std::vector<std::string> dummy_authority(1, "dummy");
385 cert_request_info->cert_authorities = dummy_authority;
387 // Plug in test content browser client.
388 SelectCertificateBrowserClient test_client;
389 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
391 // Everything is set up. Trigger the resource loader certificate request event
392 // and run the message loop.
393 loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get());
394 base::RunLoop().RunUntilIdle();
396 // Restore the original content browser client.
397 SetBrowserClientForTesting(old_client);
399 // Check if the test store was queried against correct |cert_authorities|.
400 EXPECT_EQ(1, raw_ptr_to_store->request_count());
401 EXPECT_EQ(dummy_authority, raw_ptr_to_store->requested_authorities());
403 // Check if the retrieved certificates were passed to the content browser
404 // client.
405 EXPECT_EQ(1, test_client.call_count());
406 EXPECT_EQ(dummy_certs, test_client.passed_certs());
409 // Verifies if a call to net::URLRequest::Delegate::OnCertificateRequested()
410 // on a platform with a NULL client cert store still calls the content browser
411 // client for selection.
412 TEST_F(ResourceLoaderTest, ClientCertStoreNull) {
413 // Prepare a dummy certificate request.
414 scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
415 new net::SSLCertRequestInfo());
416 std::vector<std::string> dummy_authority(1, "dummy");
417 cert_request_info->cert_authorities = dummy_authority;
419 // Plug in test content browser client.
420 SelectCertificateBrowserClient test_client;
421 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
423 // Everything is set up. Trigger the resource loader certificate request event
424 // and run the message loop.
425 loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get());
426 base::RunLoop().RunUntilIdle();
428 // Restore the original content browser client.
429 SetBrowserClientForTesting(old_client);
431 // Check if the SelectClientCertificate was called on the content browser
432 // client.
433 EXPECT_EQ(1, test_client.call_count());
434 EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
437 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) {
438 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
440 loader_->StartRequest();
441 loader_->CancelRequest(true);
442 static_cast<ResourceController*>(loader_.get())->Resume();
445 // Tests that no invariants are broken if a ResourceHandler cancels during
446 // OnReadCompleted.
447 TEST_F(ResourceLoaderTest, CancelOnReadCompleted) {
448 raw_ptr_resource_handler_->set_cancel_on_read_completed(true);
450 loader_->StartRequest();
451 base::RunLoop().RunUntilIdle();
453 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
454 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
455 EXPECT_EQ(net::URLRequestStatus::CANCELED,
456 raw_ptr_resource_handler_->status().status());
459 // Tests that no invariants are broken if a ResourceHandler defers EOF.
460 TEST_F(ResourceLoaderTest, DeferEOF) {
461 raw_ptr_resource_handler_->set_defer_eof(true);
463 loader_->StartRequest();
464 base::RunLoop().RunUntilIdle();
466 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
467 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
469 raw_ptr_resource_handler_->Resume();
470 base::RunLoop().RunUntilIdle();
472 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
473 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
474 raw_ptr_resource_handler_->status().status());
477 class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
478 public:
479 ResourceLoaderRedirectToFileTest()
480 : file_stream_(NULL),
481 redirect_to_file_resource_handler_(NULL) {
484 base::FilePath temp_path() const { return temp_path_; }
485 ShareableFileReference* deletable_file() const {
486 return deletable_file_.get();
488 net::testing::MockFileStream* file_stream() const { return file_stream_; }
489 RedirectToFileResourceHandler* redirect_to_file_resource_handler() const {
490 return redirect_to_file_resource_handler_;
493 void ReleaseLoader() {
494 file_stream_ = NULL;
495 deletable_file_ = NULL;
496 loader_.reset();
499 scoped_ptr<ResourceHandler> WrapResourceHandler(
500 scoped_ptr<ResourceHandlerStub> leaf_handler,
501 net::URLRequest* request) override {
502 leaf_handler->set_expect_reads(false);
504 // Make a temporary file.
505 CHECK(base::CreateTemporaryFile(&temp_path_));
506 int flags = base::File::FLAG_WRITE | base::File::FLAG_TEMPORARY |
507 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_ASYNC;
508 base::File file(temp_path_, flags);
509 CHECK(file.IsValid());
511 // Create mock file streams and a ShareableFileReference.
512 scoped_ptr<net::testing::MockFileStream> file_stream(
513 new net::testing::MockFileStream(file.Pass(),
514 base::MessageLoopProxy::current()));
515 file_stream_ = file_stream.get();
516 deletable_file_ = ShareableFileReference::GetOrCreate(
517 temp_path_,
518 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
519 BrowserThread::GetMessageLoopProxyForThread(
520 BrowserThread::FILE).get());
522 // Inject them into the handler.
523 scoped_ptr<RedirectToFileResourceHandler> handler(
524 new RedirectToFileResourceHandler(leaf_handler.Pass(), request));
525 redirect_to_file_resource_handler_ = handler.get();
526 handler->SetCreateTemporaryFileStreamFunctionForTesting(
527 base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback,
528 base::Unretained(this),
529 base::Passed(&file_stream)));
530 return handler.Pass();
533 private:
534 void PostCallback(
535 scoped_ptr<net::FileStream> file_stream,
536 const CreateTemporaryFileStreamCallback& callback) {
537 base::MessageLoop::current()->PostTask(
538 FROM_HERE,
539 base::Bind(callback, base::File::FILE_OK,
540 base::Passed(&file_stream), deletable_file_));
543 base::FilePath temp_path_;
544 scoped_refptr<ShareableFileReference> deletable_file_;
545 // These are owned by the ResourceLoader.
546 net::testing::MockFileStream* file_stream_;
547 RedirectToFileResourceHandler* redirect_to_file_resource_handler_;
550 // Tests that a RedirectToFileResourceHandler works and forwards everything
551 // downstream.
552 TEST_F(ResourceLoaderRedirectToFileTest, Basic) {
553 // Run it to completion.
554 loader_->StartRequest();
555 base::RunLoop().RunUntilIdle();
557 // Check that the handler forwarded all information to the downstream handler.
558 EXPECT_EQ(temp_path(),
559 raw_ptr_resource_handler_->response()->head.download_file_path);
560 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
561 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
562 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
563 raw_ptr_resource_handler_->status().status());
564 EXPECT_EQ(test_data().size(), static_cast<size_t>(
565 raw_ptr_resource_handler_->total_bytes_downloaded()));
567 // Check that the data was written to the file.
568 std::string contents;
569 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
570 EXPECT_EQ(test_data(), contents);
572 // Release the loader and the saved reference to file. The file should be gone
573 // now.
574 ReleaseLoader();
575 base::RunLoop().RunUntilIdle();
576 EXPECT_FALSE(base::PathExists(temp_path()));
579 // Tests that RedirectToFileResourceHandler handles errors in creating the
580 // temporary file.
581 TEST_F(ResourceLoaderRedirectToFileTest, CreateTemporaryError) {
582 // Swap out the create temporary function.
583 redirect_to_file_resource_handler()->
584 SetCreateTemporaryFileStreamFunctionForTesting(
585 base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED));
587 // Run it to completion.
588 loader_->StartRequest();
589 base::RunLoop().RunUntilIdle();
591 // To downstream, the request was canceled.
592 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
593 EXPECT_EQ(net::URLRequestStatus::CANCELED,
594 raw_ptr_resource_handler_->status().status());
595 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
598 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
599 TEST_F(ResourceLoaderRedirectToFileTest, WriteError) {
600 file_stream()->set_forced_error(net::ERR_FAILED);
602 // Run it to completion.
603 loader_->StartRequest();
604 base::RunLoop().RunUntilIdle();
606 // To downstream, the request was canceled sometime after it started, but
607 // before any data was written.
608 EXPECT_EQ(temp_path(),
609 raw_ptr_resource_handler_->response()->head.download_file_path);
610 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
611 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
612 EXPECT_EQ(net::URLRequestStatus::CANCELED,
613 raw_ptr_resource_handler_->status().status());
614 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
616 // Release the loader. The file should be gone now.
617 ReleaseLoader();
618 base::RunLoop().RunUntilIdle();
619 EXPECT_FALSE(base::PathExists(temp_path()));
622 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
623 TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) {
624 file_stream()->set_forced_error_async(net::ERR_FAILED);
626 // Run it to completion.
627 loader_->StartRequest();
628 base::RunLoop().RunUntilIdle();
630 // To downstream, the request was canceled sometime after it started, but
631 // before any data was written.
632 EXPECT_EQ(temp_path(),
633 raw_ptr_resource_handler_->response()->head.download_file_path);
634 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
635 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
636 EXPECT_EQ(net::URLRequestStatus::CANCELED,
637 raw_ptr_resource_handler_->status().status());
638 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
640 // Release the loader. The file should be gone now.
641 ReleaseLoader();
642 base::RunLoop().RunUntilIdle();
643 EXPECT_FALSE(base::PathExists(temp_path()));
646 // Tests that RedirectToFileHandler defers completion if there are outstanding
647 // writes and accounts for errors which occur in that time.
648 TEST_F(ResourceLoaderRedirectToFileTest, DeferCompletion) {
649 // Program the MockFileStream to error asynchronously, but throttle the
650 // callback.
651 file_stream()->set_forced_error_async(net::ERR_FAILED);
652 file_stream()->ThrottleCallbacks();
654 // Run it as far as it will go.
655 loader_->StartRequest();
656 base::RunLoop().RunUntilIdle();
658 // At this point, the request should have completed.
659 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
660 raw_ptr_to_request_->status().status());
662 // However, the resource loader stack is stuck somewhere after receiving the
663 // response.
664 EXPECT_EQ(temp_path(),
665 raw_ptr_resource_handler_->response()->head.download_file_path);
666 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
667 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
668 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
670 // Now, release the floodgates.
671 file_stream()->ReleaseCallbacks();
672 base::RunLoop().RunUntilIdle();
674 // Although the URLRequest was successful, the leaf handler sees a failure
675 // because the write never completed.
676 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
677 EXPECT_EQ(net::URLRequestStatus::CANCELED,
678 raw_ptr_resource_handler_->status().status());
680 // Release the loader. The file should be gone now.
681 ReleaseLoader();
682 base::RunLoop().RunUntilIdle();
683 EXPECT_FALSE(base::PathExists(temp_path()));
686 // Tests that a RedirectToFileResourceHandler behaves properly when the
687 // downstream handler defers OnWillStart.
688 TEST_F(ResourceLoaderRedirectToFileTest, DownstreamDeferStart) {
689 // Defer OnWillStart.
690 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
692 // Run as far as we'll go.
693 loader_->StartRequest();
694 base::RunLoop().RunUntilIdle();
696 // The request should have stopped at OnWillStart.
697 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
698 EXPECT_FALSE(raw_ptr_resource_handler_->response());
699 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
700 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
702 // Now resume the request. Now we complete.
703 raw_ptr_resource_handler_->Resume();
704 base::RunLoop().RunUntilIdle();
706 // Check that the handler forwarded all information to the downstream handler.
707 EXPECT_EQ(temp_path(),
708 raw_ptr_resource_handler_->response()->head.download_file_path);
709 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
710 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
711 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
712 raw_ptr_resource_handler_->status().status());
713 EXPECT_EQ(test_data().size(), static_cast<size_t>(
714 raw_ptr_resource_handler_->total_bytes_downloaded()));
716 // Check that the data was written to the file.
717 std::string contents;
718 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
719 EXPECT_EQ(test_data(), contents);
721 // Release the loader. The file should be gone now.
722 ReleaseLoader();
723 base::RunLoop().RunUntilIdle();
724 EXPECT_FALSE(base::PathExists(temp_path()));
727 } // namespace content