Chromium Code Reviews| 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" | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |