Upstream version 7.36.149.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/file_util.h"
8 #include "base/files/file.h"
9 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/platform_file.h"
11 #include "base/run_loop.h"
12 #include "content/browser/browser_thread_impl.h"
13 #include "content/browser/loader/redirect_to_file_resource_handler.h"
14 #include "content/browser/loader/resource_loader_delegate.h"
15 #include "content/public/browser/resource_request_info.h"
16 #include "content/public/common/resource_response.h"
17 #include "content/public/test/mock_resource_context.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "content/test/test_content_browser_client.h"
20 #include "ipc/ipc_message.h"
21 #include "net/base/io_buffer.h"
22 #include "net/base/mock_file_stream.h"
23 #include "net/base/request_priority.h"
24 #include "net/cert/x509_certificate.h"
25 #include "net/ssl/client_cert_store.h"
26 #include "net/ssl/ssl_cert_request_info.h"
27 #include "net/url_request/url_request.h"
28 #include "net/url_request/url_request_job_factory_impl.h"
29 #include "net/url_request/url_request_test_job.h"
30 #include "net/url_request/url_request_test_util.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 #include "webkit/common/blob/shareable_file_reference.h"
33
34 using webkit_blob::ShareableFileReference;
35
36 namespace content {
37 namespace {
38
39 // Stub client certificate store that returns a preset list of certificates for
40 // each request and records the arguments of the most recent request for later
41 // inspection.
42 class ClientCertStoreStub : public net::ClientCertStore {
43  public:
44   ClientCertStoreStub(const net::CertificateList& certs)
45       : response_(certs),
46         request_count_(0) {}
47
48   virtual ~ClientCertStoreStub() {}
49
50   // Returns |cert_authorities| field of the certificate request passed in the
51   // most recent call to GetClientCerts().
52   // TODO(ppi): Make the stub independent from the internal representation of
53   // SSLCertRequestInfo. For now it seems that we cannot neither save the
54   // scoped_refptr<> (since it is never passed to us) nor copy the entire
55   // CertificateRequestInfo (since there is no copy constructor).
56   std::vector<std::string> requested_authorities() {
57     return requested_authorities_;
58   }
59
60   // Returns the number of calls to GetClientCerts().
61   int request_count() {
62     return request_count_;
63   }
64
65   // net::ClientCertStore:
66   virtual void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
67                               net::CertificateList* selected_certs,
68                               const base::Closure& callback) OVERRIDE {
69     ++request_count_;
70     requested_authorities_ = cert_request_info.cert_authorities;
71     *selected_certs = response_;
72     callback.Run();
73   }
74
75  private:
76   const net::CertificateList response_;
77   int request_count_;
78   std::vector<std::string> requested_authorities_;
79 };
80
81 // Arbitrary read buffer size.
82 const int kReadBufSize = 1024;
83
84 // Dummy implementation of ResourceHandler, instance of which is needed to
85 // initialize ResourceLoader.
86 class ResourceHandlerStub : public ResourceHandler {
87  public:
88   explicit ResourceHandlerStub(net::URLRequest* request)
89       : ResourceHandler(request),
90         read_buffer_(new net::IOBuffer(kReadBufSize)),
91         defer_request_on_will_start_(false),
92         expect_reads_(true),
93         cancel_on_read_completed_(false),
94         defer_eof_(false),
95         received_response_completed_(false),
96         total_bytes_downloaded_(0) {
97   }
98
99   // If true, defers the resource load in OnWillStart.
100   void set_defer_request_on_will_start(bool defer_request_on_will_start) {
101     defer_request_on_will_start_ = defer_request_on_will_start;
102   }
103
104   // If true, expect OnWillRead / OnReadCompleted pairs for handling
105   // data. Otherwise, expect OnDataDownloaded.
106   void set_expect_reads(bool expect_reads) { expect_reads_ = expect_reads; }
107
108   // If true, cancel the request in OnReadCompleted by returning false.
109   void set_cancel_on_read_completed(bool cancel_on_read_completed) {
110     cancel_on_read_completed_ = cancel_on_read_completed;
111   }
112
113   // If true, cancel the request in OnReadCompleted by returning false.
114   void set_defer_eof(bool defer_eof) { defer_eof_ = defer_eof; }
115
116   const GURL& start_url() const { return start_url_; }
117   ResourceResponse* response() const { return response_.get(); }
118   bool received_response_completed() const {
119     return received_response_completed_;
120   }
121   const net::URLRequestStatus& status() const { return status_; }
122   int total_bytes_downloaded() const { return total_bytes_downloaded_; }
123
124   void Resume() {
125     controller()->Resume();
126   }
127
128   // ResourceHandler implementation:
129   virtual bool OnUploadProgress(int request_id,
130                                 uint64 position,
131                                 uint64 size) OVERRIDE {
132     NOTREACHED();
133     return true;
134   }
135
136   virtual bool OnRequestRedirected(int request_id,
137                                    const GURL& url,
138                                    ResourceResponse* response,
139                                    bool* defer) OVERRIDE {
140     NOTREACHED();
141     return true;
142   }
143
144   virtual bool OnResponseStarted(int request_id,
145                                  ResourceResponse* response,
146                                  bool* defer) OVERRIDE {
147     EXPECT_FALSE(response_);
148     response_ = response;
149     return true;
150   }
151
152   virtual bool OnWillStart(int request_id,
153                            const GURL& url,
154                            bool* defer) OVERRIDE {
155     EXPECT_TRUE(start_url_.is_empty());
156     start_url_ = url;
157     *defer = defer_request_on_will_start_;
158     return true;
159   }
160
161   virtual bool OnBeforeNetworkStart(int request_id,
162                                     const GURL& url,
163                                     bool* defer) OVERRIDE {
164     return true;
165   }
166
167   virtual bool OnWillRead(int request_id,
168                           scoped_refptr<net::IOBuffer>* buf,
169                           int* buf_size,
170                           int min_size) OVERRIDE {
171     if (!expect_reads_) {
172       ADD_FAILURE();
173       return false;
174     }
175
176     *buf = read_buffer_;
177     *buf_size = kReadBufSize;
178     return true;
179   }
180
181   virtual bool OnReadCompleted(int request_id,
182                                int bytes_read,
183                                bool* defer) OVERRIDE {
184     if (!expect_reads_) {
185       ADD_FAILURE();
186       return false;
187     }
188
189     if (bytes_read == 0 && defer_eof_) {
190       // Only defer it once; on resumption there will be another EOF.
191       defer_eof_ = false;
192       *defer = true;
193     }
194
195     return !cancel_on_read_completed_;
196   }
197
198   virtual void OnResponseCompleted(int request_id,
199                                    const net::URLRequestStatus& status,
200                                    const std::string& security_info,
201                                    bool* defer) OVERRIDE {
202     EXPECT_FALSE(received_response_completed_);
203     received_response_completed_ = true;
204     status_ = status;
205   }
206
207   virtual void OnDataDownloaded(int request_id,
208                                 int bytes_downloaded) OVERRIDE {
209     if (expect_reads_)
210       ADD_FAILURE();
211     total_bytes_downloaded_ += bytes_downloaded;
212   }
213
214  private:
215   scoped_refptr<net::IOBuffer> read_buffer_;
216
217   bool defer_request_on_will_start_;
218   bool expect_reads_;
219   bool cancel_on_read_completed_;
220   bool defer_eof_;
221
222   GURL start_url_;
223   scoped_refptr<ResourceResponse> response_;
224   bool received_response_completed_;
225   net::URLRequestStatus status_;
226   int total_bytes_downloaded_;
227 };
228
229 // Test browser client that captures calls to SelectClientCertificates and
230 // records the arguments of the most recent call for later inspection.
231 class SelectCertificateBrowserClient : public TestContentBrowserClient {
232  public:
233   SelectCertificateBrowserClient() : call_count_(0) {}
234
235   virtual void SelectClientCertificate(
236       int render_process_id,
237       int render_view_id,
238       const net::HttpNetworkSession* network_session,
239       net::SSLCertRequestInfo* cert_request_info,
240       const base::Callback<void(net::X509Certificate*)>& callback) OVERRIDE {
241     ++call_count_;
242     passed_certs_ = cert_request_info->client_certs;
243   }
244
245   int call_count() {
246     return call_count_;
247   }
248
249   net::CertificateList passed_certs() {
250     return passed_certs_;
251   }
252
253  private:
254   net::CertificateList passed_certs_;
255   int call_count_;
256 };
257
258 class ResourceContextStub : public MockResourceContext {
259  public:
260   explicit ResourceContextStub(net::URLRequestContext* test_request_context)
261       : MockResourceContext(test_request_context) {}
262
263   virtual scoped_ptr<net::ClientCertStore> CreateClientCertStore() OVERRIDE {
264     return dummy_cert_store_.Pass();
265   }
266
267   void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
268     dummy_cert_store_ = store.Pass();
269   }
270
271  private:
272   scoped_ptr<net::ClientCertStore> dummy_cert_store_;
273 };
274
275 // Fails to create a temporary file with the given error.
276 void CreateTemporaryError(
277     base::File::Error error,
278     const CreateTemporaryFileStreamCallback& callback) {
279   base::MessageLoop::current()->PostTask(
280       FROM_HERE,
281       base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
282                  scoped_refptr<ShareableFileReference>()));
283 }
284
285 }  // namespace
286
287 class ResourceLoaderTest : public testing::Test,
288                            public ResourceLoaderDelegate {
289  protected:
290   ResourceLoaderTest()
291     : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
292       resource_context_(&test_url_request_context_),
293       raw_ptr_resource_handler_(NULL),
294       raw_ptr_to_request_(NULL) {
295     job_factory_.SetProtocolHandler(
296         "test", net::URLRequestTestJob::CreateProtocolHandler());
297     test_url_request_context_.set_job_factory(&job_factory_);
298   }
299
300   GURL test_url() const {
301     return net::URLRequestTestJob::test_url_1();
302   }
303
304   std::string test_data() const {
305     return net::URLRequestTestJob::test_data_1();
306   }
307
308   virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
309       scoped_ptr<ResourceHandlerStub> leaf_handler,
310       net::URLRequest* request) {
311     return leaf_handler.PassAs<ResourceHandler>();
312   }
313
314   virtual void SetUp() OVERRIDE {
315     const int kRenderProcessId = 1;
316     const int kRenderViewId = 2;
317
318     scoped_ptr<net::URLRequest> request(
319         new net::URLRequest(test_url(),
320                             net::DEFAULT_PRIORITY,
321                             NULL,
322                             resource_context_.GetRequestContext()));
323     raw_ptr_to_request_ = request.get();
324     ResourceRequestInfo::AllocateForTesting(request.get(),
325                                             ResourceType::MAIN_FRAME,
326                                             &resource_context_,
327                                             kRenderProcessId,
328                                             kRenderViewId,
329                                             MSG_ROUTING_NONE,
330                                             false);
331     scoped_ptr<ResourceHandlerStub> resource_handler(
332         new ResourceHandlerStub(request.get()));
333     raw_ptr_resource_handler_ = resource_handler.get();
334     loader_.reset(new ResourceLoader(
335         request.Pass(),
336         WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
337         this));
338   }
339
340   // ResourceLoaderDelegate:
341   virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
342       ResourceLoader* loader,
343       net::AuthChallengeInfo* auth_info) OVERRIDE {
344     return NULL;
345   }
346   virtual bool HandleExternalProtocol(ResourceLoader* loader,
347                                       const GURL& url) OVERRIDE {
348     return false;
349   }
350   virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {}
351   virtual void DidReceiveRedirect(ResourceLoader* loader,
352                                   const GURL& new_url) OVERRIDE {}
353   virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {}
354   virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {}
355
356   content::TestBrowserThreadBundle thread_bundle_;
357
358   net::URLRequestJobFactoryImpl job_factory_;
359   net::TestURLRequestContext test_url_request_context_;
360   ResourceContextStub resource_context_;
361
362   // The ResourceLoader owns the URLRequest and the ResourceHandler.
363   ResourceHandlerStub* raw_ptr_resource_handler_;
364   net::URLRequest* raw_ptr_to_request_;
365   scoped_ptr<ResourceLoader> loader_;
366 };
367
368 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested()
369 // causes client cert store to be queried for certificates and if the returned
370 // certificates are correctly passed to the content browser client for
371 // selection.
372 TEST_F(ResourceLoaderTest, ClientCertStoreLookup) {
373   // Set up the test client cert store.
374   net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
375       new net::X509Certificate("test", "test", base::Time(), base::Time())));
376   scoped_ptr<ClientCertStoreStub> test_store(
377       new ClientCertStoreStub(dummy_certs));
378   EXPECT_EQ(0, test_store->request_count());
379
380   // Ownership of the |test_store| is about to be turned over to ResourceLoader.
381   // We need to keep raw pointer copies to access these objects later.
382   ClientCertStoreStub* raw_ptr_to_store = test_store.get();
383   resource_context_.SetClientCertStore(
384       test_store.PassAs<net::ClientCertStore>());
385
386   // Prepare a dummy certificate request.
387   scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
388       new net::SSLCertRequestInfo());
389   std::vector<std::string> dummy_authority(1, "dummy");
390   cert_request_info->cert_authorities = dummy_authority;
391
392   // Plug in test content browser client.
393   SelectCertificateBrowserClient test_client;
394   ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
395
396   // Everything is set up. Trigger the resource loader certificate request event
397   // and run the message loop.
398   loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get());
399   base::RunLoop().RunUntilIdle();
400
401   // Restore the original content browser client.
402   SetBrowserClientForTesting(old_client);
403
404   // Check if the test store was queried against correct |cert_authorities|.
405   EXPECT_EQ(1, raw_ptr_to_store->request_count());
406   EXPECT_EQ(dummy_authority, raw_ptr_to_store->requested_authorities());
407
408   // Check if the retrieved certificates were passed to the content browser
409   // client.
410   EXPECT_EQ(1, test_client.call_count());
411   EXPECT_EQ(dummy_certs, test_client.passed_certs());
412 }
413
414 // Verifies if a call to net::URLRequest::Delegate::OnCertificateRequested()
415 // on a platform with a NULL client cert store still calls the content browser
416 // client for selection.
417 TEST_F(ResourceLoaderTest, ClientCertStoreNull) {
418   // Prepare a dummy certificate request.
419   scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
420       new net::SSLCertRequestInfo());
421   std::vector<std::string> dummy_authority(1, "dummy");
422   cert_request_info->cert_authorities = dummy_authority;
423
424   // Plug in test content browser client.
425   SelectCertificateBrowserClient test_client;
426   ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
427
428   // Everything is set up. Trigger the resource loader certificate request event
429   // and run the message loop.
430   loader_->OnCertificateRequested(raw_ptr_to_request_, cert_request_info.get());
431   base::RunLoop().RunUntilIdle();
432
433   // Restore the original content browser client.
434   SetBrowserClientForTesting(old_client);
435
436   // Check if the SelectClientCertificate was called on the content browser
437   // client.
438   EXPECT_EQ(1, test_client.call_count());
439   EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
440 }
441
442 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) {
443   raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
444
445   loader_->StartRequest();
446   loader_->CancelRequest(true);
447   static_cast<ResourceController*>(loader_.get())->Resume();
448 }
449
450 // Tests that no invariants are broken if a ResourceHandler cancels during
451 // OnReadCompleted.
452 TEST_F(ResourceLoaderTest, CancelOnReadCompleted) {
453   raw_ptr_resource_handler_->set_cancel_on_read_completed(true);
454
455   loader_->StartRequest();
456   base::RunLoop().RunUntilIdle();
457
458   EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
459   EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
460   EXPECT_EQ(net::URLRequestStatus::CANCELED,
461             raw_ptr_resource_handler_->status().status());
462 }
463
464 // Tests that no invariants are broken if a ResourceHandler defers EOF.
465 TEST_F(ResourceLoaderTest, DeferEOF) {
466   raw_ptr_resource_handler_->set_defer_eof(true);
467
468   loader_->StartRequest();
469   base::RunLoop().RunUntilIdle();
470
471   EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
472   EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
473
474   raw_ptr_resource_handler_->Resume();
475   base::RunLoop().RunUntilIdle();
476
477   EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
478   EXPECT_EQ(net::URLRequestStatus::SUCCESS,
479             raw_ptr_resource_handler_->status().status());
480 }
481
482 class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
483  public:
484   ResourceLoaderRedirectToFileTest()
485       : file_stream_(NULL),
486         redirect_to_file_resource_handler_(NULL) {
487   }
488
489   base::FilePath temp_path() const { return temp_path_; }
490   ShareableFileReference* deletable_file() const {
491     return deletable_file_.get();
492   }
493   net::testing::MockFileStream* file_stream() const { return file_stream_; }
494   RedirectToFileResourceHandler* redirect_to_file_resource_handler() const {
495     return redirect_to_file_resource_handler_;
496   }
497
498   void ReleaseLoader() {
499     file_stream_ = NULL;
500     deletable_file_ = NULL;
501     loader_.reset();
502   }
503
504   virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
505       scoped_ptr<ResourceHandlerStub> leaf_handler,
506       net::URLRequest* request) OVERRIDE {
507     leaf_handler->set_expect_reads(false);
508
509     // Make a temporary file.
510     CHECK(base::CreateTemporaryFile(&temp_path_));
511     int flags = base::File::FLAG_WRITE | base::File::FLAG_TEMPORARY |
512                 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_ASYNC;
513     base::File file(temp_path_, flags);
514     CHECK(file.IsValid());
515
516     // Create mock file streams and a ShareableFileReference.
517     scoped_ptr<net::testing::MockFileStream> file_stream(
518         new net::testing::MockFileStream(file.Pass(),
519                                          base::MessageLoopProxy::current()));
520     file_stream_ = file_stream.get();
521     deletable_file_ = ShareableFileReference::GetOrCreate(
522         temp_path_,
523         ShareableFileReference::DELETE_ON_FINAL_RELEASE,
524         BrowserThread::GetMessageLoopProxyForThread(
525             BrowserThread::FILE).get());
526
527     // Inject them into the handler.
528     scoped_ptr<RedirectToFileResourceHandler> handler(
529         new RedirectToFileResourceHandler(
530             leaf_handler.PassAs<ResourceHandler>(), request));
531     redirect_to_file_resource_handler_ = handler.get();
532     handler->SetCreateTemporaryFileStreamFunctionForTesting(
533         base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback,
534                    base::Unretained(this),
535                    base::Passed(file_stream.PassAs<net::FileStream>())));
536     return handler.PassAs<ResourceHandler>();
537   }
538
539  private:
540   void PostCallback(
541       scoped_ptr<net::FileStream> file_stream,
542       const CreateTemporaryFileStreamCallback& callback) {
543     base::MessageLoop::current()->PostTask(
544         FROM_HERE,
545         base::Bind(callback, base::File::FILE_OK,
546                    base::Passed(&file_stream), deletable_file_));
547   }
548
549   base::FilePath temp_path_;
550   scoped_refptr<ShareableFileReference> deletable_file_;
551   // These are owned by the ResourceLoader.
552   net::testing::MockFileStream* file_stream_;
553   RedirectToFileResourceHandler* redirect_to_file_resource_handler_;
554 };
555
556 // Tests that a RedirectToFileResourceHandler works and forwards everything
557 // downstream.
558 TEST_F(ResourceLoaderRedirectToFileTest, Basic) {
559   // Run it to completion.
560   loader_->StartRequest();
561   base::RunLoop().RunUntilIdle();
562
563   // Check that the handler forwarded all information to the downstream handler.
564   EXPECT_EQ(temp_path(),
565             raw_ptr_resource_handler_->response()->head.download_file_path);
566   EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
567   EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
568   EXPECT_EQ(net::URLRequestStatus::SUCCESS,
569             raw_ptr_resource_handler_->status().status());
570   EXPECT_EQ(test_data().size(), static_cast<size_t>(
571       raw_ptr_resource_handler_->total_bytes_downloaded()));
572
573   // Check that the data was written to the file.
574   std::string contents;
575   ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
576   EXPECT_EQ(test_data(), contents);
577
578   // Release the loader and the saved reference to file. The file should be gone
579   // now.
580   ReleaseLoader();
581   base::RunLoop().RunUntilIdle();
582   EXPECT_FALSE(base::PathExists(temp_path()));
583 }
584
585 // Tests that RedirectToFileResourceHandler handles errors in creating the
586 // temporary file.
587 TEST_F(ResourceLoaderRedirectToFileTest, CreateTemporaryError) {
588   // Swap out the create temporary function.
589   redirect_to_file_resource_handler()->
590       SetCreateTemporaryFileStreamFunctionForTesting(
591           base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED));
592
593   // Run it to completion.
594   loader_->StartRequest();
595   base::RunLoop().RunUntilIdle();
596
597   // To downstream, the request was canceled.
598   EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
599   EXPECT_EQ(net::URLRequestStatus::CANCELED,
600             raw_ptr_resource_handler_->status().status());
601   EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
602 }
603
604 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
605 TEST_F(ResourceLoaderRedirectToFileTest, WriteError) {
606   file_stream()->set_forced_error(net::ERR_FAILED);
607
608   // Run it to completion.
609   loader_->StartRequest();
610   base::RunLoop().RunUntilIdle();
611
612   // To downstream, the request was canceled sometime after it started, but
613   // before any data was written.
614   EXPECT_EQ(temp_path(),
615             raw_ptr_resource_handler_->response()->head.download_file_path);
616   EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
617   EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
618   EXPECT_EQ(net::URLRequestStatus::CANCELED,
619             raw_ptr_resource_handler_->status().status());
620   EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
621
622   // Release the loader. The file should be gone now.
623   ReleaseLoader();
624   base::RunLoop().RunUntilIdle();
625   EXPECT_FALSE(base::PathExists(temp_path()));
626 }
627
628 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
629 TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) {
630   file_stream()->set_forced_error_async(net::ERR_FAILED);
631
632   // Run it to completion.
633   loader_->StartRequest();
634   base::RunLoop().RunUntilIdle();
635
636   // To downstream, the request was canceled sometime after it started, but
637   // before any data was written.
638   EXPECT_EQ(temp_path(),
639             raw_ptr_resource_handler_->response()->head.download_file_path);
640   EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
641   EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
642   EXPECT_EQ(net::URLRequestStatus::CANCELED,
643             raw_ptr_resource_handler_->status().status());
644   EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
645
646   // Release the loader. The file should be gone now.
647   ReleaseLoader();
648   base::RunLoop().RunUntilIdle();
649   EXPECT_FALSE(base::PathExists(temp_path()));
650 }
651
652 // Tests that RedirectToFileHandler defers completion if there are outstanding
653 // writes and accounts for errors which occur in that time.
654 TEST_F(ResourceLoaderRedirectToFileTest, DeferCompletion) {
655   // Program the MockFileStream to error asynchronously, but throttle the
656   // callback.
657   file_stream()->set_forced_error_async(net::ERR_FAILED);
658   file_stream()->ThrottleCallbacks();
659
660   // Run it as far as it will go.
661   loader_->StartRequest();
662   base::RunLoop().RunUntilIdle();
663
664   // At this point, the request should have completed.
665   EXPECT_EQ(net::URLRequestStatus::SUCCESS,
666             raw_ptr_to_request_->status().status());
667
668   // However, the resource loader stack is stuck somewhere after receiving the
669   // response.
670   EXPECT_EQ(temp_path(),
671             raw_ptr_resource_handler_->response()->head.download_file_path);
672   EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
673   EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
674   EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
675
676   // Now, release the floodgates.
677   file_stream()->ReleaseCallbacks();
678   base::RunLoop().RunUntilIdle();
679
680   // Although the URLRequest was successful, the leaf handler sees a failure
681   // because the write never completed.
682   EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
683   EXPECT_EQ(net::URLRequestStatus::CANCELED,
684             raw_ptr_resource_handler_->status().status());
685
686   // Release the loader. The file should be gone now.
687   ReleaseLoader();
688   base::RunLoop().RunUntilIdle();
689   EXPECT_FALSE(base::PathExists(temp_path()));
690 }
691
692 // Tests that a RedirectToFileResourceHandler behaves properly when the
693 // downstream handler defers OnWillStart.
694 TEST_F(ResourceLoaderRedirectToFileTest, DownstreamDeferStart) {
695   // Defer OnWillStart.
696   raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
697
698   // Run as far as we'll go.
699   loader_->StartRequest();
700   base::RunLoop().RunUntilIdle();
701
702   // The request should have stopped at OnWillStart.
703   EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
704   EXPECT_FALSE(raw_ptr_resource_handler_->response());
705   EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
706   EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
707
708   // Now resume the request. Now we complete.
709   raw_ptr_resource_handler_->Resume();
710   base::RunLoop().RunUntilIdle();
711
712   // Check that the handler forwarded all information to the downstream handler.
713   EXPECT_EQ(temp_path(),
714             raw_ptr_resource_handler_->response()->head.download_file_path);
715   EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
716   EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
717   EXPECT_EQ(net::URLRequestStatus::SUCCESS,
718             raw_ptr_resource_handler_->status().status());
719   EXPECT_EQ(test_data().size(), static_cast<size_t>(
720       raw_ptr_resource_handler_->total_bytes_downloaded()));
721
722   // Check that the data was written to the file.
723   std::string contents;
724   ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
725   EXPECT_EQ(test_data(), contents);
726
727   // Release the loader. The file should be gone now.
728   ReleaseLoader();
729   base::RunLoop().RunUntilIdle();
730   EXPECT_FALSE(base::PathExists(temp_path()));
731 }
732
733 }  // namespace content