Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / loader / resource_loader_unittest.cc
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.
4
5 #include "content/browser/loader/resource_loader.h"
6
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"
32
33 using storage::ShareableFileReference;
34
35 namespace content {
36 namespace {
37
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) {}
46
47   ~ClientCertStoreStub() override {}
48
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_;
57   }
58
59   // Returns the number of calls to GetClientCerts().
60   int request_count() {
61     return request_count_;
62   }
63
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();
72   }
73
74  private:
75   const net::CertificateList response_;
76   int request_count_;
77   std::vector<std::string> requested_authorities_;
78 };
79
80 // Arbitrary read buffer size.
81 const int kReadBufSize = 1024;
82
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) {
98   }
99
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;
103   }
104
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; }
108
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;
112   }
113
114   // If true, cancel the request in OnReadCompleted by returning false.
115   void set_defer_eof(bool defer_eof) { defer_eof_ = defer_eof; }
116
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_;
121   }
122   const net::URLRequestStatus& status() const { return status_; }
123   int total_bytes_downloaded() const { return total_bytes_downloaded_; }
124
125   void Resume() {
126     controller()->Resume();
127   }
128
129   // ResourceHandler implementation:
130   bool OnUploadProgress(uint64 position, uint64 size) override {
131     NOTREACHED();
132     return true;
133   }
134
135   bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
136                            ResourceResponse* response,
137                            bool* defer) override {
138     NOTREACHED();
139     return true;
140   }
141
142   bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
143     EXPECT_FALSE(response_.get());
144     response_ = response;
145     return true;
146   }
147
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;
153   }
154
155   bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
156     return true;
157   }
158
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_);
166
167     *buf = read_buffer_;
168     *buf_size = kReadBufSize;
169     received_on_will_read_ = true;
170     return true;
171   }
172
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_);
177
178     if (bytes_read == 0) {
179       received_eof_ = true;
180       if (defer_eof_) {
181         defer_eof_ = false;
182         *defer = true;
183       }
184     }
185
186     // Need another OnWillRead() call before seeing an OnReadCompleted().
187     received_on_will_read_ = false;
188
189     return !cancel_on_read_completed_;
190   }
191
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_);
198
199     received_response_completed_ = true;
200     status_ = status;
201   }
202
203   void OnDataDownloaded(int bytes_downloaded) override {
204     EXPECT_FALSE(expect_reads_);
205     total_bytes_downloaded_ += bytes_downloaded;
206   }
207
208  private:
209   scoped_refptr<net::IOBuffer> read_buffer_;
210
211   bool defer_request_on_will_start_;
212   bool expect_reads_;
213   bool cancel_on_read_completed_;
214   bool defer_eof_;
215
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_;
223 };
224
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) {}
230
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;
238   }
239
240   int call_count() {
241     return call_count_;
242   }
243
244   net::CertificateList passed_certs() {
245     return passed_certs_;
246   }
247
248  private:
249   net::CertificateList passed_certs_;
250   int call_count_;
251 };
252
253 class ResourceContextStub : public MockResourceContext {
254  public:
255   explicit ResourceContextStub(net::URLRequestContext* test_request_context)
256       : MockResourceContext(test_request_context) {}
257
258   scoped_ptr<net::ClientCertStore> CreateClientCertStore() override {
259     return dummy_cert_store_.Pass();
260   }
261
262   void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
263     dummy_cert_store_ = store.Pass();
264   }
265
266  private:
267   scoped_ptr<net::ClientCertStore> dummy_cert_store_;
268 };
269
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>()));
278 }
279
280 }  // namespace
281
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_);
293   }
294
295   GURL test_url() const {
296     return net::URLRequestTestJob::test_url_1();
297   }
298
299   std::string test_data() const {
300     return net::URLRequestTestJob::test_data_1();
301   }
302
303   virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
304       scoped_ptr<ResourceHandlerStub> leaf_handler,
305       net::URLRequest* request) {
306     return leaf_handler.Pass();
307   }
308
309   void SetUp() override {
310     const int kRenderProcessId = 1;
311     const int kRenderViewId = 2;
312
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));
334   }
335
336   // ResourceLoaderDelegate:
337   ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
338       ResourceLoader* loader,
339       net::AuthChallengeInfo* auth_info) override {
340     return NULL;
341   }
342   bool HandleExternalProtocol(ResourceLoader* loader,
343                               const GURL& url) override {
344     return false;
345   }
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 {}
351
352   content::TestBrowserThreadBundle thread_bundle_;
353
354   net::URLRequestJobFactoryImpl job_factory_;
355   net::TestURLRequestContext test_url_request_context_;
356   ResourceContextStub resource_context_;
357
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_;
362 };
363
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());
375
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());
380
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;
386
387   // Plug in test content browser client.
388   SelectCertificateBrowserClient test_client;
389   ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
390
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();
395
396   // Restore the original content browser client.
397   SetBrowserClientForTesting(old_client);
398
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());
402
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());
407 }
408
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;
418
419   // Plug in test content browser client.
420   SelectCertificateBrowserClient test_client;
421   ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
422
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();
427
428   // Restore the original content browser client.
429   SetBrowserClientForTesting(old_client);
430
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());
435 }
436
437 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) {
438   raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
439
440   loader_->StartRequest();
441   loader_->CancelRequest(true);
442   static_cast<ResourceController*>(loader_.get())->Resume();
443 }
444
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);
449
450   loader_->StartRequest();
451   base::RunLoop().RunUntilIdle();
452
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());
457 }
458
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);
462
463   loader_->StartRequest();
464   base::RunLoop().RunUntilIdle();
465
466   EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
467   EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
468
469   raw_ptr_resource_handler_->Resume();
470   base::RunLoop().RunUntilIdle();
471
472   EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
473   EXPECT_EQ(net::URLRequestStatus::SUCCESS,
474             raw_ptr_resource_handler_->status().status());
475 }
476
477 class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
478  public:
479   ResourceLoaderRedirectToFileTest()
480       : file_stream_(NULL),
481         redirect_to_file_resource_handler_(NULL) {
482   }
483
484   base::FilePath temp_path() const { return temp_path_; }
485   ShareableFileReference* deletable_file() const {
486     return deletable_file_.get();
487   }
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_;
491   }
492
493   void ReleaseLoader() {
494     file_stream_ = NULL;
495     deletable_file_ = NULL;
496     loader_.reset();
497   }
498
499   scoped_ptr<ResourceHandler> WrapResourceHandler(
500       scoped_ptr<ResourceHandlerStub> leaf_handler,
501       net::URLRequest* request) override {
502     leaf_handler->set_expect_reads(false);
503
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());
510
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());
521
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();
531   }
532
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_));
541   }
542
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_;
548 };
549
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();
556
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()));
566
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);
571
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()));
577 }
578
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));
586
587   // Run it to completion.
588   loader_->StartRequest();
589   base::RunLoop().RunUntilIdle();
590
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());
596 }
597
598 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
599 TEST_F(ResourceLoaderRedirectToFileTest, WriteError) {
600   file_stream()->set_forced_error(net::ERR_FAILED);
601
602   // Run it to completion.
603   loader_->StartRequest();
604   base::RunLoop().RunUntilIdle();
605
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());
615
616   // Release the loader. The file should be gone now.
617   ReleaseLoader();
618   base::RunLoop().RunUntilIdle();
619   EXPECT_FALSE(base::PathExists(temp_path()));
620 }
621
622 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
623 TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) {
624   file_stream()->set_forced_error_async(net::ERR_FAILED);
625
626   // Run it to completion.
627   loader_->StartRequest();
628   base::RunLoop().RunUntilIdle();
629
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());
639
640   // Release the loader. The file should be gone now.
641   ReleaseLoader();
642   base::RunLoop().RunUntilIdle();
643   EXPECT_FALSE(base::PathExists(temp_path()));
644 }
645
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();
653
654   // Run it as far as it will go.
655   loader_->StartRequest();
656   base::RunLoop().RunUntilIdle();
657
658   // At this point, the request should have completed.
659   EXPECT_EQ(net::URLRequestStatus::SUCCESS,
660             raw_ptr_to_request_->status().status());
661
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());
669
670   // Now, release the floodgates.
671   file_stream()->ReleaseCallbacks();
672   base::RunLoop().RunUntilIdle();
673
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());
679
680   // Release the loader. The file should be gone now.
681   ReleaseLoader();
682   base::RunLoop().RunUntilIdle();
683   EXPECT_FALSE(base::PathExists(temp_path()));
684 }
685
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);
691
692   // Run as far as we'll go.
693   loader_->StartRequest();
694   base::RunLoop().RunUntilIdle();
695
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());
701
702   // Now resume the request. Now we complete.
703   raw_ptr_resource_handler_->Resume();
704   base::RunLoop().RunUntilIdle();
705
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()));
715
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);
720
721   // Release the loader. The file should be gone now.
722   ReleaseLoader();
723   base::RunLoop().RunUntilIdle();
724   EXPECT_FALSE(base::PathExists(temp_path()));
725 }
726
727 }  // namespace content