| 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() : ResourceHandler(NULL) {} | 84 explicit ResourceHandlerStub(net::URLRequest* request) |
| 85 : ResourceHandler(request), |
| 86 defer_start_(false), |
| 87 received_response_completed_(false), |
| 88 total_bytes_downloaded_(0) { |
| 89 } |
| 73 | 90 |
| 91 void set_defer_start(bool defer_start) { defer_start_ = defer_start; } |
| 92 |
| 93 const GURL& start_url() const { return start_url_; } |
| 94 ResourceResponse* response() const { return response_.get(); } |
| 95 bool received_response_completed() const { |
| 96 return received_response_completed_; |
| 97 } |
| 98 const net::URLRequestStatus& status() const { return status_; } |
| 99 int total_bytes_downloaded() const { return total_bytes_downloaded_; } |
| 100 |
| 101 void Resume() { |
| 102 controller()->Resume(); |
| 103 } |
| 104 |
| 105 // ResourceHandler implementation: |
| 74 virtual bool OnUploadProgress(int request_id, | 106 virtual bool OnUploadProgress(int request_id, |
| 75 uint64 position, | 107 uint64 position, |
| 76 uint64 size) OVERRIDE { | 108 uint64 size) OVERRIDE { |
| 109 NOTREACHED(); |
| 77 return true; | 110 return true; |
| 78 } | 111 } |
| 79 | 112 |
| 80 virtual bool OnRequestRedirected(int request_id, | 113 virtual bool OnRequestRedirected(int request_id, |
| 81 const GURL& url, | 114 const GURL& url, |
| 82 ResourceResponse* response, | 115 ResourceResponse* response, |
| 83 bool* defer) OVERRIDE { | 116 bool* defer) OVERRIDE { |
| 117 NOTREACHED(); |
| 84 return true; | 118 return true; |
| 85 } | 119 } |
| 86 | 120 |
| 87 virtual bool OnResponseStarted(int request_id, | 121 virtual bool OnResponseStarted(int request_id, |
| 88 ResourceResponse* response, | 122 ResourceResponse* response, |
| 89 bool* defer) OVERRIDE { return true; } | 123 bool* defer) OVERRIDE { |
| 124 EXPECT_FALSE(response_); |
| 125 response_ = response; |
| 126 return true; |
| 127 } |
| 90 | 128 |
| 91 virtual bool OnWillStart(int request_id, | 129 virtual bool OnWillStart(int request_id, |
| 92 const GURL& url, | 130 const GURL& url, |
| 93 bool* defer) OVERRIDE { | 131 bool* defer) OVERRIDE { |
| 132 EXPECT_TRUE(start_url_.is_empty()); |
| 133 start_url_ = url; |
| 134 *defer = defer_start_; |
| 94 return true; | 135 return true; |
| 95 } | 136 } |
| 96 | 137 |
| 97 virtual bool OnBeforeNetworkStart(int request_id, | 138 virtual bool OnBeforeNetworkStart(int request_id, |
| 98 const GURL& url, | 139 const GURL& url, |
| 99 bool* defer) OVERRIDE { | 140 bool* defer) OVERRIDE { |
| 100 return true; | 141 return true; |
| 101 } | 142 } |
| 102 | 143 |
| 103 virtual bool OnWillRead(int request_id, | 144 virtual bool OnWillRead(int request_id, |
| 104 scoped_refptr<net::IOBuffer>* buf, | 145 scoped_refptr<net::IOBuffer>* buf, |
| 105 int* buf_size, | 146 int* buf_size, |
| 106 int min_size) OVERRIDE { | 147 int min_size) OVERRIDE { |
| 107 return true; | 148 NOTREACHED(); |
| 149 return false; |
| 108 } | 150 } |
| 109 | 151 |
| 110 virtual bool OnReadCompleted(int request_id, | 152 virtual bool OnReadCompleted(int request_id, |
| 111 int bytes_read, | 153 int bytes_read, |
| 112 bool* defer) OVERRIDE { | 154 bool* defer) OVERRIDE { |
| 113 return true; | 155 NOTREACHED(); |
| 156 return false; |
| 114 } | 157 } |
| 115 | 158 |
| 116 virtual void OnResponseCompleted(int request_id, | 159 virtual void OnResponseCompleted(int request_id, |
| 117 const net::URLRequestStatus& status, | 160 const net::URLRequestStatus& status, |
| 118 const std::string& security_info, | 161 const std::string& security_info, |
| 119 bool* defer) OVERRIDE { | 162 bool* defer) OVERRIDE { |
| 163 // TODO(davidben): This DCHECK currently fires everywhere. Fix the places in |
| 164 // ResourceLoader where OnResponseCompleted is signaled twice. |
| 165 // DCHECK(!received_response_completed_); |
| 166 received_response_completed_ = true; |
| 167 status_ = status; |
| 120 } | 168 } |
| 121 | 169 |
| 122 virtual void OnDataDownloaded(int request_id, | 170 virtual void OnDataDownloaded(int request_id, |
| 123 int bytes_downloaded) OVERRIDE {} | 171 int bytes_downloaded) OVERRIDE { |
| 172 total_bytes_downloaded_ += bytes_downloaded; |
| 173 } |
| 174 |
| 175 private: |
| 176 bool defer_start_; |
| 177 GURL start_url_; |
| 178 scoped_refptr<ResourceResponse> response_; |
| 179 bool received_response_completed_; |
| 180 net::URLRequestStatus status_; |
| 181 int total_bytes_downloaded_; |
| 124 }; | 182 }; |
| 125 | 183 |
| 126 // Test browser client that captures calls to SelectClientCertificates and | 184 // Test browser client that captures calls to SelectClientCertificates and |
| 127 // records the arguments of the most recent call for later inspection. | 185 // records the arguments of the most recent call for later inspection. |
| 128 class SelectCertificateBrowserClient : public TestContentBrowserClient { | 186 class SelectCertificateBrowserClient : public TestContentBrowserClient { |
| 129 public: | 187 public: |
| 130 SelectCertificateBrowserClient() : call_count_(0) {} | 188 SelectCertificateBrowserClient() : call_count_(0) {} |
| 131 | 189 |
| 132 virtual void SelectClientCertificate( | 190 virtual void SelectClientCertificate( |
| 133 int render_process_id, | 191 int render_process_id, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 162 } | 220 } |
| 163 | 221 |
| 164 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) { | 222 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) { |
| 165 dummy_cert_store_ = store.Pass(); | 223 dummy_cert_store_ = store.Pass(); |
| 166 } | 224 } |
| 167 | 225 |
| 168 private: | 226 private: |
| 169 scoped_ptr<net::ClientCertStore> dummy_cert_store_; | 227 scoped_ptr<net::ClientCertStore> dummy_cert_store_; |
| 170 }; | 228 }; |
| 171 | 229 |
| 230 // Fails to create a temporary file with the given error. |
| 231 void CreateTemporaryError( |
| 232 base::File::Error error, |
| 233 const CreateTemporaryFileStreamCallback& callback) { |
| 234 base::MessageLoop::current()->PostTask( |
| 235 FROM_HERE, |
| 236 base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()), |
| 237 scoped_refptr<ShareableFileReference>())); |
| 238 } |
| 239 |
| 240 // Glue code to mock up a RedirectToFileResourceHandler with a MockFileStream |
| 241 // and a pre-created temporary file. |
| 242 class RedirectToFileMock { |
| 243 public: |
| 244 RedirectToFileMock() { |
| 245 base::FilePath file_path; |
| 246 CHECK(base::CreateTemporaryFile(&file_path)); |
| 247 base::PlatformFile platform_file = |
| 248 base::CreatePlatformFile(file_path, |
| 249 base::PLATFORM_FILE_WRITE | |
| 250 base::PLATFORM_FILE_TEMPORARY | |
| 251 base::PLATFORM_FILE_CREATE_ALWAYS | |
| 252 base::PLATFORM_FILE_ASYNC, |
| 253 NULL, NULL); |
| 254 CHECK_NE(base::kInvalidPlatformFileValue, platform_file); |
| 255 file_stream_.reset( |
| 256 new net::testing::MockFileStream( |
| 257 platform_file, |
| 258 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, |
| 259 NULL, base::MessageLoopProxy::current())); |
| 260 deletable_file_ = |
| 261 ShareableFileReference::GetOrCreate( |
| 262 file_path, |
| 263 ShareableFileReference::DELETE_ON_FINAL_RELEASE, |
| 264 BrowserThread::GetMessageLoopProxyForThread( |
| 265 BrowserThread::FILE).get()); |
| 266 } |
| 267 |
| 268 // These methods are only callable before CreateResourceHandler is called. |
| 269 net::testing::MockFileStream* file_stream() const { |
| 270 return file_stream_.get(); |
| 271 } |
| 272 ShareableFileReference* deletable_file() const { |
| 273 return deletable_file_.get(); |
| 274 } |
| 275 |
| 276 scoped_ptr<RedirectToFileResourceHandler> CreateResourceHandler( |
| 277 scoped_ptr<ResourceHandler> next_handler, |
| 278 net::URLRequest* request) { |
| 279 scoped_ptr<RedirectToFileResourceHandler> handler( |
| 280 new RedirectToFileResourceHandler(next_handler.Pass(), request)); |
| 281 handler->SetCreateTemporaryFileStreamFunctionForTesting( |
| 282 base::Bind(&RedirectToFileMock::PostCallback, |
| 283 base::Unretained(this))); |
| 284 return handler.Pass(); |
| 285 } |
| 286 |
| 287 private: |
| 288 void PostCallback(const CreateTemporaryFileStreamCallback& callback) { |
| 289 CHECK(file_stream_); |
| 290 CHECK(deletable_file_); |
| 291 base::MessageLoop::current()->PostTask( |
| 292 FROM_HERE, |
| 293 base::Bind(callback, base::File::FILE_OK, |
| 294 base::Passed(file_stream_.PassAs<net::FileStream>()), |
| 295 deletable_file_)); |
| 296 deletable_file_ = NULL; |
| 297 } |
| 298 |
| 299 scoped_ptr<net::testing::MockFileStream> file_stream_; |
| 300 scoped_refptr<ShareableFileReference> deletable_file_; |
| 301 |
| 302 DISALLOW_COPY_AND_ASSIGN(RedirectToFileMock); |
| 303 }; |
| 304 |
| 172 } // namespace | 305 } // namespace |
| 173 | 306 |
| 174 class ResourceLoaderTest : public testing::Test, | 307 class ResourceLoaderTest : public testing::Test, |
| 175 public ResourceLoaderDelegate { | 308 public ResourceLoaderDelegate { |
| 176 protected: | 309 protected: |
| 177 ResourceLoaderTest() | 310 ResourceLoaderTest() |
| 178 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), | 311 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), |
| 179 resource_context_(&test_url_request_context_) { | 312 resource_context_(&test_url_request_context_) { |
| 313 job_factory_.SetProtocolHandler( |
| 314 "test", net::URLRequestTestJob::CreateProtocolHandler()); |
| 315 test_url_request_context_.set_job_factory(&job_factory_); |
| 316 } |
| 317 |
| 318 scoped_ptr<net::URLRequest> CreateTestRequest(const GURL& url) { |
| 319 const int kRenderProcessId = 1; |
| 320 const int kRenderViewId = 2; |
| 321 |
| 322 scoped_ptr<net::URLRequest> request( |
| 323 new net::URLRequest(url, net::DEFAULT_PRIORITY, NULL, |
| 324 resource_context_.GetRequestContext())); |
| 325 ResourceRequestInfo::AllocateForTesting(request.get(), |
| 326 ResourceType::MAIN_FRAME, |
| 327 &resource_context_, |
| 328 kRenderProcessId, |
| 329 kRenderViewId, |
| 330 MSG_ROUTING_NONE, |
| 331 false); |
| 332 return request.Pass(); |
| 180 } | 333 } |
| 181 | 334 |
| 182 // ResourceLoaderDelegate: | 335 // ResourceLoaderDelegate: |
| 183 virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( | 336 virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( |
| 184 ResourceLoader* loader, | 337 ResourceLoader* loader, |
| 185 net::AuthChallengeInfo* auth_info) OVERRIDE { | 338 net::AuthChallengeInfo* auth_info) OVERRIDE { |
| 186 return NULL; | 339 return NULL; |
| 187 } | 340 } |
| 188 virtual bool HandleExternalProtocol(ResourceLoader* loader, | 341 virtual bool HandleExternalProtocol(ResourceLoader* loader, |
| 189 const GURL& url) OVERRIDE { | 342 const GURL& url) OVERRIDE { |
| 190 return false; | 343 return false; |
| 191 } | 344 } |
| 192 virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {} | 345 virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {} |
| 193 virtual void DidReceiveRedirect(ResourceLoader* loader, | 346 virtual void DidReceiveRedirect(ResourceLoader* loader, |
| 194 const GURL& new_url) OVERRIDE {} | 347 const GURL& new_url) OVERRIDE {} |
| 195 virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {} | 348 virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {} |
| 196 virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {} | 349 virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {} |
| 197 | 350 |
| 198 content::TestBrowserThreadBundle thread_bundle_; | 351 content::TestBrowserThreadBundle thread_bundle_; |
| 199 | 352 |
| 353 net::URLRequestJobFactoryImpl job_factory_; |
| 200 net::TestURLRequestContext test_url_request_context_; | 354 net::TestURLRequestContext test_url_request_context_; |
| 201 ResourceContextStub resource_context_; | 355 ResourceContextStub resource_context_; |
| 202 }; | 356 }; |
| 203 | 357 |
| 204 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested() | 358 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested() |
| 205 // causes client cert store to be queried for certificates and if the returned | 359 // causes client cert store to be queried for certificates and if the returned |
| 206 // certificates are correctly passed to the content browser client for | 360 // certificates are correctly passed to the content browser client for |
| 207 // selection. | 361 // selection. |
| 208 TEST_F(ResourceLoaderTest, ClientCertStoreLookup) { | 362 TEST_F(ResourceLoaderTest, ClientCertStoreLookup) { |
| 209 const int kRenderProcessId = 1; | 363 scoped_ptr<net::URLRequest> request = CreateTestRequest(GURL("dummy")); |
| 210 const int kRenderViewId = 2; | |
| 211 | |
| 212 scoped_ptr<net::URLRequest> request( | |
| 213 new net::URLRequest(GURL("dummy"), | |
| 214 net::DEFAULT_PRIORITY, | |
| 215 NULL, | |
| 216 resource_context_.GetRequestContext())); | |
| 217 ResourceRequestInfo::AllocateForTesting(request.get(), | |
| 218 ResourceType::MAIN_FRAME, | |
| 219 &resource_context_, | |
| 220 kRenderProcessId, | |
| 221 kRenderViewId, | |
| 222 MSG_ROUTING_NONE, | |
| 223 false); | |
| 224 | 364 |
| 225 // Set up the test client cert store. | 365 // Set up the test client cert store. |
| 226 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>( | 366 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>( |
| 227 new net::X509Certificate("test", "test", base::Time(), base::Time()))); | 367 new net::X509Certificate("test", "test", base::Time(), base::Time()))); |
| 228 scoped_ptr<ClientCertStoreStub> test_store( | 368 scoped_ptr<ClientCertStoreStub> test_store( |
| 229 new ClientCertStoreStub(dummy_certs)); | 369 new ClientCertStoreStub(dummy_certs)); |
| 230 EXPECT_EQ(0, test_store->request_count()); | 370 EXPECT_EQ(0, test_store->request_count()); |
| 231 | 371 |
| 232 // Ownership of the |request| and |test_store| is about to be turned over to | 372 // Ownership of the |request| and |test_store| is about to be turned over to |
| 233 // ResourceLoader. We need to keep raw pointer copies to access these objects | 373 // ResourceLoader. We need to keep raw pointer copies to access these objects |
| 234 // later. | 374 // later. |
| 235 net::URLRequest* raw_ptr_to_request = request.get(); | 375 net::URLRequest* raw_ptr_to_request = request.get(); |
| 236 ClientCertStoreStub* raw_ptr_to_store = test_store.get(); | 376 ClientCertStoreStub* raw_ptr_to_store = test_store.get(); |
| 237 resource_context_.SetClientCertStore( | 377 resource_context_.SetClientCertStore( |
| 238 test_store.PassAs<net::ClientCertStore>()); | 378 test_store.PassAs<net::ClientCertStore>()); |
| 239 | 379 |
| 240 scoped_ptr<ResourceHandler> resource_handler(new ResourceHandlerStub()); | 380 scoped_ptr<ResourceHandler> resource_handler( |
| 381 new ResourceHandlerStub(request.get())); |
| 241 ResourceLoader loader(request.Pass(), resource_handler.Pass(), this); | 382 ResourceLoader loader(request.Pass(), resource_handler.Pass(), this); |
| 242 | 383 |
| 243 // Prepare a dummy certificate request. | 384 // Prepare a dummy certificate request. |
| 244 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( | 385 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( |
| 245 new net::SSLCertRequestInfo()); | 386 new net::SSLCertRequestInfo()); |
| 246 std::vector<std::string> dummy_authority(1, "dummy"); | 387 std::vector<std::string> dummy_authority(1, "dummy"); |
| 247 cert_request_info->cert_authorities = dummy_authority; | 388 cert_request_info->cert_authorities = dummy_authority; |
| 248 | 389 |
| 249 // Plug in test content browser client. | 390 // Plug in test content browser client. |
| 250 SelectCertificateBrowserClient test_client; | 391 SelectCertificateBrowserClient test_client; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 265 // Check if the retrieved certificates were passed to the content browser | 406 // Check if the retrieved certificates were passed to the content browser |
| 266 // client. | 407 // client. |
| 267 EXPECT_EQ(1, test_client.call_count()); | 408 EXPECT_EQ(1, test_client.call_count()); |
| 268 EXPECT_EQ(dummy_certs, test_client.passed_certs()); | 409 EXPECT_EQ(dummy_certs, test_client.passed_certs()); |
| 269 } | 410 } |
| 270 | 411 |
| 271 // Verifies if a call to net::URLRequest::Delegate::OnCertificateRequested() | 412 // Verifies if a call to net::URLRequest::Delegate::OnCertificateRequested() |
| 272 // on a platform with a NULL client cert store still calls the content browser | 413 // on a platform with a NULL client cert store still calls the content browser |
| 273 // client for selection. | 414 // client for selection. |
| 274 TEST_F(ResourceLoaderTest, ClientCertStoreNull) { | 415 TEST_F(ResourceLoaderTest, ClientCertStoreNull) { |
| 275 const int kRenderProcessId = 1; | 416 scoped_ptr<net::URLRequest> request = CreateTestRequest(GURL("dummy")); |
| 276 const int kRenderViewId = 2; | |
| 277 | |
| 278 scoped_ptr<net::URLRequest> request( | |
| 279 new net::URLRequest(GURL("dummy"), | |
| 280 net::DEFAULT_PRIORITY, | |
| 281 NULL, | |
| 282 resource_context_.GetRequestContext())); | |
| 283 ResourceRequestInfo::AllocateForTesting(request.get(), | |
| 284 ResourceType::MAIN_FRAME, | |
| 285 &resource_context_, | |
| 286 kRenderProcessId, | |
| 287 kRenderViewId, | |
| 288 MSG_ROUTING_NONE, | |
| 289 false); | |
| 290 | 417 |
| 291 // Ownership of the |request| is about to be turned over to ResourceLoader. We | 418 // Ownership of the |request| is about to be turned over to ResourceLoader. We |
| 292 // need to keep a raw pointer copy to access this object later. | 419 // need to keep a raw pointer copy to access this object later. |
| 293 net::URLRequest* raw_ptr_to_request = request.get(); | 420 net::URLRequest* raw_ptr_to_request = request.get(); |
| 294 | 421 |
| 295 scoped_ptr<ResourceHandler> resource_handler(new ResourceHandlerStub()); | 422 scoped_ptr<ResourceHandler> resource_handler( |
| 423 new ResourceHandlerStub(request.get())); |
| 296 ResourceLoader loader(request.Pass(), resource_handler.Pass(), this); | 424 ResourceLoader loader(request.Pass(), resource_handler.Pass(), this); |
| 297 | 425 |
| 298 // Prepare a dummy certificate request. | 426 // Prepare a dummy certificate request. |
| 299 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( | 427 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( |
| 300 new net::SSLCertRequestInfo()); | 428 new net::SSLCertRequestInfo()); |
| 301 std::vector<std::string> dummy_authority(1, "dummy"); | 429 std::vector<std::string> dummy_authority(1, "dummy"); |
| 302 cert_request_info->cert_authorities = dummy_authority; | 430 cert_request_info->cert_authorities = dummy_authority; |
| 303 | 431 |
| 304 // Plug in test content browser client. | 432 // Plug in test content browser client. |
| 305 SelectCertificateBrowserClient test_client; | 433 SelectCertificateBrowserClient test_client; |
| 306 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client); | 434 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client); |
| 307 | 435 |
| 308 // Everything is set up. Trigger the resource loader certificate request event | 436 // Everything is set up. Trigger the resource loader certificate request event |
| 309 // and run the message loop. | 437 // and run the message loop. |
| 310 loader.OnCertificateRequested(raw_ptr_to_request, cert_request_info.get()); | 438 loader.OnCertificateRequested(raw_ptr_to_request, cert_request_info.get()); |
| 311 base::RunLoop().RunUntilIdle(); | 439 base::RunLoop().RunUntilIdle(); |
| 312 | 440 |
| 313 // Restore the original content browser client. | 441 // Restore the original content browser client. |
| 314 SetBrowserClientForTesting(old_client); | 442 SetBrowserClientForTesting(old_client); |
| 315 | 443 |
| 316 // Check if the SelectClientCertificate was called on the content browser | 444 // Check if the SelectClientCertificate was called on the content browser |
| 317 // client. | 445 // client. |
| 318 EXPECT_EQ(1, test_client.call_count()); | 446 EXPECT_EQ(1, test_client.call_count()); |
| 319 EXPECT_EQ(net::CertificateList(), test_client.passed_certs()); | 447 EXPECT_EQ(net::CertificateList(), test_client.passed_certs()); |
| 320 } | 448 } |
| 321 | 449 |
| 450 // Tests that a RedirectToFileResourceHandler works and forwards everything |
| 451 // downstream. |
| 452 TEST_F(ResourceLoaderTest, RedirectToFile) { |
| 453 RedirectToFileMock redirect_to_file_mock; |
| 454 base::FilePath temp_path = redirect_to_file_mock.deletable_file()->path(); |
| 455 |
| 456 // Set up the request. |
| 457 scoped_ptr<net::URLRequest> request = CreateTestRequest( |
| 458 net::URLRequestTestJob::test_url_1()); |
| 459 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); |
| 460 scoped_ptr<ResourceHandler> resource_handler(leaf_handler); |
| 461 resource_handler = redirect_to_file_mock.CreateResourceHandler( |
| 462 resource_handler.Pass(), request.get()); |
| 463 scoped_ptr<ResourceLoader> loader(new ResourceLoader( |
| 464 request.Pass(), resource_handler.Pass(), this)); |
| 465 |
| 466 // Run it to completion. |
| 467 loader->StartRequest(); |
| 468 base::RunLoop().RunUntilIdle(); |
| 469 |
| 470 // Check that the handler forwarded all information to the downstream handler. |
| 471 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path); |
| 472 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url()); |
| 473 EXPECT_TRUE(leaf_handler->received_response_completed()); |
| 474 EXPECT_EQ(net::URLRequestStatus::SUCCESS, leaf_handler->status().status()); |
| 475 EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(), |
| 476 static_cast<size_t>(leaf_handler->total_bytes_downloaded())); |
| 477 |
| 478 // Check that the data was written to the file. |
| 479 std::string contents; |
| 480 ASSERT_TRUE(base::ReadFileToString(temp_path, &contents)); |
| 481 EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents); |
| 482 |
| 483 // Release the loader. The file should be gone now. |
| 484 loader.reset(); |
| 485 base::RunLoop().RunUntilIdle(); |
| 486 EXPECT_FALSE(base::PathExists(temp_path)); |
| 487 } |
| 488 |
| 489 // Tests that RedirectToFileResourceHandler handles errors in creating the |
| 490 // temporary file. |
| 491 TEST_F(ResourceLoaderTest, RedirectToFileCreateTemporaryError) { |
| 492 // Set up the request. |
| 493 scoped_ptr<net::URLRequest> request = CreateTestRequest( |
| 494 net::URLRequestTestJob::test_url_1()); |
| 495 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); |
| 496 |
| 497 scoped_ptr<RedirectToFileResourceHandler> resource_handler( |
| 498 new RedirectToFileResourceHandler( |
| 499 scoped_ptr<ResourceHandler>(leaf_handler), request.get())); |
| 500 resource_handler->SetCreateTemporaryFileStreamFunctionForTesting( |
| 501 base::Bind(&CreateTemporaryError, base::File::FILE_ERROR_FAILED)); |
| 502 |
| 503 scoped_ptr<ResourceLoader> loader(new ResourceLoader( |
| 504 request.Pass(), resource_handler.PassAs<ResourceHandler>(), this)); |
| 505 |
| 506 // Run it to completion. |
| 507 loader->StartRequest(); |
| 508 base::RunLoop().RunUntilIdle(); |
| 509 |
| 510 // To downstream, the request was canceled. |
| 511 EXPECT_TRUE(leaf_handler->received_response_completed()); |
| 512 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status()); |
| 513 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded()); |
| 514 } |
| 515 |
| 516 // Tests that RedirectToFileResourceHandler handles synchronous write errors. |
| 517 TEST_F(ResourceLoaderTest, RedirectToFileWriteError) { |
| 518 RedirectToFileMock redirect_to_file_mock; |
| 519 base::FilePath temp_path = redirect_to_file_mock.deletable_file()->path(); |
| 520 net::testing::MockFileStream* mock_file_stream = |
| 521 redirect_to_file_mock.file_stream(); |
| 522 mock_file_stream->set_forced_error(net::ERR_FAILED); |
| 523 |
| 524 // Set up the request. |
| 525 scoped_ptr<net::URLRequest> request = CreateTestRequest( |
| 526 net::URLRequestTestJob::test_url_1()); |
| 527 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); |
| 528 scoped_ptr<ResourceHandler> resource_handler(leaf_handler); |
| 529 resource_handler = redirect_to_file_mock.CreateResourceHandler( |
| 530 resource_handler.Pass(), request.get()); |
| 531 scoped_ptr<ResourceLoader> loader(new ResourceLoader( |
| 532 request.Pass(), resource_handler.Pass(), this)); |
| 533 |
| 534 // Run it to completion. |
| 535 loader->StartRequest(); |
| 536 base::RunLoop().RunUntilIdle(); |
| 537 |
| 538 // To downstream, the request was canceled sometime after it started, but |
| 539 // before any data was written. |
| 540 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path); |
| 541 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url()); |
| 542 EXPECT_TRUE(leaf_handler->received_response_completed()); |
| 543 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status()); |
| 544 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded()); |
| 545 |
| 546 // Release the loader. The file should be gone now. |
| 547 loader.reset(); |
| 548 base::RunLoop().RunUntilIdle(); |
| 549 EXPECT_FALSE(base::PathExists(temp_path)); |
| 550 } |
| 551 |
| 552 // Tests that RedirectToFileResourceHandler handles asynchronous write errors. |
| 553 TEST_F(ResourceLoaderTest, RedirectToFileWriteErrorAsync) { |
| 554 RedirectToFileMock redirect_to_file_mock; |
| 555 base::FilePath temp_path = redirect_to_file_mock.deletable_file()->path(); |
| 556 net::testing::MockFileStream* mock_file_stream = |
| 557 redirect_to_file_mock.file_stream(); |
| 558 mock_file_stream->set_forced_error_async(net::ERR_FAILED); |
| 559 |
| 560 // Set up the request. |
| 561 scoped_ptr<net::URLRequest> request = CreateTestRequest( |
| 562 net::URLRequestTestJob::test_url_1()); |
| 563 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); |
| 564 scoped_ptr<ResourceHandler> resource_handler(leaf_handler); |
| 565 resource_handler = redirect_to_file_mock.CreateResourceHandler( |
| 566 resource_handler.Pass(), request.get()); |
| 567 scoped_ptr<ResourceLoader> loader(new ResourceLoader( |
| 568 request.Pass(), resource_handler.Pass(), this)); |
| 569 |
| 570 // Run it to completion. |
| 571 loader->StartRequest(); |
| 572 base::RunLoop().RunUntilIdle(); |
| 573 |
| 574 // To downstream, the request was canceled sometime after it started, but |
| 575 // before any data was written. |
| 576 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path); |
| 577 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url()); |
| 578 EXPECT_TRUE(leaf_handler->received_response_completed()); |
| 579 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status()); |
| 580 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded()); |
| 581 |
| 582 // Release the loader. The file should be gone now. |
| 583 loader.reset(); |
| 584 base::RunLoop().RunUntilIdle(); |
| 585 EXPECT_FALSE(base::PathExists(temp_path)); |
| 586 } |
| 587 |
| 588 // Tests that RedirectToFileHandler defers completion if there are outstanding |
| 589 // writes and accounts for errors which occur in that time. |
| 590 TEST_F(ResourceLoaderTest, RedirectToFileDeferCompletion) { |
| 591 // Program the MockFileStream to error asynchronously, but throttle the |
| 592 // callback. |
| 593 RedirectToFileMock redirect_to_file_mock; |
| 594 base::FilePath temp_path = redirect_to_file_mock.deletable_file()->path(); |
| 595 net::testing::MockFileStream* mock_file_stream = |
| 596 redirect_to_file_mock.file_stream(); |
| 597 mock_file_stream->set_forced_error_async(net::ERR_FAILED); |
| 598 mock_file_stream->ThrottleCallbacks(); |
| 599 |
| 600 // Set up the request. |
| 601 scoped_ptr<net::URLRequest> request = CreateTestRequest( |
| 602 net::URLRequestTestJob::test_url_1()); |
| 603 net::URLRequest* raw_ptr_to_request = request.get(); |
| 604 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); |
| 605 scoped_ptr<ResourceHandler> resource_handler(leaf_handler); |
| 606 resource_handler = redirect_to_file_mock.CreateResourceHandler( |
| 607 resource_handler.Pass(), request.get()); |
| 608 scoped_ptr<ResourceLoader> loader(new ResourceLoader( |
| 609 request.Pass(), resource_handler.Pass(), this)); |
| 610 |
| 611 // Run it as far as it will go. |
| 612 loader->StartRequest(); |
| 613 base::RunLoop().RunUntilIdle(); |
| 614 |
| 615 // At this point, the request should have completed. |
| 616 EXPECT_EQ(net::URLRequestStatus::SUCCESS, |
| 617 raw_ptr_to_request->status().status()); |
| 618 |
| 619 // However, the resource loader stack is stuck somewhere after receiving the |
| 620 // response. |
| 621 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path); |
| 622 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url()); |
| 623 EXPECT_FALSE(leaf_handler->received_response_completed()); |
| 624 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded()); |
| 625 |
| 626 // Now, release the floodgates. |
| 627 mock_file_stream->ReleaseCallbacks(); |
| 628 base::RunLoop().RunUntilIdle(); |
| 629 |
| 630 // Although the URLRequest was successful, the leaf handler sees a failure |
| 631 // because the write never completed. |
| 632 EXPECT_TRUE(leaf_handler->received_response_completed()); |
| 633 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status()); |
| 634 |
| 635 // Release the loader. The file should be gone now. |
| 636 loader.reset(); |
| 637 base::RunLoop().RunUntilIdle(); |
| 638 EXPECT_FALSE(base::PathExists(temp_path)); |
| 639 } |
| 640 |
| 641 // Tests that a RedirectToFileResourceHandler behaves properly when the |
| 642 // downstream handler defers OnWillStart. |
| 643 TEST_F(ResourceLoaderTest, RedirectToFileDownstreamDeferStart) { |
| 644 RedirectToFileMock redirect_to_file_mock; |
| 645 base::FilePath temp_path = |
| 646 redirect_to_file_mock.deletable_file()->path(); |
| 647 |
| 648 // Set up the request. |
| 649 scoped_ptr<net::URLRequest> request = CreateTestRequest( |
| 650 net::URLRequestTestJob::test_url_1()); |
| 651 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); |
| 652 scoped_ptr<ResourceHandler> resource_handler(leaf_handler); |
| 653 resource_handler = redirect_to_file_mock.CreateResourceHandler( |
| 654 resource_handler.Pass(), request.get()); |
| 655 scoped_ptr<ResourceLoader> loader(new ResourceLoader( |
| 656 request.Pass(), resource_handler.Pass(), this)); |
| 657 |
| 658 // Defer OnWillStart. |
| 659 leaf_handler->set_defer_start(true); |
| 660 |
| 661 // Run as far as we'll go. |
| 662 loader->StartRequest(); |
| 663 base::RunLoop().RunUntilIdle(); |
| 664 |
| 665 // The request should have stopped at OnWillStart. |
| 666 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url()); |
| 667 EXPECT_FALSE(leaf_handler->response()); |
| 668 EXPECT_FALSE(leaf_handler->received_response_completed()); |
| 669 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded()); |
| 670 |
| 671 // Now resume the request. Now we complete. |
| 672 leaf_handler->Resume(); |
| 673 base::RunLoop().RunUntilIdle(); |
| 674 |
| 675 // Check that the handler forwarded all information to the downstream handler. |
| 676 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path); |
| 677 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url()); |
| 678 EXPECT_TRUE(leaf_handler->received_response_completed()); |
| 679 EXPECT_EQ(net::URLRequestStatus::SUCCESS, leaf_handler->status().status()); |
| 680 EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(), |
| 681 static_cast<size_t>(leaf_handler->total_bytes_downloaded())); |
| 682 |
| 683 // Check that the data was written to the file. |
| 684 std::string contents; |
| 685 ASSERT_TRUE(base::ReadFileToString(temp_path, &contents)); |
| 686 EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents); |
| 687 |
| 688 // Release the loader. The file should be gone now. |
| 689 loader.reset(); |
| 690 base::RunLoop().RunUntilIdle(); |
| 691 EXPECT_FALSE(base::PathExists(temp_path)); |
| 692 } |
| 693 |
| 322 } // namespace content | 694 } // namespace content |
| OLD | NEW |