Supervised user import: Listen for profile creation/deletion
[chromium-blink-merge.git] / content / browser / loader / resource_loader_unittest.cc
blob8be5ec1d0ebdc82e3b30c215e976ef44f6ca83e0
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/macros.h"
10 #include "base/message_loop/message_loop_proxy.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/client_certificate_delegate.h"
16 #include "content/public/browser/resource_request_info.h"
17 #include "content/public/common/resource_response.h"
18 #include "content/public/test/mock_resource_context.h"
19 #include "content/public/test/test_browser_context.h"
20 #include "content/public/test/test_browser_thread_bundle.h"
21 #include "content/public/test/test_renderer_host.h"
22 #include "content/test/test_content_browser_client.h"
23 #include "content/test/test_web_contents.h"
24 #include "ipc/ipc_message.h"
25 #include "net/base/io_buffer.h"
26 #include "net/base/mock_file_stream.h"
27 #include "net/base/net_errors.h"
28 #include "net/base/request_priority.h"
29 #include "net/cert/x509_certificate.h"
30 #include "net/ssl/client_cert_store.h"
31 #include "net/ssl/ssl_cert_request_info.h"
32 #include "net/url_request/url_request.h"
33 #include "net/url_request/url_request_job_factory.h"
34 #include "net/url_request/url_request_job_factory_impl.h"
35 #include "net/url_request/url_request_test_job.h"
36 #include "net/url_request/url_request_test_util.h"
37 #include "storage/browser/blob/shareable_file_reference.h"
38 #include "testing/gtest/include/gtest/gtest.h"
40 using storage::ShareableFileReference;
42 namespace content {
43 namespace {
45 // Stub client certificate store that returns a preset list of certificates for
46 // each request and records the arguments of the most recent request for later
47 // inspection.
48 class ClientCertStoreStub : public net::ClientCertStore {
49 public:
50 // Creates a new ClientCertStoreStub that returns |response| on query. It
51 // saves the number of requests and most recently certificate authorities list
52 // in |requested_authorities| and |request_count|, respectively. The caller is
53 // responsible for ensuring those pointers outlive the ClientCertStoreStub.
55 // TODO(ppi): Make the stub independent from the internal representation of
56 // SSLCertRequestInfo. For now it seems that we can neither save the
57 // scoped_refptr<> (since it is never passed to us) nor copy the entire
58 // CertificateRequestInfo (since there is no copy constructor).
59 ClientCertStoreStub(const net::CertificateList& response,
60 int* request_count,
61 std::vector<std::string>* requested_authorities)
62 : response_(response),
63 requested_authorities_(requested_authorities),
64 request_count_(request_count) {
65 requested_authorities_->clear();
66 *request_count_ = 0;
69 ~ClientCertStoreStub() override {}
71 // net::ClientCertStore:
72 void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
73 net::CertificateList* selected_certs,
74 const base::Closure& callback) override {
75 *requested_authorities_ = cert_request_info.cert_authorities;
76 ++(*request_count_);
78 *selected_certs = response_;
79 callback.Run();
82 private:
83 const net::CertificateList response_;
84 std::vector<std::string>* requested_authorities_;
85 int* request_count_;
88 // Client certificate store which destroys its resource loader before the
89 // asynchronous GetClientCerts callback is called.
90 class LoaderDestroyingCertStore : public net::ClientCertStore {
91 public:
92 // Creates a client certificate store which, when looked up, posts a task to
93 // reset |loader| and then call the callback. The caller is responsible for
94 // ensuring the pointers remain valid until the process is complete.
95 explicit LoaderDestroyingCertStore(scoped_ptr<ResourceLoader>* loader)
96 : loader_(loader) {}
98 // net::ClientCertStore:
99 void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
100 net::CertificateList* selected_certs,
101 const base::Closure& callback) override {
102 // Don't destroy |loader_| while it's on the stack.
103 base::MessageLoop::current()->PostTask(
104 FROM_HERE, base::Bind(&LoaderDestroyingCertStore::DoCallback,
105 base::Unretained(loader_), callback));
108 private:
109 static void DoCallback(scoped_ptr<ResourceLoader>* loader,
110 const base::Closure& callback) {
111 loader->reset();
112 callback.Run();
115 scoped_ptr<ResourceLoader>* loader_;
118 // A mock URLRequestJob which simulates an SSL client auth request.
119 class MockClientCertURLRequestJob : public net::URLRequestTestJob {
120 public:
121 MockClientCertURLRequestJob(net::URLRequest* request,
122 net::NetworkDelegate* network_delegate)
123 : net::URLRequestTestJob(request, network_delegate) {}
125 static std::vector<std::string> test_authorities() {
126 return std::vector<std::string>(1, "dummy");
129 // net::URLRequestTestJob:
130 void Start() override {
131 scoped_refptr<net::SSLCertRequestInfo> cert_request_info(
132 new net::SSLCertRequestInfo);
133 cert_request_info->cert_authorities = test_authorities();
134 base::MessageLoop::current()->PostTask(
135 FROM_HERE,
136 base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
137 this, cert_request_info));
140 void ContinueWithCertificate(net::X509Certificate* cert) override {
141 net::URLRequestTestJob::Start();
144 private:
145 ~MockClientCertURLRequestJob() override {}
147 DISALLOW_COPY_AND_ASSIGN(MockClientCertURLRequestJob);
150 class MockClientCertJobProtocolHandler
151 : public net::URLRequestJobFactory::ProtocolHandler {
152 public:
153 // URLRequestJobFactory::ProtocolHandler implementation:
154 net::URLRequestJob* MaybeCreateJob(
155 net::URLRequest* request,
156 net::NetworkDelegate* network_delegate) const override {
157 return new MockClientCertURLRequestJob(request, network_delegate);
161 // Arbitrary read buffer size.
162 const int kReadBufSize = 1024;
164 // Dummy implementation of ResourceHandler, instance of which is needed to
165 // initialize ResourceLoader.
166 class ResourceHandlerStub : public ResourceHandler {
167 public:
168 explicit ResourceHandlerStub(net::URLRequest* request)
169 : ResourceHandler(request),
170 read_buffer_(new net::IOBuffer(kReadBufSize)),
171 defer_request_on_will_start_(false),
172 expect_reads_(true),
173 cancel_on_read_completed_(false),
174 defer_eof_(false),
175 received_on_will_read_(false),
176 received_eof_(false),
177 received_response_completed_(false),
178 total_bytes_downloaded_(0) {
181 // If true, defers the resource load in OnWillStart.
182 void set_defer_request_on_will_start(bool defer_request_on_will_start) {
183 defer_request_on_will_start_ = defer_request_on_will_start;
186 // If true, expect OnWillRead / OnReadCompleted pairs for handling
187 // data. Otherwise, expect OnDataDownloaded.
188 void set_expect_reads(bool expect_reads) { expect_reads_ = expect_reads; }
190 // If true, cancel the request in OnReadCompleted by returning false.
191 void set_cancel_on_read_completed(bool cancel_on_read_completed) {
192 cancel_on_read_completed_ = cancel_on_read_completed;
195 // If true, cancel the request in OnReadCompleted by returning false.
196 void set_defer_eof(bool defer_eof) { defer_eof_ = defer_eof; }
198 const GURL& start_url() const { return start_url_; }
199 ResourceResponse* response() const { return response_.get(); }
200 bool received_response_completed() const {
201 return received_response_completed_;
203 const net::URLRequestStatus& status() const { return status_; }
204 int total_bytes_downloaded() const { return total_bytes_downloaded_; }
206 void Resume() {
207 controller()->Resume();
210 // ResourceHandler implementation:
211 bool OnUploadProgress(uint64 position, uint64 size) override {
212 NOTREACHED();
213 return true;
216 bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
217 ResourceResponse* response,
218 bool* defer) override {
219 NOTREACHED();
220 return true;
223 bool OnResponseStarted(ResourceResponse* response, bool* defer) override {
224 EXPECT_FALSE(response_.get());
225 response_ = response;
226 return true;
229 bool OnWillStart(const GURL& url, bool* defer) override {
230 EXPECT_TRUE(start_url_.is_empty());
231 start_url_ = url;
232 *defer = defer_request_on_will_start_;
233 return true;
236 bool OnBeforeNetworkStart(const GURL& url, bool* defer) override {
237 return true;
240 bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
241 int* buf_size,
242 int min_size) override {
243 EXPECT_TRUE(expect_reads_);
244 EXPECT_FALSE(received_on_will_read_);
245 EXPECT_FALSE(received_eof_);
246 EXPECT_FALSE(received_response_completed_);
248 *buf = read_buffer_;
249 *buf_size = kReadBufSize;
250 received_on_will_read_ = true;
251 return true;
254 bool OnReadCompleted(int bytes_read, bool* defer) override {
255 EXPECT_TRUE(received_on_will_read_);
256 EXPECT_TRUE(expect_reads_);
257 EXPECT_FALSE(received_response_completed_);
259 if (bytes_read == 0) {
260 received_eof_ = true;
261 if (defer_eof_) {
262 defer_eof_ = false;
263 *defer = true;
267 // Need another OnWillRead() call before seeing an OnReadCompleted().
268 received_on_will_read_ = false;
270 return !cancel_on_read_completed_;
273 void OnResponseCompleted(const net::URLRequestStatus& status,
274 const std::string& security_info,
275 bool* defer) override {
276 EXPECT_FALSE(received_response_completed_);
277 if (status.is_success() && expect_reads_)
278 EXPECT_TRUE(received_eof_);
280 received_response_completed_ = true;
281 status_ = status;
284 void OnDataDownloaded(int bytes_downloaded) override {
285 EXPECT_FALSE(expect_reads_);
286 total_bytes_downloaded_ += bytes_downloaded;
289 private:
290 scoped_refptr<net::IOBuffer> read_buffer_;
292 bool defer_request_on_will_start_;
293 bool expect_reads_;
294 bool cancel_on_read_completed_;
295 bool defer_eof_;
297 GURL start_url_;
298 scoped_refptr<ResourceResponse> response_;
299 bool received_on_will_read_;
300 bool received_eof_;
301 bool received_response_completed_;
302 net::URLRequestStatus status_;
303 int total_bytes_downloaded_;
306 // Test browser client that captures calls to SelectClientCertificates and
307 // records the arguments of the most recent call for later inspection.
308 class SelectCertificateBrowserClient : public TestContentBrowserClient {
309 public:
310 SelectCertificateBrowserClient() : call_count_(0) {}
312 void SelectClientCertificate(
313 WebContents* web_contents,
314 net::SSLCertRequestInfo* cert_request_info,
315 scoped_ptr<ClientCertificateDelegate> delegate) override {
316 ++call_count_;
317 passed_certs_ = cert_request_info->client_certs;
318 delegate_ = delegate.Pass();
321 int call_count() { return call_count_; }
322 net::CertificateList passed_certs() { return passed_certs_; }
324 void ContinueWithCertificate(net::X509Certificate* cert) {
325 delegate_->ContinueWithCertificate(cert);
326 delegate_.reset();
329 void CancelCertificateSelection() { delegate_.reset(); }
331 private:
332 net::CertificateList passed_certs_;
333 int call_count_;
334 scoped_ptr<ClientCertificateDelegate> delegate_;
337 class ResourceContextStub : public MockResourceContext {
338 public:
339 explicit ResourceContextStub(net::URLRequestContext* test_request_context)
340 : MockResourceContext(test_request_context) {}
342 scoped_ptr<net::ClientCertStore> CreateClientCertStore() override {
343 return dummy_cert_store_.Pass();
346 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
347 dummy_cert_store_ = store.Pass();
350 private:
351 scoped_ptr<net::ClientCertStore> dummy_cert_store_;
354 // Fails to create a temporary file with the given error.
355 void CreateTemporaryError(
356 base::File::Error error,
357 const CreateTemporaryFileStreamCallback& callback) {
358 base::MessageLoop::current()->PostTask(
359 FROM_HERE,
360 base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
361 scoped_refptr<ShareableFileReference>()));
364 } // namespace
366 class ResourceLoaderTest : public testing::Test,
367 public ResourceLoaderDelegate {
368 protected:
369 ResourceLoaderTest()
370 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
371 resource_context_(&test_url_request_context_),
372 raw_ptr_resource_handler_(NULL),
373 raw_ptr_to_request_(NULL) {
374 test_url_request_context_.set_job_factory(&job_factory_);
377 GURL test_url() const { return net::URLRequestTestJob::test_url_1(); }
379 std::string test_data() const {
380 return net::URLRequestTestJob::test_data_1();
383 virtual net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler() {
384 return net::URLRequestTestJob::CreateProtocolHandler();
387 virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
388 scoped_ptr<ResourceHandlerStub> leaf_handler,
389 net::URLRequest* request) {
390 return leaf_handler.Pass();
393 void SetUp() override {
394 job_factory_.SetProtocolHandler("test", CreateProtocolHandler());
396 browser_context_.reset(new TestBrowserContext());
397 scoped_refptr<SiteInstance> site_instance =
398 SiteInstance::Create(browser_context_.get());
399 web_contents_.reset(
400 TestWebContents::Create(browser_context_.get(), site_instance.get()));
401 RenderFrameHost* rfh = web_contents_->GetMainFrame();
403 scoped_ptr<net::URLRequest> request(
404 resource_context_.GetRequestContext()->CreateRequest(
405 test_url(),
406 net::DEFAULT_PRIORITY,
407 NULL /* delegate */));
408 raw_ptr_to_request_ = request.get();
409 ResourceRequestInfo::AllocateForTesting(
410 request.get(), RESOURCE_TYPE_MAIN_FRAME, &resource_context_,
411 rfh->GetProcess()->GetID(), rfh->GetRenderViewHost()->GetRoutingID(),
412 rfh->GetRoutingID(), true /* is_main_frame */,
413 false /* parent_is_main_frame */, true /* allow_download */,
414 false /* is_async */);
415 scoped_ptr<ResourceHandlerStub> resource_handler(
416 new ResourceHandlerStub(request.get()));
417 raw_ptr_resource_handler_ = resource_handler.get();
418 loader_.reset(new ResourceLoader(
419 request.Pass(),
420 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_),
421 this));
424 void TearDown() override {
425 // Destroy the WebContents and pump the event loop before destroying
426 // |rvh_test_enabler_| and |thread_bundle_|. This lets asynchronous cleanup
427 // tasks complete.
428 web_contents_.reset();
429 base::RunLoop().RunUntilIdle();
432 // ResourceLoaderDelegate:
433 ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
434 ResourceLoader* loader,
435 net::AuthChallengeInfo* auth_info) override {
436 return NULL;
438 bool HandleExternalProtocol(ResourceLoader* loader,
439 const GURL& url) override {
440 return false;
442 void DidStartRequest(ResourceLoader* loader) override {}
443 void DidReceiveRedirect(ResourceLoader* loader,
444 const GURL& new_url) override {}
445 void DidReceiveResponse(ResourceLoader* loader) override {}
446 void DidFinishLoading(ResourceLoader* loader) override {}
448 TestBrowserThreadBundle thread_bundle_;
449 RenderViewHostTestEnabler rvh_test_enabler_;
451 net::URLRequestJobFactoryImpl job_factory_;
452 net::TestURLRequestContext test_url_request_context_;
453 ResourceContextStub resource_context_;
454 scoped_ptr<TestBrowserContext> browser_context_;
455 scoped_ptr<TestWebContents> web_contents_;
457 // The ResourceLoader owns the URLRequest and the ResourceHandler.
458 ResourceHandlerStub* raw_ptr_resource_handler_;
459 net::URLRequest* raw_ptr_to_request_;
460 scoped_ptr<ResourceLoader> loader_;
463 class ClientCertResourceLoaderTest : public ResourceLoaderTest {
464 protected:
465 net::URLRequestJobFactory::ProtocolHandler* CreateProtocolHandler() override {
466 return new MockClientCertJobProtocolHandler;
470 // Tests that client certificates are requested with ClientCertStore lookup.
471 TEST_F(ClientCertResourceLoaderTest, WithStoreLookup) {
472 // Set up the test client cert store.
473 int store_request_count;
474 std::vector<std::string> store_requested_authorities;
475 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
476 new net::X509Certificate("test", "test", base::Time(), base::Time())));
477 scoped_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub(
478 dummy_certs, &store_request_count, &store_requested_authorities));
479 resource_context_.SetClientCertStore(test_store.Pass());
481 // Plug in test content browser client.
482 SelectCertificateBrowserClient test_client;
483 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
485 // Start the request and wait for it to pause.
486 loader_->StartRequest();
487 base::RunLoop().RunUntilIdle();
489 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
491 // Check if the test store was queried against correct |cert_authorities|.
492 EXPECT_EQ(1, store_request_count);
493 EXPECT_EQ(MockClientCertURLRequestJob::test_authorities(),
494 store_requested_authorities);
496 // Check if the retrieved certificates were passed to the content browser
497 // client.
498 EXPECT_EQ(1, test_client.call_count());
499 EXPECT_EQ(dummy_certs, test_client.passed_certs());
501 // Continue the request.
502 test_client.ContinueWithCertificate(dummy_certs[0].get());
503 base::RunLoop().RunUntilIdle();
504 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
505 EXPECT_EQ(net::OK, raw_ptr_resource_handler_->status().error());
507 // Restore the original content browser client.
508 SetBrowserClientForTesting(old_client);
511 // Tests that client certificates are requested on a platform with NULL
512 // ClientCertStore.
513 TEST_F(ClientCertResourceLoaderTest, WithNullStore) {
514 // Plug in test content browser client.
515 SelectCertificateBrowserClient test_client;
516 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
518 // Start the request and wait for it to pause.
519 loader_->StartRequest();
520 base::RunLoop().RunUntilIdle();
522 // Check if the SelectClientCertificate was called on the content browser
523 // client.
524 EXPECT_EQ(1, test_client.call_count());
525 EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
527 // Continue the request.
528 scoped_refptr<net::X509Certificate> cert(
529 new net::X509Certificate("test", "test", base::Time(), base::Time()));
530 test_client.ContinueWithCertificate(cert.get());
531 base::RunLoop().RunUntilIdle();
532 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
533 EXPECT_EQ(net::OK, raw_ptr_resource_handler_->status().error());
535 // Restore the original content browser client.
536 SetBrowserClientForTesting(old_client);
539 // Tests that the ContentBrowserClient may cancel a certificate request.
540 TEST_F(ClientCertResourceLoaderTest, CancelSelection) {
541 // Plug in test content browser client.
542 SelectCertificateBrowserClient test_client;
543 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
545 // Start the request and wait for it to pause.
546 loader_->StartRequest();
547 base::RunLoop().RunUntilIdle();
549 // Check if the SelectClientCertificate was called on the content browser
550 // client.
551 EXPECT_EQ(1, test_client.call_count());
552 EXPECT_EQ(net::CertificateList(), test_client.passed_certs());
554 // Cancel the request.
555 test_client.CancelCertificateSelection();
556 base::RunLoop().RunUntilIdle();
557 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
558 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
559 raw_ptr_resource_handler_->status().error());
561 // Restore the original content browser client.
562 SetBrowserClientForTesting(old_client);
565 // Verifies that requests without WebContents attached abort.
566 TEST_F(ClientCertResourceLoaderTest, NoWebContents) {
567 // Destroy the WebContents before starting the request.
568 web_contents_.reset();
570 // Plug in test content browser client.
571 SelectCertificateBrowserClient test_client;
572 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client);
574 // Start the request and wait for it to pause.
575 loader_->StartRequest();
576 base::RunLoop().RunUntilIdle();
578 // Check that SelectClientCertificate wasn't called and the request aborted.
579 EXPECT_EQ(0, test_client.call_count());
580 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
581 EXPECT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED,
582 raw_ptr_resource_handler_->status().error());
584 // Restore the original content browser client.
585 SetBrowserClientForTesting(old_client);
588 // Verifies that ClientCertStore's callback doesn't crash if called after the
589 // loader is destroyed.
590 TEST_F(ClientCertResourceLoaderTest, StoreAsyncCancel) {
591 scoped_ptr<LoaderDestroyingCertStore> test_store(
592 new LoaderDestroyingCertStore(&loader_));
593 resource_context_.SetClientCertStore(test_store.Pass());
595 loader_->StartRequest();
596 base::RunLoop().RunUntilIdle();
597 EXPECT_FALSE(loader_);
599 // Pump the event loop to ensure nothing asynchronous crashes either.
600 base::RunLoop().RunUntilIdle();
603 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) {
604 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
606 loader_->StartRequest();
607 loader_->CancelRequest(true);
608 static_cast<ResourceController*>(loader_.get())->Resume();
611 // Tests that no invariants are broken if a ResourceHandler cancels during
612 // OnReadCompleted.
613 TEST_F(ResourceLoaderTest, CancelOnReadCompleted) {
614 raw_ptr_resource_handler_->set_cancel_on_read_completed(true);
616 loader_->StartRequest();
617 base::RunLoop().RunUntilIdle();
619 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
620 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
621 EXPECT_EQ(net::URLRequestStatus::CANCELED,
622 raw_ptr_resource_handler_->status().status());
625 // Tests that no invariants are broken if a ResourceHandler defers EOF.
626 TEST_F(ResourceLoaderTest, DeferEOF) {
627 raw_ptr_resource_handler_->set_defer_eof(true);
629 loader_->StartRequest();
630 base::RunLoop().RunUntilIdle();
632 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
633 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
635 raw_ptr_resource_handler_->Resume();
636 base::RunLoop().RunUntilIdle();
638 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
639 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
640 raw_ptr_resource_handler_->status().status());
643 class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
644 public:
645 ResourceLoaderRedirectToFileTest()
646 : file_stream_(NULL),
647 redirect_to_file_resource_handler_(NULL) {
650 base::FilePath temp_path() const { return temp_path_; }
651 ShareableFileReference* deletable_file() const {
652 return deletable_file_.get();
654 net::testing::MockFileStream* file_stream() const { return file_stream_; }
655 RedirectToFileResourceHandler* redirect_to_file_resource_handler() const {
656 return redirect_to_file_resource_handler_;
659 void ReleaseLoader() {
660 file_stream_ = NULL;
661 deletable_file_ = NULL;
662 loader_.reset();
665 scoped_ptr<ResourceHandler> WrapResourceHandler(
666 scoped_ptr<ResourceHandlerStub> leaf_handler,
667 net::URLRequest* request) override {
668 leaf_handler->set_expect_reads(false);
670 // Make a temporary file.
671 CHECK(base::CreateTemporaryFile(&temp_path_));
672 int flags = base::File::FLAG_WRITE | base::File::FLAG_TEMPORARY |
673 base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_ASYNC;
674 base::File file(temp_path_, flags);
675 CHECK(file.IsValid());
677 // Create mock file streams and a ShareableFileReference.
678 scoped_ptr<net::testing::MockFileStream> file_stream(
679 new net::testing::MockFileStream(file.Pass(),
680 base::MessageLoopProxy::current()));
681 file_stream_ = file_stream.get();
682 deletable_file_ = ShareableFileReference::GetOrCreate(
683 temp_path_,
684 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
685 BrowserThread::GetMessageLoopProxyForThread(
686 BrowserThread::FILE).get());
688 // Inject them into the handler.
689 scoped_ptr<RedirectToFileResourceHandler> handler(
690 new RedirectToFileResourceHandler(leaf_handler.Pass(), request));
691 redirect_to_file_resource_handler_ = handler.get();
692 handler->SetCreateTemporaryFileStreamFunctionForTesting(
693 base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback,
694 base::Unretained(this),
695 base::Passed(&file_stream)));
696 return handler.Pass();
699 private:
700 void PostCallback(
701 scoped_ptr<net::FileStream> file_stream,
702 const CreateTemporaryFileStreamCallback& callback) {
703 base::MessageLoop::current()->PostTask(
704 FROM_HERE,
705 base::Bind(callback, base::File::FILE_OK,
706 base::Passed(&file_stream), deletable_file_));
709 base::FilePath temp_path_;
710 scoped_refptr<ShareableFileReference> deletable_file_;
711 // These are owned by the ResourceLoader.
712 net::testing::MockFileStream* file_stream_;
713 RedirectToFileResourceHandler* redirect_to_file_resource_handler_;
716 // Tests that a RedirectToFileResourceHandler works and forwards everything
717 // downstream.
718 TEST_F(ResourceLoaderRedirectToFileTest, Basic) {
719 // Run it to completion.
720 loader_->StartRequest();
721 base::RunLoop().RunUntilIdle();
723 // Check that the handler forwarded all information to the downstream handler.
724 EXPECT_EQ(temp_path(),
725 raw_ptr_resource_handler_->response()->head.download_file_path);
726 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
727 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
728 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
729 raw_ptr_resource_handler_->status().status());
730 EXPECT_EQ(test_data().size(), static_cast<size_t>(
731 raw_ptr_resource_handler_->total_bytes_downloaded()));
733 // Check that the data was written to the file.
734 std::string contents;
735 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
736 EXPECT_EQ(test_data(), contents);
738 // Release the loader and the saved reference to file. The file should be gone
739 // now.
740 ReleaseLoader();
741 base::RunLoop().RunUntilIdle();
742 EXPECT_FALSE(base::PathExists(temp_path()));
745 // Tests that RedirectToFileResourceHandler handles errors in creating the
746 // temporary file.
747 TEST_F(ResourceLoaderRedirectToFileTest, CreateTemporaryError) {
748 // Swap out the create temporary function.
749 redirect_to_file_resource_handler()->
750 SetCreateTemporaryFileStreamFunctionForTesting(
751 base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED));
753 // Run it to completion.
754 loader_->StartRequest();
755 base::RunLoop().RunUntilIdle();
757 // To downstream, the request was canceled.
758 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
759 EXPECT_EQ(net::URLRequestStatus::CANCELED,
760 raw_ptr_resource_handler_->status().status());
761 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
764 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
765 TEST_F(ResourceLoaderRedirectToFileTest, WriteError) {
766 file_stream()->set_forced_error(net::ERR_FAILED);
768 // Run it to completion.
769 loader_->StartRequest();
770 base::RunLoop().RunUntilIdle();
772 // To downstream, the request was canceled sometime after it started, but
773 // before any data was written.
774 EXPECT_EQ(temp_path(),
775 raw_ptr_resource_handler_->response()->head.download_file_path);
776 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
777 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
778 EXPECT_EQ(net::URLRequestStatus::CANCELED,
779 raw_ptr_resource_handler_->status().status());
780 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
782 // Release the loader. The file should be gone now.
783 ReleaseLoader();
784 base::RunLoop().RunUntilIdle();
785 EXPECT_FALSE(base::PathExists(temp_path()));
788 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
789 TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) {
790 file_stream()->set_forced_error_async(net::ERR_FAILED);
792 // Run it to completion.
793 loader_->StartRequest();
794 base::RunLoop().RunUntilIdle();
796 // To downstream, the request was canceled sometime after it started, but
797 // before any data was written.
798 EXPECT_EQ(temp_path(),
799 raw_ptr_resource_handler_->response()->head.download_file_path);
800 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
801 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
802 EXPECT_EQ(net::URLRequestStatus::CANCELED,
803 raw_ptr_resource_handler_->status().status());
804 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
806 // Release the loader. The file should be gone now.
807 ReleaseLoader();
808 base::RunLoop().RunUntilIdle();
809 EXPECT_FALSE(base::PathExists(temp_path()));
812 // Tests that RedirectToFileHandler defers completion if there are outstanding
813 // writes and accounts for errors which occur in that time.
814 TEST_F(ResourceLoaderRedirectToFileTest, DeferCompletion) {
815 // Program the MockFileStream to error asynchronously, but throttle the
816 // callback.
817 file_stream()->set_forced_error_async(net::ERR_FAILED);
818 file_stream()->ThrottleCallbacks();
820 // Run it as far as it will go.
821 loader_->StartRequest();
822 base::RunLoop().RunUntilIdle();
824 // At this point, the request should have completed.
825 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
826 raw_ptr_to_request_->status().status());
828 // However, the resource loader stack is stuck somewhere after receiving the
829 // response.
830 EXPECT_EQ(temp_path(),
831 raw_ptr_resource_handler_->response()->head.download_file_path);
832 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
833 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
834 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
836 // Now, release the floodgates.
837 file_stream()->ReleaseCallbacks();
838 base::RunLoop().RunUntilIdle();
840 // Although the URLRequest was successful, the leaf handler sees a failure
841 // because the write never completed.
842 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
843 EXPECT_EQ(net::URLRequestStatus::CANCELED,
844 raw_ptr_resource_handler_->status().status());
846 // Release the loader. The file should be gone now.
847 ReleaseLoader();
848 base::RunLoop().RunUntilIdle();
849 EXPECT_FALSE(base::PathExists(temp_path()));
852 // Tests that a RedirectToFileResourceHandler behaves properly when the
853 // downstream handler defers OnWillStart.
854 TEST_F(ResourceLoaderRedirectToFileTest, DownstreamDeferStart) {
855 // Defer OnWillStart.
856 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
858 // Run as far as we'll go.
859 loader_->StartRequest();
860 base::RunLoop().RunUntilIdle();
862 // The request should have stopped at OnWillStart.
863 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
864 EXPECT_FALSE(raw_ptr_resource_handler_->response());
865 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed());
866 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded());
868 // Now resume the request. Now we complete.
869 raw_ptr_resource_handler_->Resume();
870 base::RunLoop().RunUntilIdle();
872 // Check that the handler forwarded all information to the downstream handler.
873 EXPECT_EQ(temp_path(),
874 raw_ptr_resource_handler_->response()->head.download_file_path);
875 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url());
876 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed());
877 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
878 raw_ptr_resource_handler_->status().status());
879 EXPECT_EQ(test_data().size(), static_cast<size_t>(
880 raw_ptr_resource_handler_->total_bytes_downloaded()));
882 // Check that the data was written to the file.
883 std::string contents;
884 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents));
885 EXPECT_EQ(test_data(), contents);
887 // Release the loader. The file should be gone now.
888 ReleaseLoader();
889 base::RunLoop().RunUntilIdle();
890 EXPECT_FALSE(base::PathExists(temp_path()));
893 } // namespace content