Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(66)

Side by Side Diff: content/browser/loader/resource_loader_unittest.cc

Issue 82273002: Fix various issues in RedirectToFileResourceHandler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Code duplication from rebase. Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/loader/resource_loader.h" 5 #include "content/browser/loader/resource_loader.h"
6 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"
7 #include "base/run_loop.h" 11 #include "base/run_loop.h"
8 #include "content/browser/browser_thread_impl.h" 12 #include "content/browser/browser_thread_impl.h"
13 #include "content/browser/loader/redirect_to_file_resource_handler.h"
9 #include "content/browser/loader/resource_loader_delegate.h" 14 #include "content/browser/loader/resource_loader_delegate.h"
10 #include "content/public/browser/resource_request_info.h" 15 #include "content/public/browser/resource_request_info.h"
16 #include "content/public/common/resource_response.h"
11 #include "content/public/test/mock_resource_context.h" 17 #include "content/public/test/mock_resource_context.h"
12 #include "content/public/test/test_browser_thread_bundle.h" 18 #include "content/public/test/test_browser_thread_bundle.h"
13 #include "content/test/test_content_browser_client.h" 19 #include "content/test/test_content_browser_client.h"
14 #include "ipc/ipc_message.h" 20 #include "ipc/ipc_message.h"
21 #include "net/base/mock_file_stream.h"
15 #include "net/base/request_priority.h" 22 #include "net/base/request_priority.h"
16 #include "net/cert/x509_certificate.h" 23 #include "net/cert/x509_certificate.h"
17 #include "net/ssl/client_cert_store.h" 24 #include "net/ssl/client_cert_store.h"
18 #include "net/ssl/ssl_cert_request_info.h" 25 #include "net/ssl/ssl_cert_request_info.h"
19 #include "net/url_request/url_request.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"
20 #include "net/url_request/url_request_test_util.h" 29 #include "net/url_request/url_request_test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h" 30 #include "testing/gtest/include/gtest/gtest.h"
31 #include "webkit/common/blob/shareable_file_reference.h"
32
33 using webkit_blob::ShareableFileReference;
22 34
23 namespace content { 35 namespace content {
24 namespace { 36 namespace {
25 37
26 // Stub client certificate store that returns a preset list of certificates for 38 // Stub client certificate store that returns a preset list of certificates for
27 // each request and records the arguments of the most recent request for later 39 // each request and records the arguments of the most recent request for later
28 // inspection. 40 // inspection.
29 class ClientCertStoreStub : public net::ClientCertStore { 41 class ClientCertStoreStub : public net::ClientCertStore {
30 public: 42 public:
31 ClientCertStoreStub(const net::CertificateList& certs) 43 ClientCertStoreStub(const net::CertificateList& certs)
(...skipping 30 matching lines...) Expand all
62 private: 74 private:
63 const net::CertificateList response_; 75 const net::CertificateList response_;
64 int request_count_; 76 int request_count_;
65 std::vector<std::string> requested_authorities_; 77 std::vector<std::string> requested_authorities_;
66 }; 78 };
67 79
68 // Dummy implementation of ResourceHandler, instance of which is needed to 80 // Dummy implementation of ResourceHandler, instance of which is needed to
69 // initialize ResourceLoader. 81 // initialize ResourceLoader.
70 class ResourceHandlerStub : public ResourceHandler { 82 class ResourceHandlerStub : public ResourceHandler {
71 public: 83 public:
72 ResourceHandlerStub() 84 explicit ResourceHandlerStub(net::URLRequest* request)
73 : ResourceHandler(NULL), defer_request_on_will_start_(false) {} 85 : ResourceHandler(request),
86 defer_request_on_will_start_(false),
87 received_response_completed_(false),
88 total_bytes_downloaded_(0) {
89 }
74 90
75 void set_defer_request_on_will_start(bool defer_request_on_will_start) { 91 void set_defer_request_on_will_start(bool defer_request_on_will_start) {
76 defer_request_on_will_start_ = defer_request_on_will_start; 92 defer_request_on_will_start_ = defer_request_on_will_start;
77 } 93 }
78 94
95 const GURL& start_url() const { return start_url_; }
96 ResourceResponse* response() const { return response_.get(); }
97 bool received_response_completed() const {
98 return received_response_completed_;
99 }
100 const net::URLRequestStatus& status() const { return status_; }
101 int total_bytes_downloaded() const { return total_bytes_downloaded_; }
102
103 void Resume() {
104 controller()->Resume();
105 }
106
107 // ResourceHandler implementation:
79 virtual bool OnUploadProgress(int request_id, 108 virtual bool OnUploadProgress(int request_id,
80 uint64 position, 109 uint64 position,
81 uint64 size) OVERRIDE { 110 uint64 size) OVERRIDE {
111 NOTREACHED();
82 return true; 112 return true;
83 } 113 }
84 114
85 virtual bool OnRequestRedirected(int request_id, 115 virtual bool OnRequestRedirected(int request_id,
86 const GURL& url, 116 const GURL& url,
87 ResourceResponse* response, 117 ResourceResponse* response,
88 bool* defer) OVERRIDE { 118 bool* defer) OVERRIDE {
119 NOTREACHED();
89 return true; 120 return true;
90 } 121 }
91 122
92 virtual bool OnResponseStarted(int request_id, 123 virtual bool OnResponseStarted(int request_id,
93 ResourceResponse* response, 124 ResourceResponse* response,
94 bool* defer) OVERRIDE { 125 bool* defer) OVERRIDE {
126 EXPECT_FALSE(response_);
127 response_ = response;
95 return true; 128 return true;
96 } 129 }
97 130
98 virtual bool OnWillStart(int request_id, 131 virtual bool OnWillStart(int request_id,
99 const GURL& url, 132 const GURL& url,
100 bool* defer) OVERRIDE { 133 bool* defer) OVERRIDE {
134 EXPECT_TRUE(start_url_.is_empty());
135 start_url_ = url;
101 *defer = defer_request_on_will_start_; 136 *defer = defer_request_on_will_start_;
102 return true; 137 return true;
103 } 138 }
104 139
105 virtual bool OnBeforeNetworkStart(int request_id, 140 virtual bool OnBeforeNetworkStart(int request_id,
106 const GURL& url, 141 const GURL& url,
107 bool* defer) OVERRIDE { 142 bool* defer) OVERRIDE {
108 return true; 143 return true;
109 } 144 }
110 145
111 virtual bool OnWillRead(int request_id, 146 virtual bool OnWillRead(int request_id,
112 scoped_refptr<net::IOBuffer>* buf, 147 scoped_refptr<net::IOBuffer>* buf,
113 int* buf_size, 148 int* buf_size,
114 int min_size) OVERRIDE { 149 int min_size) OVERRIDE {
115 return true; 150 NOTREACHED();
151 return false;
116 } 152 }
117 153
118 virtual bool OnReadCompleted(int request_id, 154 virtual bool OnReadCompleted(int request_id,
119 int bytes_read, 155 int bytes_read,
120 bool* defer) OVERRIDE { 156 bool* defer) OVERRIDE {
121 return true; 157 NOTREACHED();
158 return false;
122 } 159 }
123 160
124 virtual void OnResponseCompleted(int request_id, 161 virtual void OnResponseCompleted(int request_id,
125 const net::URLRequestStatus& status, 162 const net::URLRequestStatus& status,
126 const std::string& security_info, 163 const std::string& security_info,
127 bool* defer) OVERRIDE { 164 bool* defer) OVERRIDE {
165 // TODO(davidben): This DCHECK currently fires everywhere. Fix the places in
166 // ResourceLoader where OnResponseCompleted is signaled twice.
167 // DCHECK(!received_response_completed_);
168 received_response_completed_ = true;
169 status_ = status;
128 } 170 }
129 171
130 virtual void OnDataDownloaded(int request_id, 172 virtual void OnDataDownloaded(int request_id,
131 int bytes_downloaded) OVERRIDE {} 173 int bytes_downloaded) OVERRIDE {
174 total_bytes_downloaded_ += bytes_downloaded;
175 }
132 176
133 private: 177 private:
134 bool defer_request_on_will_start_; 178 bool defer_request_on_will_start_;
179 GURL start_url_;
180 scoped_refptr<ResourceResponse> response_;
181 bool received_response_completed_;
182 net::URLRequestStatus status_;
183 int total_bytes_downloaded_;
135 }; 184 };
136 185
137 // Test browser client that captures calls to SelectClientCertificates and 186 // Test browser client that captures calls to SelectClientCertificates and
138 // records the arguments of the most recent call for later inspection. 187 // records the arguments of the most recent call for later inspection.
139 class SelectCertificateBrowserClient : public TestContentBrowserClient { 188 class SelectCertificateBrowserClient : public TestContentBrowserClient {
140 public: 189 public:
141 SelectCertificateBrowserClient() : call_count_(0) {} 190 SelectCertificateBrowserClient() : call_count_(0) {}
142 191
143 virtual void SelectClientCertificate( 192 virtual void SelectClientCertificate(
144 int render_process_id, 193 int render_process_id,
(...skipping 28 matching lines...) Expand all
173 } 222 }
174 223
175 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) { 224 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
176 dummy_cert_store_ = store.Pass(); 225 dummy_cert_store_ = store.Pass();
177 } 226 }
178 227
179 private: 228 private:
180 scoped_ptr<net::ClientCertStore> dummy_cert_store_; 229 scoped_ptr<net::ClientCertStore> dummy_cert_store_;
181 }; 230 };
182 231
232 // Fails to create a temporary file with the given error.
233 void CreateTemporaryError(
234 base::File::Error error,
235 const CreateTemporaryFileStreamCallback& callback) {
236 base::MessageLoop::current()->PostTask(
237 FROM_HERE,
238 base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
239 scoped_refptr<ShareableFileReference>()));
240 }
241
242 // Glue code to mock up a RedirectToFileResourceHandler with a MockFileStream
243 // and a pre-created temporary file.
244 class RedirectToFileMock {
245 public:
246 RedirectToFileMock() {
247 base::FilePath file_path;
248 CHECK(base::CreateTemporaryFile(&file_path));
249 base::PlatformFile platform_file =
250 base::CreatePlatformFile(file_path,
251 base::PLATFORM_FILE_WRITE |
252 base::PLATFORM_FILE_TEMPORARY |
253 base::PLATFORM_FILE_CREATE_ALWAYS |
254 base::PLATFORM_FILE_ASYNC,
255 NULL, NULL);
256 CHECK_NE(base::kInvalidPlatformFileValue, platform_file);
257 file_stream_.reset(
258 new net::testing::MockFileStream(
259 platform_file,
260 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC,
261 NULL, base::MessageLoopProxy::current()));
262 deletable_file_ =
263 ShareableFileReference::GetOrCreate(
264 file_path,
265 ShareableFileReference::DELETE_ON_FINAL_RELEASE,
266 BrowserThread::GetMessageLoopProxyForThread(
267 BrowserThread::FILE).get());
268 }
269
270 // These methods are only callable before CreateResourceHandler is called.
271 net::testing::MockFileStream* file_stream() const {
272 return file_stream_.get();
273 }
274 ShareableFileReference* deletable_file() const {
275 return deletable_file_.get();
276 }
277
278 scoped_ptr<RedirectToFileResourceHandler> CreateResourceHandler(
279 scoped_ptr<ResourceHandler> next_handler,
280 net::URLRequest* request) {
281 scoped_ptr<RedirectToFileResourceHandler> handler(
282 new RedirectToFileResourceHandler(next_handler.Pass(), request));
283 handler->SetCreateTemporaryFileStreamFunctionForTesting(
284 base::Bind(&RedirectToFileMock::PostCallback,
285 base::Unretained(this)));
286 return handler.Pass();
287 }
288
289 private:
290 void PostCallback(const CreateTemporaryFileStreamCallback& callback) {
291 CHECK(file_stream_);
292 CHECK(deletable_file_);
293 base::MessageLoop::current()->PostTask(
294 FROM_HERE,
295 base::Bind(callback, base::File::FILE_OK,
296 base::Passed(file_stream_.PassAs<net::FileStream>()),
297 deletable_file_));
298 deletable_file_ = NULL;
299 }
300
301 scoped_ptr<net::testing::MockFileStream> file_stream_;
302 scoped_refptr<ShareableFileReference> deletable_file_;
303
304 DISALLOW_COPY_AND_ASSIGN(RedirectToFileMock);
305 };
306
183 } // namespace 307 } // namespace
184 308
185 class ResourceLoaderTest : public testing::Test, 309 class ResourceLoaderTest : public testing::Test,
186 public ResourceLoaderDelegate { 310 public ResourceLoaderDelegate {
187 protected: 311 protected:
188 ResourceLoaderTest() 312 ResourceLoaderTest()
189 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), 313 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
190 resource_context_(&test_url_request_context_) { 314 resource_context_(&test_url_request_context_),
315 raw_ptr_resource_handler_(NULL),
316 raw_ptr_to_request_(NULL) {
317 job_factory_.SetProtocolHandler(
318 "test", net::URLRequestTestJob::CreateProtocolHandler());
319 test_url_request_context_.set_job_factory(&job_factory_);
191 } 320 }
192 321
193 virtual void SetUp() OVERRIDE { 322 scoped_ptr<net::URLRequest> CreateTestRequest(const GURL& url) {
194 const int kRenderProcessId = 1; 323 const int kRenderProcessId = 1;
195 const int kRenderViewId = 2; 324 const int kRenderViewId = 2;
196 325
197 scoped_ptr<net::URLRequest> request( 326 scoped_ptr<net::URLRequest> request(
198 new net::URLRequest(GURL("dummy"), 327 new net::URLRequest(url, net::DEFAULT_PRIORITY, NULL,
199 net::DEFAULT_PRIORITY,
200 NULL,
201 resource_context_.GetRequestContext())); 328 resource_context_.GetRequestContext()));
202 raw_ptr_to_request_ = request.get();
203 ResourceRequestInfo::AllocateForTesting(request.get(), 329 ResourceRequestInfo::AllocateForTesting(request.get(),
204 ResourceType::MAIN_FRAME, 330 ResourceType::MAIN_FRAME,
205 &resource_context_, 331 &resource_context_,
206 kRenderProcessId, 332 kRenderProcessId,
207 kRenderViewId, 333 kRenderViewId,
208 MSG_ROUTING_NONE, 334 MSG_ROUTING_NONE,
209 false); 335 false);
210 scoped_ptr<ResourceHandlerStub> resource_handler(new ResourceHandlerStub()); 336 return request.Pass();
337 }
338
339 virtual void SetUp() OVERRIDE {
340 scoped_ptr<net::URLRequest> request = CreateTestRequest(GURL("dummy"));
341 raw_ptr_to_request_ = request.get();
342 scoped_ptr<ResourceHandlerStub> resource_handler(
343 new ResourceHandlerStub(request.get()));
211 raw_ptr_resource_handler_ = resource_handler.get(); 344 raw_ptr_resource_handler_ = resource_handler.get();
212 loader_.reset(new ResourceLoader( 345 loader_.reset(new ResourceLoader(
213 request.Pass(), resource_handler.PassAs<ResourceHandler>(), this)); 346 request.Pass(), resource_handler.PassAs<ResourceHandler>(), this));
214 } 347 }
215 348
216 // ResourceLoaderDelegate: 349 // ResourceLoaderDelegate:
217 virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( 350 virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
218 ResourceLoader* loader, 351 ResourceLoader* loader,
219 net::AuthChallengeInfo* auth_info) OVERRIDE { 352 net::AuthChallengeInfo* auth_info) OVERRIDE {
220 return NULL; 353 return NULL;
221 } 354 }
222 virtual bool HandleExternalProtocol(ResourceLoader* loader, 355 virtual bool HandleExternalProtocol(ResourceLoader* loader,
223 const GURL& url) OVERRIDE { 356 const GURL& url) OVERRIDE {
224 return false; 357 return false;
225 } 358 }
226 virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {} 359 virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {}
227 virtual void DidReceiveRedirect(ResourceLoader* loader, 360 virtual void DidReceiveRedirect(ResourceLoader* loader,
228 const GURL& new_url) OVERRIDE {} 361 const GURL& new_url) OVERRIDE {}
229 virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {} 362 virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {}
230 virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {} 363 virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {}
231 364
232 content::TestBrowserThreadBundle thread_bundle_; 365 content::TestBrowserThreadBundle thread_bundle_;
233 366
367 net::URLRequestJobFactoryImpl job_factory_;
234 net::TestURLRequestContext test_url_request_context_; 368 net::TestURLRequestContext test_url_request_context_;
235 ResourceContextStub resource_context_; 369 ResourceContextStub resource_context_;
236 370
237 // The ResourceLoader owns the URLRequest and the ResourceHandler. 371 // The ResourceLoader owns the URLRequest and the ResourceHandler.
238 ResourceHandlerStub* raw_ptr_resource_handler_; 372 ResourceHandlerStub* raw_ptr_resource_handler_;
239 net::URLRequest* raw_ptr_to_request_; 373 net::URLRequest* raw_ptr_to_request_;
240 scoped_ptr<ResourceLoader> loader_; 374 scoped_ptr<ResourceLoader> loader_;
241 }; 375 };
242 376
243 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested() 377 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested()
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 } 449 }
316 450
317 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) { 451 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) {
318 raw_ptr_resource_handler_->set_defer_request_on_will_start(true); 452 raw_ptr_resource_handler_->set_defer_request_on_will_start(true);
319 453
320 loader_->StartRequest(); 454 loader_->StartRequest();
321 loader_->CancelRequest(true); 455 loader_->CancelRequest(true);
322 static_cast<ResourceController*>(loader_.get())->Resume(); 456 static_cast<ResourceController*>(loader_.get())->Resume();
323 } 457 }
324 458
459 // Tests that a RedirectToFileResourceHandler works and forwards everything
460 // downstream.
461 TEST_F(ResourceLoaderTest, RedirectToFile) {
darin (slow to review) 2014/03/11 05:15:58 Hmm, do these new tests really belong in this file
davidben 2014/03/11 19:50:04 Yeah, that was what I alluded to in comment #38. T
462 RedirectToFileMock redirect_to_file_mock;
463 base::FilePath temp_path = redirect_to_file_mock.deletable_file()->path();
464
465 // Set up the request.
466 scoped_ptr<net::URLRequest> request = CreateTestRequest(
467 net::URLRequestTestJob::test_url_1());
468 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
469 scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
470 resource_handler = redirect_to_file_mock.CreateResourceHandler(
471 resource_handler.Pass(), request.get());
472 scoped_ptr<ResourceLoader> loader(new ResourceLoader(
473 request.Pass(), resource_handler.Pass(), this));
474
475 // Run it to completion.
476 loader->StartRequest();
477 base::RunLoop().RunUntilIdle();
478
479 // Check that the handler forwarded all information to the downstream handler.
480 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path);
481 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
482 EXPECT_TRUE(leaf_handler->received_response_completed());
483 EXPECT_EQ(net::URLRequestStatus::SUCCESS, leaf_handler->status().status());
484 EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(),
485 static_cast<size_t>(leaf_handler->total_bytes_downloaded()));
486
487 // Check that the data was written to the file.
488 std::string contents;
489 ASSERT_TRUE(base::ReadFileToString(temp_path, &contents));
490 EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents);
491
492 // Release the loader. The file should be gone now.
493 loader.reset();
494 base::RunLoop().RunUntilIdle();
495 EXPECT_FALSE(base::PathExists(temp_path));
496 }
497
498 // Tests that RedirectToFileResourceHandler handles errors in creating the
499 // temporary file.
500 TEST_F(ResourceLoaderTest, RedirectToFileCreateTemporaryError) {
501 // Set up the request.
502 scoped_ptr<net::URLRequest> request = CreateTestRequest(
503 net::URLRequestTestJob::test_url_1());
504 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
505
506 scoped_ptr<RedirectToFileResourceHandler> resource_handler(
507 new RedirectToFileResourceHandler(
508 scoped_ptr<ResourceHandler>(leaf_handler), request.get()));
509 resource_handler->SetCreateTemporaryFileStreamFunctionForTesting(
510 base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED));
511
512 scoped_ptr<ResourceLoader> loader(new ResourceLoader(
513 request.Pass(), resource_handler.PassAs<ResourceHandler>(), this));
514
515 // Run it to completion.
516 loader->StartRequest();
517 base::RunLoop().RunUntilIdle();
518
519 // To downstream, the request was canceled.
520 EXPECT_TRUE(leaf_handler->received_response_completed());
521 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status());
522 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded());
523 }
524
525 // Tests that RedirectToFileResourceHandler handles synchronous write errors.
526 TEST_F(ResourceLoaderTest, RedirectToFileWriteError) {
527 RedirectToFileMock redirect_to_file_mock;
528 base::FilePath temp_path = redirect_to_file_mock.deletable_file()->path();
529 net::testing::MockFileStream* mock_file_stream =
530 redirect_to_file_mock.file_stream();
531 mock_file_stream->set_forced_error(net::ERR_FAILED);
532
533 // Set up the request.
534 scoped_ptr<net::URLRequest> request = CreateTestRequest(
535 net::URLRequestTestJob::test_url_1());
536 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
537 scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
538 resource_handler = redirect_to_file_mock.CreateResourceHandler(
539 resource_handler.Pass(), request.get());
540 scoped_ptr<ResourceLoader> loader(new ResourceLoader(
541 request.Pass(), resource_handler.Pass(), this));
542
543 // Run it to completion.
544 loader->StartRequest();
545 base::RunLoop().RunUntilIdle();
546
547 // To downstream, the request was canceled sometime after it started, but
548 // before any data was written.
549 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path);
550 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
551 EXPECT_TRUE(leaf_handler->received_response_completed());
552 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status());
553 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded());
554
555 // Release the loader. The file should be gone now.
556 loader.reset();
557 base::RunLoop().RunUntilIdle();
558 EXPECT_FALSE(base::PathExists(temp_path));
559 }
560
561 // Tests that RedirectToFileResourceHandler handles asynchronous write errors.
562 TEST_F(ResourceLoaderTest, RedirectToFileWriteErrorAsync) {
563 RedirectToFileMock redirect_to_file_mock;
564 base::FilePath temp_path = redirect_to_file_mock.deletable_file()->path();
565 net::testing::MockFileStream* mock_file_stream =
566 redirect_to_file_mock.file_stream();
567 mock_file_stream->set_forced_error_async(net::ERR_FAILED);
568
569 // Set up the request.
570 scoped_ptr<net::URLRequest> request = CreateTestRequest(
571 net::URLRequestTestJob::test_url_1());
572 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
573 scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
574 resource_handler = redirect_to_file_mock.CreateResourceHandler(
575 resource_handler.Pass(), request.get());
576 scoped_ptr<ResourceLoader> loader(new ResourceLoader(
577 request.Pass(), resource_handler.Pass(), this));
578
579 // Run it to completion.
580 loader->StartRequest();
581 base::RunLoop().RunUntilIdle();
582
583 // To downstream, the request was canceled sometime after it started, but
584 // before any data was written.
585 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path);
586 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
587 EXPECT_TRUE(leaf_handler->received_response_completed());
588 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status());
589 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded());
590
591 // Release the loader. The file should be gone now.
592 loader.reset();
593 base::RunLoop().RunUntilIdle();
594 EXPECT_FALSE(base::PathExists(temp_path));
595 }
596
597 // Tests that RedirectToFileHandler defers completion if there are outstanding
598 // writes and accounts for errors which occur in that time.
599 TEST_F(ResourceLoaderTest, RedirectToFileDeferCompletion) {
600 // Program the MockFileStream to error asynchronously, but throttle the
601 // callback.
602 RedirectToFileMock redirect_to_file_mock;
603 base::FilePath temp_path = redirect_to_file_mock.deletable_file()->path();
604 net::testing::MockFileStream* mock_file_stream =
605 redirect_to_file_mock.file_stream();
606 mock_file_stream->set_forced_error_async(net::ERR_FAILED);
607 mock_file_stream->ThrottleCallbacks();
608
609 // Set up the request.
610 scoped_ptr<net::URLRequest> request = CreateTestRequest(
611 net::URLRequestTestJob::test_url_1());
612 net::URLRequest* raw_ptr_to_request = request.get();
613 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
614 scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
615 resource_handler = redirect_to_file_mock.CreateResourceHandler(
616 resource_handler.Pass(), request.get());
617 scoped_ptr<ResourceLoader> loader(new ResourceLoader(
618 request.Pass(), resource_handler.Pass(), this));
619
620 // Run it as far as it will go.
621 loader->StartRequest();
622 base::RunLoop().RunUntilIdle();
623
624 // At this point, the request should have completed.
625 EXPECT_EQ(net::URLRequestStatus::SUCCESS,
626 raw_ptr_to_request->status().status());
627
628 // However, the resource loader stack is stuck somewhere after receiving the
629 // response.
630 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path);
631 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
632 EXPECT_FALSE(leaf_handler->received_response_completed());
633 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded());
634
635 // Now, release the floodgates.
636 mock_file_stream->ReleaseCallbacks();
637 base::RunLoop().RunUntilIdle();
638
639 // Although the URLRequest was successful, the leaf handler sees a failure
640 // because the write never completed.
641 EXPECT_TRUE(leaf_handler->received_response_completed());
642 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status());
643
644 // Release the loader. The file should be gone now.
645 loader.reset();
646 base::RunLoop().RunUntilIdle();
647 EXPECT_FALSE(base::PathExists(temp_path));
648 }
649
650 // Tests that a RedirectToFileResourceHandler behaves properly when the
651 // downstream handler defers OnWillStart.
652 TEST_F(ResourceLoaderTest, RedirectToFileDownstreamDeferStart) {
653 RedirectToFileMock redirect_to_file_mock;
654 base::FilePath temp_path =
655 redirect_to_file_mock.deletable_file()->path();
656
657 // Set up the request.
658 scoped_ptr<net::URLRequest> request = CreateTestRequest(
659 net::URLRequestTestJob::test_url_1());
660 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get());
661 scoped_ptr<ResourceHandler> resource_handler(leaf_handler);
662 resource_handler = redirect_to_file_mock.CreateResourceHandler(
663 resource_handler.Pass(), request.get());
664 scoped_ptr<ResourceLoader> loader(new ResourceLoader(
665 request.Pass(), resource_handler.Pass(), this));
666
667 // Defer OnWillStart.
668 leaf_handler->set_defer_request_on_will_start(true);
669
670 // Run as far as we'll go.
671 loader->StartRequest();
672 base::RunLoop().RunUntilIdle();
673
674 // The request should have stopped at OnWillStart.
675 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
676 EXPECT_FALSE(leaf_handler->response());
677 EXPECT_FALSE(leaf_handler->received_response_completed());
678 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded());
679
680 // Now resume the request. Now we complete.
681 leaf_handler->Resume();
682 base::RunLoop().RunUntilIdle();
683
684 // Check that the handler forwarded all information to the downstream handler.
685 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path);
686 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url());
687 EXPECT_TRUE(leaf_handler->received_response_completed());
688 EXPECT_EQ(net::URLRequestStatus::SUCCESS, leaf_handler->status().status());
689 EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(),
690 static_cast<size_t>(leaf_handler->total_bytes_downloaded()));
691
692 // Check that the data was written to the file.
693 std::string contents;
694 ASSERT_TRUE(base::ReadFileToString(temp_path, &contents));
695 EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents);
696
697 // Release the loader. The file should be gone now.
698 loader.reset();
699 base::RunLoop().RunUntilIdle();
700 EXPECT_FALSE(base::PathExists(temp_path));
701 }
702
325 } // namespace content 703 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698