OLD | NEW |
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" | |
11 #include "base/run_loop.h" | 7 #include "base/run_loop.h" |
12 #include "content/browser/browser_thread_impl.h" | 8 #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" | 9 #include "content/browser/loader/resource_loader_delegate.h" |
15 #include "content/public/browser/resource_request_info.h" | 10 #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" | 11 #include "content/public/test/mock_resource_context.h" |
18 #include "content/public/test/test_browser_thread_bundle.h" | 12 #include "content/public/test/test_browser_thread_bundle.h" |
19 #include "content/test/test_content_browser_client.h" | 13 #include "content/test/test_content_browser_client.h" |
20 #include "ipc/ipc_message.h" | 14 #include "ipc/ipc_message.h" |
21 #include "net/base/mock_file_stream.h" | |
22 #include "net/base/request_priority.h" | 15 #include "net/base/request_priority.h" |
23 #include "net/cert/x509_certificate.h" | 16 #include "net/cert/x509_certificate.h" |
24 #include "net/ssl/client_cert_store.h" | 17 #include "net/ssl/client_cert_store.h" |
25 #include "net/ssl/ssl_cert_request_info.h" | 18 #include "net/ssl/ssl_cert_request_info.h" |
26 #include "net/url_request/url_request.h" | 19 #include "net/url_request/url_request.h" |
27 #include "net/url_request/url_request_job_factory_impl.h" | |
28 #include "net/url_request/url_request_test_job.h" | |
29 #include "net/url_request/url_request_test_util.h" | 20 #include "net/url_request/url_request_test_util.h" |
30 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
31 #include "webkit/common/blob/shareable_file_reference.h" | |
32 | |
33 using webkit_blob::ShareableFileReference; | |
34 | 22 |
35 namespace content { | 23 namespace content { |
36 namespace { | 24 namespace { |
37 | 25 |
38 // Stub client certificate store that returns a preset list of certificates for | 26 // Stub client certificate store that returns a preset list of certificates for |
39 // each request and records the arguments of the most recent request for later | 27 // each request and records the arguments of the most recent request for later |
40 // inspection. | 28 // inspection. |
41 class ClientCertStoreStub : public net::ClientCertStore { | 29 class ClientCertStoreStub : public net::ClientCertStore { |
42 public: | 30 public: |
43 ClientCertStoreStub(const net::CertificateList& certs) | 31 ClientCertStoreStub(const net::CertificateList& certs) |
(...skipping 30 matching lines...) Expand all Loading... |
74 private: | 62 private: |
75 const net::CertificateList response_; | 63 const net::CertificateList response_; |
76 int request_count_; | 64 int request_count_; |
77 std::vector<std::string> requested_authorities_; | 65 std::vector<std::string> requested_authorities_; |
78 }; | 66 }; |
79 | 67 |
80 // Dummy implementation of ResourceHandler, instance of which is needed to | 68 // Dummy implementation of ResourceHandler, instance of which is needed to |
81 // initialize ResourceLoader. | 69 // initialize ResourceLoader. |
82 class ResourceHandlerStub : public ResourceHandler { | 70 class ResourceHandlerStub : public ResourceHandler { |
83 public: | 71 public: |
84 explicit ResourceHandlerStub(net::URLRequest* request) | 72 ResourceHandlerStub() |
85 : ResourceHandler(request), | 73 : ResourceHandler(NULL), defer_request_on_will_start_(false) {} |
86 defer_request_on_will_start_(false), | |
87 received_response_completed_(false), | |
88 total_bytes_downloaded_(0) { | |
89 } | |
90 | 74 |
91 void set_defer_request_on_will_start(bool defer_request_on_will_start) { | 75 void set_defer_request_on_will_start(bool defer_request_on_will_start) { |
92 defer_request_on_will_start_ = defer_request_on_will_start; | 76 defer_request_on_will_start_ = defer_request_on_will_start; |
93 } | 77 } |
94 | 78 |
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: | |
108 virtual bool OnUploadProgress(int request_id, | 79 virtual bool OnUploadProgress(int request_id, |
109 uint64 position, | 80 uint64 position, |
110 uint64 size) OVERRIDE { | 81 uint64 size) OVERRIDE { |
111 NOTREACHED(); | |
112 return true; | 82 return true; |
113 } | 83 } |
114 | 84 |
115 virtual bool OnRequestRedirected(int request_id, | 85 virtual bool OnRequestRedirected(int request_id, |
116 const GURL& url, | 86 const GURL& url, |
117 ResourceResponse* response, | 87 ResourceResponse* response, |
118 bool* defer) OVERRIDE { | 88 bool* defer) OVERRIDE { |
119 NOTREACHED(); | |
120 return true; | 89 return true; |
121 } | 90 } |
122 | 91 |
123 virtual bool OnResponseStarted(int request_id, | 92 virtual bool OnResponseStarted(int request_id, |
124 ResourceResponse* response, | 93 ResourceResponse* response, |
125 bool* defer) OVERRIDE { | 94 bool* defer) OVERRIDE { |
126 EXPECT_FALSE(response_); | |
127 response_ = response; | |
128 return true; | 95 return true; |
129 } | 96 } |
130 | 97 |
131 virtual bool OnWillStart(int request_id, | 98 virtual bool OnWillStart(int request_id, |
132 const GURL& url, | 99 const GURL& url, |
133 bool* defer) OVERRIDE { | 100 bool* defer) OVERRIDE { |
134 EXPECT_TRUE(start_url_.is_empty()); | |
135 start_url_ = url; | |
136 *defer = defer_request_on_will_start_; | 101 *defer = defer_request_on_will_start_; |
137 return true; | 102 return true; |
138 } | 103 } |
139 | 104 |
140 virtual bool OnBeforeNetworkStart(int request_id, | 105 virtual bool OnBeforeNetworkStart(int request_id, |
141 const GURL& url, | 106 const GURL& url, |
142 bool* defer) OVERRIDE { | 107 bool* defer) OVERRIDE { |
143 return true; | 108 return true; |
144 } | 109 } |
145 | 110 |
146 virtual bool OnWillRead(int request_id, | 111 virtual bool OnWillRead(int request_id, |
147 scoped_refptr<net::IOBuffer>* buf, | 112 scoped_refptr<net::IOBuffer>* buf, |
148 int* buf_size, | 113 int* buf_size, |
149 int min_size) OVERRIDE { | 114 int min_size) OVERRIDE { |
150 NOTREACHED(); | 115 return true; |
151 return false; | |
152 } | 116 } |
153 | 117 |
154 virtual bool OnReadCompleted(int request_id, | 118 virtual bool OnReadCompleted(int request_id, |
155 int bytes_read, | 119 int bytes_read, |
156 bool* defer) OVERRIDE { | 120 bool* defer) OVERRIDE { |
157 NOTREACHED(); | 121 return true; |
158 return false; | |
159 } | 122 } |
160 | 123 |
161 virtual void OnResponseCompleted(int request_id, | 124 virtual void OnResponseCompleted(int request_id, |
162 const net::URLRequestStatus& status, | 125 const net::URLRequestStatus& status, |
163 const std::string& security_info, | 126 const std::string& security_info, |
164 bool* defer) OVERRIDE { | 127 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; | |
170 } | 128 } |
171 | 129 |
172 virtual void OnDataDownloaded(int request_id, | 130 virtual void OnDataDownloaded(int request_id, |
173 int bytes_downloaded) OVERRIDE { | 131 int bytes_downloaded) OVERRIDE {} |
174 total_bytes_downloaded_ += bytes_downloaded; | |
175 } | |
176 | 132 |
177 private: | 133 private: |
178 bool defer_request_on_will_start_; | 134 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_; | |
184 }; | 135 }; |
185 | 136 |
186 // Test browser client that captures calls to SelectClientCertificates and | 137 // Test browser client that captures calls to SelectClientCertificates and |
187 // records the arguments of the most recent call for later inspection. | 138 // records the arguments of the most recent call for later inspection. |
188 class SelectCertificateBrowserClient : public TestContentBrowserClient { | 139 class SelectCertificateBrowserClient : public TestContentBrowserClient { |
189 public: | 140 public: |
190 SelectCertificateBrowserClient() : call_count_(0) {} | 141 SelectCertificateBrowserClient() : call_count_(0) {} |
191 | 142 |
192 virtual void SelectClientCertificate( | 143 virtual void SelectClientCertificate( |
193 int render_process_id, | 144 int render_process_id, |
(...skipping 28 matching lines...) Expand all Loading... |
222 } | 173 } |
223 | 174 |
224 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) { | 175 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) { |
225 dummy_cert_store_ = store.Pass(); | 176 dummy_cert_store_ = store.Pass(); |
226 } | 177 } |
227 | 178 |
228 private: | 179 private: |
229 scoped_ptr<net::ClientCertStore> dummy_cert_store_; | 180 scoped_ptr<net::ClientCertStore> dummy_cert_store_; |
230 }; | 181 }; |
231 | 182 |
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 } // namespace | 183 } // namespace |
243 | 184 |
244 class ResourceLoaderTest : public testing::Test, | 185 class ResourceLoaderTest : public testing::Test, |
245 public ResourceLoaderDelegate { | 186 public ResourceLoaderDelegate { |
246 protected: | 187 protected: |
247 ResourceLoaderTest() | 188 ResourceLoaderTest() |
248 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), | 189 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), |
249 resource_context_(&test_url_request_context_), | 190 resource_context_(&test_url_request_context_) { |
250 raw_ptr_resource_handler_(NULL), | |
251 raw_ptr_to_request_(NULL) { | |
252 job_factory_.SetProtocolHandler( | |
253 "test", net::URLRequestTestJob::CreateProtocolHandler()); | |
254 test_url_request_context_.set_job_factory(&job_factory_); | |
255 } | |
256 | |
257 GURL test_url() const { | |
258 return net::URLRequestTestJob::test_url_1(); | |
259 } | |
260 | |
261 std::string test_data() const { | |
262 return net::URLRequestTestJob::test_data_1(); | |
263 } | |
264 | |
265 virtual scoped_ptr<ResourceHandler> WrapResourceHandler( | |
266 scoped_ptr<ResourceHandlerStub> leaf_handler, | |
267 net::URLRequest* request) { | |
268 return leaf_handler.PassAs<ResourceHandler>(); | |
269 } | 191 } |
270 | 192 |
271 virtual void SetUp() OVERRIDE { | 193 virtual void SetUp() OVERRIDE { |
272 const int kRenderProcessId = 1; | 194 const int kRenderProcessId = 1; |
273 const int kRenderViewId = 2; | 195 const int kRenderViewId = 2; |
274 | 196 |
275 scoped_ptr<net::URLRequest> request( | 197 scoped_ptr<net::URLRequest> request( |
276 new net::URLRequest(test_url(), | 198 new net::URLRequest(GURL("dummy"), |
277 net::DEFAULT_PRIORITY, | 199 net::DEFAULT_PRIORITY, |
278 NULL, | 200 NULL, |
279 resource_context_.GetRequestContext())); | 201 resource_context_.GetRequestContext())); |
280 raw_ptr_to_request_ = request.get(); | 202 raw_ptr_to_request_ = request.get(); |
281 ResourceRequestInfo::AllocateForTesting(request.get(), | 203 ResourceRequestInfo::AllocateForTesting(request.get(), |
282 ResourceType::MAIN_FRAME, | 204 ResourceType::MAIN_FRAME, |
283 &resource_context_, | 205 &resource_context_, |
284 kRenderProcessId, | 206 kRenderProcessId, |
285 kRenderViewId, | 207 kRenderViewId, |
286 MSG_ROUTING_NONE, | 208 MSG_ROUTING_NONE, |
287 false); | 209 false); |
288 scoped_ptr<ResourceHandlerStub> resource_handler( | 210 scoped_ptr<ResourceHandlerStub> resource_handler(new ResourceHandlerStub()); |
289 new ResourceHandlerStub(request.get())); | |
290 raw_ptr_resource_handler_ = resource_handler.get(); | 211 raw_ptr_resource_handler_ = resource_handler.get(); |
291 loader_.reset(new ResourceLoader( | 212 loader_.reset(new ResourceLoader( |
292 request.Pass(), | 213 request.Pass(), resource_handler.PassAs<ResourceHandler>(), this)); |
293 WrapResourceHandler(resource_handler.Pass(), raw_ptr_to_request_), | |
294 this)); | |
295 } | 214 } |
296 | 215 |
297 // ResourceLoaderDelegate: | 216 // ResourceLoaderDelegate: |
298 virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( | 217 virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( |
299 ResourceLoader* loader, | 218 ResourceLoader* loader, |
300 net::AuthChallengeInfo* auth_info) OVERRIDE { | 219 net::AuthChallengeInfo* auth_info) OVERRIDE { |
301 return NULL; | 220 return NULL; |
302 } | 221 } |
303 virtual bool HandleExternalProtocol(ResourceLoader* loader, | 222 virtual bool HandleExternalProtocol(ResourceLoader* loader, |
304 const GURL& url) OVERRIDE { | 223 const GURL& url) OVERRIDE { |
305 return false; | 224 return false; |
306 } | 225 } |
307 virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {} | 226 virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {} |
308 virtual void DidReceiveRedirect(ResourceLoader* loader, | 227 virtual void DidReceiveRedirect(ResourceLoader* loader, |
309 const GURL& new_url) OVERRIDE {} | 228 const GURL& new_url) OVERRIDE {} |
310 virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {} | 229 virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {} |
311 virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {} | 230 virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {} |
312 | 231 |
313 content::TestBrowserThreadBundle thread_bundle_; | 232 content::TestBrowserThreadBundle thread_bundle_; |
314 | 233 |
315 net::URLRequestJobFactoryImpl job_factory_; | |
316 net::TestURLRequestContext test_url_request_context_; | 234 net::TestURLRequestContext test_url_request_context_; |
317 ResourceContextStub resource_context_; | 235 ResourceContextStub resource_context_; |
318 | 236 |
319 // The ResourceLoader owns the URLRequest and the ResourceHandler. | 237 // The ResourceLoader owns the URLRequest and the ResourceHandler. |
320 ResourceHandlerStub* raw_ptr_resource_handler_; | 238 ResourceHandlerStub* raw_ptr_resource_handler_; |
321 net::URLRequest* raw_ptr_to_request_; | 239 net::URLRequest* raw_ptr_to_request_; |
322 scoped_ptr<ResourceLoader> loader_; | 240 scoped_ptr<ResourceLoader> loader_; |
323 }; | 241 }; |
324 | 242 |
325 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested() | 243 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested() |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 } | 315 } |
398 | 316 |
399 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) { | 317 TEST_F(ResourceLoaderTest, ResumeCancelledRequest) { |
400 raw_ptr_resource_handler_->set_defer_request_on_will_start(true); | 318 raw_ptr_resource_handler_->set_defer_request_on_will_start(true); |
401 | 319 |
402 loader_->StartRequest(); | 320 loader_->StartRequest(); |
403 loader_->CancelRequest(true); | 321 loader_->CancelRequest(true); |
404 static_cast<ResourceController*>(loader_.get())->Resume(); | 322 static_cast<ResourceController*>(loader_.get())->Resume(); |
405 } | 323 } |
406 | 324 |
407 class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest { | |
408 public: | |
409 ResourceLoaderRedirectToFileTest() | |
410 : file_stream_(NULL), | |
411 redirect_to_file_resource_handler_(NULL) { | |
412 } | |
413 | |
414 base::FilePath temp_path() const { return temp_path_; } | |
415 ShareableFileReference* deletable_file() const { | |
416 return deletable_file_.get(); | |
417 } | |
418 net::testing::MockFileStream* file_stream() const { return file_stream_; } | |
419 RedirectToFileResourceHandler* redirect_to_file_resource_handler() const { | |
420 return redirect_to_file_resource_handler_; | |
421 } | |
422 | |
423 void ReleaseLoader() { | |
424 file_stream_ = NULL; | |
425 deletable_file_ = NULL; | |
426 loader_.reset(); | |
427 } | |
428 | |
429 virtual scoped_ptr<ResourceHandler> WrapResourceHandler( | |
430 scoped_ptr<ResourceHandlerStub> leaf_handler, | |
431 net::URLRequest* request) OVERRIDE { | |
432 // Make a temporary file. | |
433 CHECK(base::CreateTemporaryFile(&temp_path_)); | |
434 base::PlatformFile platform_file = | |
435 base::CreatePlatformFile(temp_path_, | |
436 base::PLATFORM_FILE_WRITE | | |
437 base::PLATFORM_FILE_TEMPORARY | | |
438 base::PLATFORM_FILE_CREATE_ALWAYS | | |
439 base::PLATFORM_FILE_ASYNC, | |
440 NULL, NULL); | |
441 CHECK_NE(base::kInvalidPlatformFileValue, platform_file); | |
442 | |
443 // Create mock file streams and a ShareableFileReference. | |
444 scoped_ptr<net::testing::MockFileStream> file_stream( | |
445 new net::testing::MockFileStream( | |
446 platform_file, | |
447 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, | |
448 NULL, base::MessageLoopProxy::current())); | |
449 file_stream_ = file_stream.get(); | |
450 deletable_file_ = ShareableFileReference::GetOrCreate( | |
451 temp_path_, | |
452 ShareableFileReference::DELETE_ON_FINAL_RELEASE, | |
453 BrowserThread::GetMessageLoopProxyForThread( | |
454 BrowserThread::FILE).get()); | |
455 | |
456 // Inject them into the handler. | |
457 scoped_ptr<RedirectToFileResourceHandler> handler( | |
458 new RedirectToFileResourceHandler( | |
459 leaf_handler.PassAs<ResourceHandler>(), request)); | |
460 redirect_to_file_resource_handler_ = handler.get(); | |
461 handler->SetCreateTemporaryFileStreamFunctionForTesting( | |
462 base::Bind(&ResourceLoaderRedirectToFileTest::PostCallback, | |
463 base::Unretained(this), | |
464 base::Passed(file_stream.PassAs<net::FileStream>()))); | |
465 return handler.PassAs<ResourceHandler>(); | |
466 } | |
467 | |
468 private: | |
469 void PostCallback( | |
470 scoped_ptr<net::FileStream> file_stream, | |
471 const CreateTemporaryFileStreamCallback& callback) { | |
472 base::MessageLoop::current()->PostTask( | |
473 FROM_HERE, | |
474 base::Bind(callback, base::File::FILE_OK, | |
475 base::Passed(&file_stream), deletable_file_)); | |
476 } | |
477 | |
478 base::FilePath temp_path_; | |
479 scoped_refptr<ShareableFileReference> deletable_file_; | |
480 // These are owned by the ResourceLoader. | |
481 net::testing::MockFileStream* file_stream_; | |
482 RedirectToFileResourceHandler* redirect_to_file_resource_handler_; | |
483 }; | |
484 | |
485 // Tests that a RedirectToFileResourceHandler works and forwards everything | |
486 // downstream. | |
487 TEST_F(ResourceLoaderRedirectToFileTest, Basic) { | |
488 // Run it to completion. | |
489 loader_->StartRequest(); | |
490 base::RunLoop().RunUntilIdle(); | |
491 | |
492 // Check that the handler forwarded all information to the downstream handler. | |
493 EXPECT_EQ(temp_path(), | |
494 raw_ptr_resource_handler_->response()->head.download_file_path); | |
495 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url()); | |
496 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); | |
497 EXPECT_EQ(net::URLRequestStatus::SUCCESS, | |
498 raw_ptr_resource_handler_->status().status()); | |
499 EXPECT_EQ(test_data().size(), static_cast<size_t>( | |
500 raw_ptr_resource_handler_->total_bytes_downloaded())); | |
501 | |
502 // Check that the data was written to the file. | |
503 std::string contents; | |
504 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents)); | |
505 EXPECT_EQ(test_data(), contents); | |
506 | |
507 // Release the loader and the saved reference to file. The file should be gone | |
508 // now. | |
509 ReleaseLoader(); | |
510 base::RunLoop().RunUntilIdle(); | |
511 EXPECT_FALSE(base::PathExists(temp_path())); | |
512 } | |
513 | |
514 // Tests that RedirectToFileResourceHandler handles errors in creating the | |
515 // temporary file. | |
516 TEST_F(ResourceLoaderRedirectToFileTest, CreateTemporaryError) { | |
517 // Swap out the create temporary function. | |
518 redirect_to_file_resource_handler()-> | |
519 SetCreateTemporaryFileStreamFunctionForTesting( | |
520 base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED)); | |
521 | |
522 // Run it to completion. | |
523 loader_->StartRequest(); | |
524 base::RunLoop().RunUntilIdle(); | |
525 | |
526 // To downstream, the request was canceled. | |
527 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); | |
528 EXPECT_EQ(net::URLRequestStatus::CANCELED, | |
529 raw_ptr_resource_handler_->status().status()); | |
530 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded()); | |
531 } | |
532 | |
533 // Tests that RedirectToFileResourceHandler handles synchronous write errors. | |
534 TEST_F(ResourceLoaderRedirectToFileTest, WriteError) { | |
535 file_stream()->set_forced_error(net::ERR_FAILED); | |
536 | |
537 // Run it to completion. | |
538 loader_->StartRequest(); | |
539 base::RunLoop().RunUntilIdle(); | |
540 | |
541 // To downstream, the request was canceled sometime after it started, but | |
542 // before any data was written. | |
543 EXPECT_EQ(temp_path(), | |
544 raw_ptr_resource_handler_->response()->head.download_file_path); | |
545 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url()); | |
546 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); | |
547 EXPECT_EQ(net::URLRequestStatus::CANCELED, | |
548 raw_ptr_resource_handler_->status().status()); | |
549 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded()); | |
550 | |
551 // Release the loader. The file should be gone now. | |
552 ReleaseLoader(); | |
553 base::RunLoop().RunUntilIdle(); | |
554 EXPECT_FALSE(base::PathExists(temp_path())); | |
555 } | |
556 | |
557 // Tests that RedirectToFileResourceHandler handles asynchronous write errors. | |
558 TEST_F(ResourceLoaderRedirectToFileTest, WriteErrorAsync) { | |
559 file_stream()->set_forced_error_async(net::ERR_FAILED); | |
560 | |
561 // Run it to completion. | |
562 loader_->StartRequest(); | |
563 base::RunLoop().RunUntilIdle(); | |
564 | |
565 // To downstream, the request was canceled sometime after it started, but | |
566 // before any data was written. | |
567 EXPECT_EQ(temp_path(), | |
568 raw_ptr_resource_handler_->response()->head.download_file_path); | |
569 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url()); | |
570 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); | |
571 EXPECT_EQ(net::URLRequestStatus::CANCELED, | |
572 raw_ptr_resource_handler_->status().status()); | |
573 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded()); | |
574 | |
575 // Release the loader. The file should be gone now. | |
576 ReleaseLoader(); | |
577 base::RunLoop().RunUntilIdle(); | |
578 EXPECT_FALSE(base::PathExists(temp_path())); | |
579 } | |
580 | |
581 // Tests that RedirectToFileHandler defers completion if there are outstanding | |
582 // writes and accounts for errors which occur in that time. | |
583 TEST_F(ResourceLoaderRedirectToFileTest, DeferCompletion) { | |
584 // Program the MockFileStream to error asynchronously, but throttle the | |
585 // callback. | |
586 file_stream()->set_forced_error_async(net::ERR_FAILED); | |
587 file_stream()->ThrottleCallbacks(); | |
588 | |
589 // Run it as far as it will go. | |
590 loader_->StartRequest(); | |
591 base::RunLoop().RunUntilIdle(); | |
592 | |
593 // At this point, the request should have completed. | |
594 EXPECT_EQ(net::URLRequestStatus::SUCCESS, | |
595 raw_ptr_to_request_->status().status()); | |
596 | |
597 // However, the resource loader stack is stuck somewhere after receiving the | |
598 // response. | |
599 EXPECT_EQ(temp_path(), | |
600 raw_ptr_resource_handler_->response()->head.download_file_path); | |
601 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url()); | |
602 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed()); | |
603 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded()); | |
604 | |
605 // Now, release the floodgates. | |
606 file_stream()->ReleaseCallbacks(); | |
607 base::RunLoop().RunUntilIdle(); | |
608 | |
609 // Although the URLRequest was successful, the leaf handler sees a failure | |
610 // because the write never completed. | |
611 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); | |
612 EXPECT_EQ(net::URLRequestStatus::CANCELED, | |
613 raw_ptr_resource_handler_->status().status()); | |
614 | |
615 // Release the loader. The file should be gone now. | |
616 ReleaseLoader(); | |
617 base::RunLoop().RunUntilIdle(); | |
618 EXPECT_FALSE(base::PathExists(temp_path())); | |
619 } | |
620 | |
621 // Tests that a RedirectToFileResourceHandler behaves properly when the | |
622 // downstream handler defers OnWillStart. | |
623 TEST_F(ResourceLoaderRedirectToFileTest, DownstreamDeferStart) { | |
624 // Defer OnWillStart. | |
625 raw_ptr_resource_handler_->set_defer_request_on_will_start(true); | |
626 | |
627 // Run as far as we'll go. | |
628 loader_->StartRequest(); | |
629 base::RunLoop().RunUntilIdle(); | |
630 | |
631 // The request should have stopped at OnWillStart. | |
632 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url()); | |
633 EXPECT_FALSE(raw_ptr_resource_handler_->response()); | |
634 EXPECT_FALSE(raw_ptr_resource_handler_->received_response_completed()); | |
635 EXPECT_EQ(0, raw_ptr_resource_handler_->total_bytes_downloaded()); | |
636 | |
637 // Now resume the request. Now we complete. | |
638 raw_ptr_resource_handler_->Resume(); | |
639 base::RunLoop().RunUntilIdle(); | |
640 | |
641 // Check that the handler forwarded all information to the downstream handler. | |
642 EXPECT_EQ(temp_path(), | |
643 raw_ptr_resource_handler_->response()->head.download_file_path); | |
644 EXPECT_EQ(test_url(), raw_ptr_resource_handler_->start_url()); | |
645 EXPECT_TRUE(raw_ptr_resource_handler_->received_response_completed()); | |
646 EXPECT_EQ(net::URLRequestStatus::SUCCESS, | |
647 raw_ptr_resource_handler_->status().status()); | |
648 EXPECT_EQ(test_data().size(), static_cast<size_t>( | |
649 raw_ptr_resource_handler_->total_bytes_downloaded())); | |
650 | |
651 // Check that the data was written to the file. | |
652 std::string contents; | |
653 ASSERT_TRUE(base::ReadFileToString(temp_path(), &contents)); | |
654 EXPECT_EQ(test_data(), contents); | |
655 | |
656 // Release the loader. The file should be gone now. | |
657 ReleaseLoader(); | |
658 base::RunLoop().RunUntilIdle(); | |
659 EXPECT_FALSE(base::PathExists(temp_path())); | |
660 } | |
661 | |
662 } // namespace content | 325 } // namespace content |
OLD | NEW |