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/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"
34 using webkit_blob::ShareableFileReference;
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
42 class ClientCertStoreStub : public net::ClientCertStore {
44 ClientCertStoreStub(const net::CertificateList& certs)
48 virtual ~ClientCertStoreStub() {}
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_;
60 // Returns the number of calls to GetClientCerts().
62 return request_count_;
65 // net::ClientCertStore:
66 virtual void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
67 net::CertificateList* selected_certs,
68 const base::Closure& callback) OVERRIDE {
70 requested_authorities_ = cert_request_info.cert_authorities;
71 *selected_certs = response_;
76 const net::CertificateList response_;
78 std::vector<std::string> requested_authorities_;
81 // Arbitrary read buffer size.
82 const int kReadBufSize = 1024;
84 // Dummy implementation of ResourceHandler, instance of which is needed to
85 // initialize ResourceLoader.
86 class ResourceHandlerStub : public ResourceHandler {
88 explicit ResourceHandlerStub(net::URLRequest* request)
89 : ResourceHandler(request),
90 read_buffer_(new net::IOBuffer(kReadBufSize)),
91 defer_request_on_will_start_(false),
93 cancel_on_read_completed_(false),
95 received_response_completed_(false),
96 total_bytes_downloaded_(0) {
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;
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; }
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;
113 // If true, cancel the request in OnReadCompleted by returning false.
114 void set_defer_eof(bool defer_eof) { defer_eof_ = defer_eof; }
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_;
121 const net::URLRequestStatus& status() const { return status_; }
122 int total_bytes_downloaded() const { return total_bytes_downloaded_; }
125 controller()->Resume();
128 // ResourceHandler implementation:
129 virtual bool OnUploadProgress(int request_id,
131 uint64 size) OVERRIDE {
136 virtual bool OnRequestRedirected(int request_id,
138 ResourceResponse* response,
139 bool* defer) OVERRIDE {
144 virtual bool OnResponseStarted(int request_id,
145 ResourceResponse* response,
146 bool* defer) OVERRIDE {
147 EXPECT_FALSE(response_);
148 response_ = response;
152 virtual bool OnWillStart(int request_id,
154 bool* defer) OVERRIDE {
155 EXPECT_TRUE(start_url_.is_empty());
157 *defer = defer_request_on_will_start_;
161 virtual bool OnBeforeNetworkStart(int request_id,
163 bool* defer) OVERRIDE {
167 virtual bool OnWillRead(int request_id,
168 scoped_refptr<net::IOBuffer>* buf,
170 int min_size) OVERRIDE {
171 if (!expect_reads_) {
177 *buf_size = kReadBufSize;
181 virtual bool OnReadCompleted(int request_id,
183 bool* defer) OVERRIDE {
184 if (!expect_reads_) {
189 if (bytes_read == 0 && defer_eof_) {
190 // Only defer it once; on resumption there will be another EOF.
195 return !cancel_on_read_completed_;
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;
207 virtual void OnDataDownloaded(int request_id,
208 int bytes_downloaded) OVERRIDE {
211 total_bytes_downloaded_ += bytes_downloaded;
215 scoped_refptr<net::IOBuffer> read_buffer_;
217 bool defer_request_on_will_start_;
219 bool cancel_on_read_completed_;
223 scoped_refptr<ResourceResponse> response_;
224 bool received_response_completed_;
225 net::URLRequestStatus status_;
226 int total_bytes_downloaded_;
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 {
233 SelectCertificateBrowserClient() : call_count_(0) {}
235 virtual void SelectClientCertificate(
236 int render_process_id,
238 const net::HttpNetworkSession* network_session,
239 net::SSLCertRequestInfo* cert_request_info,
240 const base::Callback<void(net::X509Certificate*)>& callback) OVERRIDE {
242 passed_certs_ = cert_request_info->client_certs;
249 net::CertificateList passed_certs() {
250 return passed_certs_;
254 net::CertificateList passed_certs_;
258 class ResourceContextStub : public MockResourceContext {
260 explicit ResourceContextStub(net::URLRequestContext* test_request_context)
261 : MockResourceContext(test_request_context) {}
263 virtual scoped_ptr<net::ClientCertStore> CreateClientCertStore() OVERRIDE {
264 return dummy_cert_store_.Pass();
267 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
268 dummy_cert_store_ = store.Pass();
272 scoped_ptr<net::ClientCertStore> dummy_cert_store_;
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(
281 base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
282 scoped_refptr<ShareableFileReference>()));
287 class ResourceLoaderTest : public testing::Test,
288 public ResourceLoaderDelegate {
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_);
300 GURL test_url() const {
301 return net::URLRequestTestJob::test_url_1();
304 std::string test_data() const {
305 return net::URLRequestTestJob::test_data_1();
308 virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
309 scoped_ptr<ResourceHandlerStub> leaf_handler,
310 net::URLRequest* request) {
311 return leaf_handler.PassAs<ResourceHandler>();
314 virtual void SetUp() OVERRIDE {
315 const int kRenderProcessId = 1;
316 const int kRenderViewId = 2;
318 scoped_ptr<net::URLRequest> request(
319 new net::URLRequest(test_url(),
320 net::DEFAULT_PRIORITY,
322 resource_context_.GetRequestContext()));
323 raw_ptr_to_request_ = request.get();
324 ResourceRequestInfo::AllocateForTesting(request.get(),
325 ResourceType::MAIN_FRAME,
331 scoped_ptr<ResourceHandlerStub> resource_handler(
332 new ResourceHandlerStub(request.get()));
333 raw_ptr_resource_handler_ = resource_handler.get();
334 loader_.reset(new ResourceLoader(
336 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
340 // ResourceLoaderDelegate:
341 virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
342 ResourceLoader* loader,
343 net::AuthChallengeInfo* auth_info) OVERRIDE {
346 virtual bool HandleExternalProtocol(ResourceLoader* loader,
347 const GURL& url) OVERRIDE {
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 {}
356 content::TestBrowserThreadBundle thread_bundle_;
358 net::URLRequestJobFactoryImpl job_factory_;
359 net::TestURLRequestContext test_url_request_context_;
360 ResourceContextStub resource_context_;
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_;
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
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());
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>());
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;
392 // Plug in test content browser client.
393 SelectCertificateBrowserClient test_client;
394 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
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();
401 // Restore the original content browser client.
402 SetBrowserClientForTesting(old_client);
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());
408 // Check if the retrieved certificates were passed to the content browser
410 EXPECT_EQ(1, test_client.call_count());
411 EXPECT_EQ(dummy_certs, test_client.passed_certs());
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;
424 // Plug in test content browser client.
425 SelectCertificateBrowserClient test_client;
426 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
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();
433 // Restore the original content browser client.
434 SetBrowserClientForTesting(old_client);
436 // Check if the SelectClientCertificate was called on the content browser
438 EXPECT_EQ(1, test_client.call_count());
439 EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
442 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) {
443 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
445 loader_->StartRequest();
446 loader_->CancelRequest(true);
447 static_cast<ResourceController*>(loader_.get())->Resume();
450 // Tests that no invariants are broken if a ResourceHandler cancels during
452 TEST_F(ResourceLoaderTest, CancelOnReadCompleted) {
453 raw_ptr_resource_handler_->set_cancel_on_read_completed(true);
455 loader_->StartRequest();
456 base::RunLoop().RunUntilIdle();
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());
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);
468 loader_->StartRequest();
469 base::RunLoop().RunUntilIdle();
471 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
472 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
474 raw_ptr_resource_handler_->Resume();
475 base::RunLoop().RunUntilIdle();
477 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
478 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
479 raw_ptr_resource_handler_->status().status());
482 class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
484 ResourceLoaderRedirectToFileTest()
485 : file_stream_(NULL),
486 redirect_to_file_resource_handler_(NULL) {
489 base::FilePath temp_path() const { return temp_path_; }
490 ShareableFileReference* deletable_file() const {
491 return deletable_file_.get();
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_;
498 void ReleaseLoader() {
500 deletable_file_ = NULL;
504 virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
505 scoped_ptr<ResourceHandlerStub> leaf_handler,
506 net::URLRequest* request) OVERRIDE {
507 leaf_handler->set_expect_reads(false);
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());
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(
523 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
524 BrowserThread::GetMessageLoopProxyForThread(
525 BrowserThread::FILE).get());
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>();
541 scoped_ptr<net::FileStream> file_stream,
542 const CreateTemporaryFileStreamCallback& callback) {
543 base::MessageLoop::current()->PostTask(
545 base::Bind(callback, base::File::FILE_OK,
546 base::Passed(&file_stream), deletable_file_));
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_;
556 // Tests that a RedirectToFileResourceHandler works and forwards everything
558 TEST_F(ResourceLoaderRedirectToFileTest, Basic) {
559 // Run it to completion.
560 loader_->StartRequest();
561 base::RunLoop().RunUntilIdle();
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()));
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);
578 // Release the loader and the saved reference to file. The file should be gone
581 base::RunLoop().RunUntilIdle();
582 EXPECT_FALSE(base::PathExists(temp_path()));
585 // Tests that RedirectToFileResourceHandler handles errors in creating the
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));
593 // Run it to completion.
594 loader_->StartRequest();
595 base::RunLoop().RunUntilIdle();
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());
604 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
605 TEST_F(ResourceLoaderRedirectToFileTest, WriteError) {
606 file_stream()->set_forced_error(net::ERR_FAILED);
608 // Run it to completion.
609 loader_->StartRequest();
610 base::RunLoop().RunUntilIdle();
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());
622 // Release the loader. The file should be gone now.
624 base::RunLoop().RunUntilIdle();
625 EXPECT_FALSE(base::PathExists(temp_path()));
628 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
629 TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) {
630 file_stream()->set_forced_error_async(net::ERR_FAILED);
632 // Run it to completion.
633 loader_->StartRequest();
634 base::RunLoop().RunUntilIdle();
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());
646 // Release the loader. The file should be gone now.
648 base::RunLoop().RunUntilIdle();
649 EXPECT_FALSE(base::PathExists(temp_path()));
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
657 file_stream()->set_forced_error_async(net::ERR_FAILED);
658 file_stream()->ThrottleCallbacks();
660 // Run it as far as it will go.
661 loader_->StartRequest();
662 base::RunLoop().RunUntilIdle();
664 // At this point, the request should have completed.
665 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
666 raw_ptr_to_request_->status().status());
668 // However, the resource loader stack is stuck somewhere after receiving the
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());
676 // Now, release the floodgates.
677 file_stream()->ReleaseCallbacks();
678 base::RunLoop().RunUntilIdle();
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());
686 // Release the loader. The file should be gone now.
688 base::RunLoop().RunUntilIdle();
689 EXPECT_FALSE(base::PathExists(temp_path()));
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);
698 // Run as far as we'll go.
699 loader_->StartRequest();
700 base::RunLoop().RunUntilIdle();
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());
708 // Now resume the request. Now we complete.
709 raw_ptr_resource_handler_->Resume();
710 base::RunLoop().RunUntilIdle();
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()));
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);
727 // Release the loader. The file should be gone now.
729 base::RunLoop().RunUntilIdle();
730 EXPECT_FALSE(base::PathExists(temp_path()));
733 } // namespace content