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/message_loop/message_loop_proxy.h" | |
| 9 #include "base/platform_file.h" | |
| 7 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| 8 #include "content/browser/browser_thread_impl.h" | 11 #include "content/browser/browser_thread_impl.h" |
| 12 #include "content/browser/loader/redirect_to_file_resource_handler.h" | |
| 9 #include "content/browser/loader/resource_loader_delegate.h" | 13 #include "content/browser/loader/resource_loader_delegate.h" |
| 10 #include "content/public/browser/resource_request_info.h" | 14 #include "content/public/browser/resource_request_info.h" |
| 15 #include "content/public/common/resource_response.h" | |
| 11 #include "content/public/test/mock_resource_context.h" | 16 #include "content/public/test/mock_resource_context.h" |
| 12 #include "content/public/test/test_browser_thread_bundle.h" | 17 #include "content/public/test/test_browser_thread_bundle.h" |
| 13 #include "content/test/test_content_browser_client.h" | 18 #include "content/test/test_content_browser_client.h" |
| 19 #include "net/base/mock_file_stream.h" | |
| 14 #include "net/base/request_priority.h" | 20 #include "net/base/request_priority.h" |
| 15 #include "net/cert/x509_certificate.h" | 21 #include "net/cert/x509_certificate.h" |
| 16 #include "net/ssl/client_cert_store.h" | 22 #include "net/ssl/client_cert_store.h" |
| 17 #include "net/ssl/ssl_cert_request_info.h" | 23 #include "net/ssl/ssl_cert_request_info.h" |
| 18 #include "net/url_request/url_request.h" | 24 #include "net/url_request/url_request.h" |
| 25 #include "net/url_request/url_request_job_factory_impl.h" | |
| 26 #include "net/url_request/url_request_test_job.h" | |
| 19 #include "net/url_request/url_request_test_util.h" | 27 #include "net/url_request/url_request_test_util.h" |
| 20 #include "testing/gtest/include/gtest/gtest.h" | 28 #include "testing/gtest/include/gtest/gtest.h" |
| 29 #include "webkit/common/blob/shareable_file_reference.h" | |
| 30 | |
| 31 using webkit_blob::ShareableFileReference; | |
| 21 | 32 |
| 22 namespace content { | 33 namespace content { |
| 23 namespace { | 34 namespace { |
| 24 | 35 |
| 25 // Stub client certificate store that returns a preset list of certificates for | 36 // Stub client certificate store that returns a preset list of certificates for |
| 26 // each request and records the arguments of the most recent request for later | 37 // each request and records the arguments of the most recent request for later |
| 27 // inspection. | 38 // inspection. |
| 28 class ClientCertStoreStub : public net::ClientCertStore { | 39 class ClientCertStoreStub : public net::ClientCertStore { |
| 29 public: | 40 public: |
| 30 ClientCertStoreStub(const net::CertificateList& certs) | 41 ClientCertStoreStub(const net::CertificateList& certs) |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 61 private: | 72 private: |
| 62 const net::CertificateList response_; | 73 const net::CertificateList response_; |
| 63 int request_count_; | 74 int request_count_; |
| 64 std::vector<std::string> requested_authorities_; | 75 std::vector<std::string> requested_authorities_; |
| 65 }; | 76 }; |
| 66 | 77 |
| 67 // Dummy implementation of ResourceHandler, instance of which is needed to | 78 // Dummy implementation of ResourceHandler, instance of which is needed to |
| 68 // initialize ResourceLoader. | 79 // initialize ResourceLoader. |
| 69 class ResourceHandlerStub : public ResourceHandler { | 80 class ResourceHandlerStub : public ResourceHandler { |
| 70 public: | 81 public: |
| 71 ResourceHandlerStub() : ResourceHandler(NULL) {} | 82 ResourceHandlerStub(net::URLRequest* request) |
| 83 : ResourceHandler(request), | |
| 84 received_response_completed_(false), | |
| 85 total_bytes_downloaded_(0) { | |
| 86 } | |
| 87 | |
| 88 const GURL& start_url() const { return start_url_; } | |
| 89 ResourceResponse* response() const { return response_.get(); } | |
| 90 bool received_response_completed() const { | |
| 91 return received_response_completed_; | |
| 92 } | |
| 93 const net::URLRequestStatus& status() const { return status_; } | |
| 94 int total_bytes_downloaded() const { return total_bytes_downloaded_; } | |
| 72 | 95 |
| 73 virtual bool OnUploadProgress(int request_id, | 96 virtual bool OnUploadProgress(int request_id, |
| 74 uint64 position, | 97 uint64 position, |
| 75 uint64 size) OVERRIDE { | 98 uint64 size) OVERRIDE { |
| 76 return true; | 99 return true; |
| 77 } | 100 } |
| 78 | 101 |
| 79 virtual bool OnRequestRedirected(int request_id, | 102 virtual bool OnRequestRedirected(int request_id, |
| 80 const GURL& url, | 103 const GURL& url, |
| 81 ResourceResponse* response, | 104 ResourceResponse* response, |
| 82 bool* defer) OVERRIDE { | 105 bool* defer) OVERRIDE { |
| 83 return true; | 106 return true; |
| 84 } | 107 } |
| 85 | 108 |
| 86 virtual bool OnResponseStarted(int request_id, | 109 virtual bool OnResponseStarted(int request_id, |
| 87 ResourceResponse* response, | 110 ResourceResponse* response, |
| 88 bool* defer) OVERRIDE { return true; } | 111 bool* defer) OVERRIDE { |
| 112 DCHECK(!response_); | |
| 113 response_ = response; | |
| 114 return true; | |
| 115 } | |
| 89 | 116 |
| 90 virtual bool OnWillStart(int request_id, | 117 virtual bool OnWillStart(int request_id, |
| 91 const GURL& url, | 118 const GURL& url, |
| 92 bool* defer) OVERRIDE { | 119 bool* defer) OVERRIDE { |
| 120 DCHECK(start_url_.is_empty()); | |
| 121 start_url_ = url; | |
| 93 return true; | 122 return true; |
| 94 } | 123 } |
| 95 | 124 |
| 96 virtual bool OnWillRead(int request_id, | 125 virtual bool OnWillRead(int request_id, |
| 97 scoped_refptr<net::IOBuffer>* buf, | 126 scoped_refptr<net::IOBuffer>* buf, |
| 98 int* buf_size, | 127 int* buf_size, |
| 99 int min_size) OVERRIDE { | 128 int min_size) OVERRIDE { |
| 100 return true; | 129 NOTREACHED(); |
| 130 return false; | |
|
davidben
2013/11/26 22:59:53
These weren't called by the existing tests and are
| |
| 101 } | 131 } |
| 102 | 132 |
| 103 virtual bool OnReadCompleted(int request_id, | 133 virtual bool OnReadCompleted(int request_id, |
| 104 int bytes_read, | 134 int bytes_read, |
| 105 bool* defer) OVERRIDE { | 135 bool* defer) OVERRIDE { |
| 106 return true; | 136 NOTREACHED(); |
| 137 return false; | |
| 107 } | 138 } |
| 108 | 139 |
| 109 virtual void OnResponseCompleted(int request_id, | 140 virtual void OnResponseCompleted(int request_id, |
| 110 const net::URLRequestStatus& status, | 141 const net::URLRequestStatus& status, |
| 111 const std::string& security_info, | 142 const std::string& security_info, |
| 112 bool* defer) OVERRIDE { | 143 bool* defer) OVERRIDE { |
| 144 // TODO(davidben): This DCHECK currently fires everywhere. Fix the places in | |
| 145 // ResourceLoader where OnResponseCompleted is signaled twice. | |
| 146 // DCHECK(!received_response_completed_); | |
| 147 received_response_completed_ = true; | |
| 148 status_ = status; | |
| 113 } | 149 } |
| 114 | 150 |
| 115 virtual void OnDataDownloaded(int request_id, | 151 virtual void OnDataDownloaded(int request_id, |
| 116 int bytes_downloaded) OVERRIDE {} | 152 int bytes_downloaded) OVERRIDE { |
| 153 total_bytes_downloaded_ += bytes_downloaded; | |
| 154 } | |
| 155 | |
| 156 private: | |
| 157 GURL start_url_; | |
| 158 scoped_refptr<ResourceResponse> response_; | |
| 159 bool received_response_completed_; | |
| 160 net::URLRequestStatus status_; | |
| 161 int total_bytes_downloaded_; | |
| 117 }; | 162 }; |
| 118 | 163 |
| 119 // Test browser client that captures calls to SelectClientCertificates and | 164 // Test browser client that captures calls to SelectClientCertificates and |
| 120 // records the arguments of the most recent call for later inspection. | 165 // records the arguments of the most recent call for later inspection. |
| 121 class SelectCertificateBrowserClient : public TestContentBrowserClient { | 166 class SelectCertificateBrowserClient : public TestContentBrowserClient { |
| 122 public: | 167 public: |
| 123 SelectCertificateBrowserClient() : call_count_(0) {} | 168 SelectCertificateBrowserClient() : call_count_(0) {} |
| 124 | 169 |
| 125 virtual void SelectClientCertificate( | 170 virtual void SelectClientCertificate( |
| 126 int render_process_id, | 171 int render_process_id, |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 155 } | 200 } |
| 156 | 201 |
| 157 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) { | 202 void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) { |
| 158 dummy_cert_store_ = store.Pass(); | 203 dummy_cert_store_ = store.Pass(); |
| 159 } | 204 } |
| 160 | 205 |
| 161 private: | 206 private: |
| 162 scoped_ptr<net::ClientCertStore> dummy_cert_store_; | 207 scoped_ptr<net::ClientCertStore> dummy_cert_store_; |
| 163 }; | 208 }; |
| 164 | 209 |
| 210 class MockTemporaryFileStreamFactory : public TemporaryFileStreamFactory { | |
| 211 public: | |
| 212 MockTemporaryFileStreamFactory() | |
| 213 : error_(base::PLATFORM_FILE_OK) { | |
| 214 CreateNextTemporary(); | |
| 215 } | |
| 216 | |
| 217 net::testing::MockFileStream* next_file_stream() const { | |
| 218 return next_file_stream_.get(); | |
| 219 } | |
| 220 ShareableFileReference* next_deletable_file() const { | |
| 221 return next_deletable_file_.get(); | |
| 222 } | |
| 223 | |
| 224 void set_next_error(base::PlatformFileError error) { | |
| 225 DCHECK_EQ(base::PLATFORM_FILE_OK, error_); | |
| 226 error_ = error; | |
| 227 } | |
| 228 | |
| 229 // MockTemporaryFileStreamFactory implementation: | |
| 230 virtual void CreateTemporary(int child_id, | |
| 231 int request_id, | |
| 232 const Callback& callback) { | |
| 233 base::MessageLoop::current()->PostTask( | |
| 234 FROM_HERE, | |
| 235 base::Bind(&MockTemporaryFileStreamFactory::DoCallback, | |
| 236 base::Unretained(this), callback)); | |
| 237 } | |
| 238 | |
| 239 private: | |
| 240 void CreateNextTemporary() { | |
| 241 DCHECK(!next_file_stream_); | |
| 242 | |
| 243 base::FilePath file_path; | |
| 244 ASSERT_TRUE(file_util::CreateTemporaryFile(&file_path)); | |
| 245 base::PlatformFile platform_file = | |
| 246 base::CreatePlatformFile(file_path, | |
| 247 base::PLATFORM_FILE_WRITE | | |
| 248 base::PLATFORM_FILE_TEMPORARY | | |
| 249 base::PLATFORM_FILE_CREATE_ALWAYS | | |
| 250 base::PLATFORM_FILE_ASYNC, | |
| 251 NULL, NULL); | |
| 252 ASSERT_NE(base::kInvalidPlatformFileValue, platform_file); | |
| 253 next_file_stream_.reset( | |
| 254 new net::testing::MockFileStream( | |
| 255 platform_file, | |
| 256 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, | |
| 257 NULL, base::MessageLoopProxy::current())); | |
| 258 next_deletable_file_ = | |
| 259 ShareableFileReference::GetOrCreate( | |
| 260 file_path, | |
| 261 ShareableFileReference::DELETE_ON_FINAL_RELEASE, | |
| 262 BrowserThread::GetMessageLoopProxyForThread( | |
| 263 BrowserThread::FILE).get()); | |
| 264 } | |
| 265 | |
| 266 void DoCallback(const Callback& callback) { | |
| 267 if (error_ != base::PLATFORM_FILE_OK) { | |
| 268 callback.Run(error_, scoped_ptr<net::FileStream>(), NULL); | |
| 269 error_ = base::PLATFORM_FILE_OK; | |
| 270 } else { | |
| 271 DCHECK(next_file_stream_); | |
| 272 callback.Run(base::PLATFORM_FILE_OK, | |
| 273 next_file_stream_.PassAs<net::FileStream>(), | |
| 274 next_deletable_file_.get()); | |
| 275 next_deletable_file_ = NULL; | |
| 276 } | |
| 277 } | |
| 278 | |
| 279 base::PlatformFileError error_; | |
| 280 scoped_ptr<net::testing::MockFileStream> next_file_stream_; | |
| 281 scoped_refptr<ShareableFileReference> next_deletable_file_; | |
| 282 }; | |
| 283 | |
| 165 } // namespace | 284 } // namespace |
| 166 | 285 |
| 167 class ResourceLoaderTest : public testing::Test, | 286 class ResourceLoaderTest : public testing::Test, |
| 168 public ResourceLoaderDelegate { | 287 public ResourceLoaderDelegate { |
| 169 protected: | 288 protected: |
| 170 ResourceLoaderTest() | 289 ResourceLoaderTest() |
| 171 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), | 290 : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), |
| 172 resource_context_(&test_url_request_context_) { | 291 resource_context_(&test_url_request_context_) { |
| 173 } | 292 } |
| 174 | 293 |
| 294 virtual void SetUp() OVERRIDE { | |
| 295 job_factory_.SetProtocolHandler( | |
| 296 "test", net::URLRequestTestJob::CreateProtocolHandler()); | |
| 297 test_url_request_context_.set_job_factory(&job_factory_); | |
| 298 } | |
| 299 | |
| 300 virtual void TearDown() OVERRIDE { | |
| 301 } | |
| 302 | |
| 303 scoped_ptr<net::URLRequest> CreateTestRequest(const GURL& url) { | |
| 304 const int kRenderProcessId = 1; | |
| 305 const int kRenderViewId = 2; | |
| 306 | |
| 307 scoped_ptr<net::URLRequest> request( | |
| 308 new net::URLRequest(url, net::DEFAULT_PRIORITY, NULL, | |
| 309 resource_context_.GetRequestContext())); | |
| 310 ResourceRequestInfo::AllocateForTesting(request.get(), | |
| 311 ResourceType::MAIN_FRAME, | |
| 312 &resource_context_, | |
| 313 kRenderProcessId, | |
| 314 kRenderViewId, | |
| 315 false); | |
| 316 return request.Pass(); | |
| 317 } | |
| 318 | |
| 175 // ResourceLoaderDelegate: | 319 // ResourceLoaderDelegate: |
| 176 virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( | 320 virtual ResourceDispatcherHostLoginDelegate* CreateLoginDelegate( |
| 177 ResourceLoader* loader, | 321 ResourceLoader* loader, |
| 178 net::AuthChallengeInfo* auth_info) OVERRIDE { | 322 net::AuthChallengeInfo* auth_info) OVERRIDE { |
| 179 return NULL; | 323 return NULL; |
| 180 } | 324 } |
| 181 virtual bool AcceptAuthRequest( | 325 virtual bool AcceptAuthRequest( |
| 182 ResourceLoader* loader, | 326 ResourceLoader* loader, |
| 183 net::AuthChallengeInfo* auth_info) OVERRIDE { | 327 net::AuthChallengeInfo* auth_info) OVERRIDE { |
| 184 return false; | 328 return false; |
| 185 }; | 329 }; |
| 186 virtual bool AcceptSSLClientCertificateRequest( | 330 virtual bool AcceptSSLClientCertificateRequest( |
| 187 ResourceLoader* loader, | 331 ResourceLoader* loader, |
| 188 net::SSLCertRequestInfo* cert_info) OVERRIDE { | 332 net::SSLCertRequestInfo* cert_info) OVERRIDE { |
| 189 return true; | 333 return true; |
| 190 } | 334 } |
| 191 virtual bool HandleExternalProtocol(ResourceLoader* loader, | 335 virtual bool HandleExternalProtocol(ResourceLoader* loader, |
| 192 const GURL& url) OVERRIDE { | 336 const GURL& url) OVERRIDE { |
| 193 return false; | 337 return false; |
| 194 } | 338 } |
| 195 virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {} | 339 virtual void DidStartRequest(ResourceLoader* loader) OVERRIDE {} |
| 196 virtual void DidReceiveRedirect(ResourceLoader* loader, | 340 virtual void DidReceiveRedirect(ResourceLoader* loader, |
| 197 const GURL& new_url) OVERRIDE {} | 341 const GURL& new_url) OVERRIDE {} |
| 198 virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {} | 342 virtual void DidReceiveResponse(ResourceLoader* loader) OVERRIDE {} |
| 199 virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {} | 343 virtual void DidFinishLoading(ResourceLoader* loader) OVERRIDE {} |
| 200 | 344 |
| 201 content::TestBrowserThreadBundle thread_bundle_; | 345 content::TestBrowserThreadBundle thread_bundle_; |
| 202 | 346 |
| 347 net::URLRequestJobFactoryImpl job_factory_; | |
| 203 net::TestURLRequestContext test_url_request_context_; | 348 net::TestURLRequestContext test_url_request_context_; |
| 204 ResourceContextStub resource_context_; | 349 ResourceContextStub resource_context_; |
| 205 }; | 350 }; |
| 206 | 351 |
| 207 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested() | 352 // Verifies if a call to net::UrlRequest::Delegate::OnCertificateRequested() |
| 208 // causes client cert store to be queried for certificates and if the returned | 353 // causes client cert store to be queried for certificates and if the returned |
| 209 // certificates are correctly passed to the content browser client for | 354 // certificates are correctly passed to the content browser client for |
| 210 // selection. | 355 // selection. |
| 211 TEST_F(ResourceLoaderTest, ClientCertStoreLookup) { | 356 TEST_F(ResourceLoaderTest, ClientCertStoreLookup) { |
| 212 const int kRenderProcessId = 1; | 357 scoped_ptr<net::URLRequest> request = CreateTestRequest(GURL("dummy")); |
| 213 const int kRenderViewId = 2; | |
| 214 | |
| 215 scoped_ptr<net::URLRequest> request( | |
| 216 new net::URLRequest(GURL("dummy"), | |
| 217 net::DEFAULT_PRIORITY, | |
| 218 NULL, | |
| 219 resource_context_.GetRequestContext())); | |
| 220 ResourceRequestInfo::AllocateForTesting(request.get(), | |
| 221 ResourceType::MAIN_FRAME, | |
| 222 &resource_context_, | |
| 223 kRenderProcessId, | |
| 224 kRenderViewId, | |
| 225 false); | |
| 226 | 358 |
| 227 // Set up the test client cert store. | 359 // Set up the test client cert store. |
| 228 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>( | 360 net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>( |
| 229 new net::X509Certificate("test", "test", base::Time(), base::Time()))); | 361 new net::X509Certificate("test", "test", base::Time(), base::Time()))); |
| 230 scoped_ptr<ClientCertStoreStub> test_store( | 362 scoped_ptr<ClientCertStoreStub> test_store( |
| 231 new ClientCertStoreStub(dummy_certs)); | 363 new ClientCertStoreStub(dummy_certs)); |
| 232 EXPECT_EQ(0, test_store->request_count()); | 364 EXPECT_EQ(0, test_store->request_count()); |
| 233 | 365 |
| 234 // Ownership of the |request| and |test_store| is about to be turned over to | 366 // Ownership of the |request| and |test_store| is about to be turned over to |
| 235 // ResourceLoader. We need to keep raw pointer copies to access these objects | 367 // ResourceLoader. We need to keep raw pointer copies to access these objects |
| 236 // later. | 368 // later. |
| 237 net::URLRequest* raw_ptr_to_request = request.get(); | 369 net::URLRequest* raw_ptr_to_request = request.get(); |
| 238 ClientCertStoreStub* raw_ptr_to_store = test_store.get(); | 370 ClientCertStoreStub* raw_ptr_to_store = test_store.get(); |
| 239 resource_context_.SetClientCertStore( | 371 resource_context_.SetClientCertStore( |
| 240 test_store.PassAs<net::ClientCertStore>()); | 372 test_store.PassAs<net::ClientCertStore>()); |
| 241 | 373 |
| 242 scoped_ptr<ResourceHandler> resource_handler(new ResourceHandlerStub()); | 374 scoped_ptr<ResourceHandler> resource_handler( |
| 375 new ResourceHandlerStub(request.get())); | |
| 243 ResourceLoader loader(request.Pass(), resource_handler.Pass(), this); | 376 ResourceLoader loader(request.Pass(), resource_handler.Pass(), this); |
| 244 | 377 |
| 245 // Prepare a dummy certificate request. | 378 // Prepare a dummy certificate request. |
| 246 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( | 379 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( |
| 247 new net::SSLCertRequestInfo()); | 380 new net::SSLCertRequestInfo()); |
| 248 std::vector<std::string> dummy_authority(1, "dummy"); | 381 std::vector<std::string> dummy_authority(1, "dummy"); |
| 249 cert_request_info->cert_authorities = dummy_authority; | 382 cert_request_info->cert_authorities = dummy_authority; |
| 250 | 383 |
| 251 // Plug in test content browser client. | 384 // Plug in test content browser client. |
| 252 SelectCertificateBrowserClient test_client; | 385 SelectCertificateBrowserClient test_client; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 267 // Check if the retrieved certificates were passed to the content browser | 400 // Check if the retrieved certificates were passed to the content browser |
| 268 // client. | 401 // client. |
| 269 EXPECT_EQ(1, test_client.call_count()); | 402 EXPECT_EQ(1, test_client.call_count()); |
| 270 EXPECT_EQ(dummy_certs, test_client.passed_certs()); | 403 EXPECT_EQ(dummy_certs, test_client.passed_certs()); |
| 271 } | 404 } |
| 272 | 405 |
| 273 // Verifies if a call to net::URLRequest::Delegate::OnCertificateRequested() | 406 // Verifies if a call to net::URLRequest::Delegate::OnCertificateRequested() |
| 274 // on a platform with a NULL client cert store still calls the content browser | 407 // on a platform with a NULL client cert store still calls the content browser |
| 275 // client for selection. | 408 // client for selection. |
| 276 TEST_F(ResourceLoaderTest, ClientCertStoreNull) { | 409 TEST_F(ResourceLoaderTest, ClientCertStoreNull) { |
| 277 const int kRenderProcessId = 1; | 410 scoped_ptr<net::URLRequest> request = CreateTestRequest(GURL("dummy")); |
| 278 const int kRenderViewId = 2; | |
| 279 | |
| 280 scoped_ptr<net::URLRequest> request( | |
| 281 new net::URLRequest(GURL("dummy"), | |
| 282 net::DEFAULT_PRIORITY, | |
| 283 NULL, | |
| 284 resource_context_.GetRequestContext())); | |
| 285 ResourceRequestInfo::AllocateForTesting(request.get(), | |
| 286 ResourceType::MAIN_FRAME, | |
| 287 &resource_context_, | |
| 288 kRenderProcessId, | |
| 289 kRenderViewId, | |
| 290 false); | |
| 291 | 411 |
| 292 // Ownership of the |request| is about to be turned over to ResourceLoader. We | 412 // Ownership of the |request| is about to be turned over to ResourceLoader. We |
| 293 // need to keep a raw pointer copy to access this object later. | 413 // need to keep a raw pointer copy to access this object later. |
| 294 net::URLRequest* raw_ptr_to_request = request.get(); | 414 net::URLRequest* raw_ptr_to_request = request.get(); |
| 295 | 415 |
| 296 scoped_ptr<ResourceHandler> resource_handler(new ResourceHandlerStub()); | 416 scoped_ptr<ResourceHandler> resource_handler( |
| 417 new ResourceHandlerStub(request.get())); | |
| 297 ResourceLoader loader(request.Pass(), resource_handler.Pass(), this); | 418 ResourceLoader loader(request.Pass(), resource_handler.Pass(), this); |
| 298 | 419 |
| 299 // Prepare a dummy certificate request. | 420 // Prepare a dummy certificate request. |
| 300 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( | 421 scoped_refptr<net::SSLCertRequestInfo> cert_request_info( |
| 301 new net::SSLCertRequestInfo()); | 422 new net::SSLCertRequestInfo()); |
| 302 std::vector<std::string> dummy_authority(1, "dummy"); | 423 std::vector<std::string> dummy_authority(1, "dummy"); |
| 303 cert_request_info->cert_authorities = dummy_authority; | 424 cert_request_info->cert_authorities = dummy_authority; |
| 304 | 425 |
| 305 // Plug in test content browser client. | 426 // Plug in test content browser client. |
| 306 SelectCertificateBrowserClient test_client; | 427 SelectCertificateBrowserClient test_client; |
| 307 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client); | 428 ContentBrowserClient* old_client = SetBrowserClientForTesting(&test_client); |
| 308 | 429 |
| 309 // Everything is set up. Trigger the resource loader certificate request event | 430 // Everything is set up. Trigger the resource loader certificate request event |
| 310 // and run the message loop. | 431 // and run the message loop. |
| 311 loader.OnCertificateRequested(raw_ptr_to_request, cert_request_info.get()); | 432 loader.OnCertificateRequested(raw_ptr_to_request, cert_request_info.get()); |
| 312 base::RunLoop().RunUntilIdle(); | 433 base::RunLoop().RunUntilIdle(); |
| 313 | 434 |
| 314 // Restore the original content browser client. | 435 // Restore the original content browser client. |
| 315 SetBrowserClientForTesting(old_client); | 436 SetBrowserClientForTesting(old_client); |
| 316 | 437 |
| 317 // Check if the SelectClientCertificate was called on the content browser | 438 // Check if the SelectClientCertificate was called on the content browser |
| 318 // client. | 439 // client. |
| 319 EXPECT_EQ(1, test_client.call_count()); | 440 EXPECT_EQ(1, test_client.call_count()); |
| 320 EXPECT_EQ(net::CertificateList(), test_client.passed_certs()); | 441 EXPECT_EQ(net::CertificateList(), test_client.passed_certs()); |
| 321 } | 442 } |
| 322 | 443 |
| 444 // Tests that a RedirectToFileResourceHandler works and forwards everything | |
| 445 // downstream. | |
| 446 TEST_F(ResourceLoaderTest, RedirectToFile) { | |
| 447 MockTemporaryFileStreamFactory file_stream_factory; | |
| 448 base::FilePath temp_path = file_stream_factory.next_deletable_file()->path(); | |
| 449 | |
| 450 // Setup the request. | |
| 451 scoped_ptr<net::URLRequest> request = CreateTestRequest( | |
| 452 net::URLRequestTestJob::test_url_1()); | |
| 453 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); | |
| 454 scoped_ptr<ResourceHandler> resource_handler(leaf_handler); | |
| 455 resource_handler.reset( | |
| 456 new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(), | |
| 457 &file_stream_factory)); | |
| 458 scoped_ptr<ResourceLoader> loader(new ResourceLoader( | |
| 459 request.Pass(), resource_handler.Pass(), this)); | |
| 460 | |
| 461 // Run it to completion. | |
| 462 loader->StartRequest(); | |
| 463 base::RunLoop().RunUntilIdle(); | |
| 464 | |
| 465 // Check that the handler forwarded all information to the downstream handler. | |
| 466 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path); | |
| 467 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url()); | |
| 468 EXPECT_TRUE(leaf_handler->received_response_completed()); | |
| 469 EXPECT_EQ(net::URLRequestStatus::SUCCESS, leaf_handler->status().status()); | |
| 470 EXPECT_EQ(net::URLRequestTestJob::test_data_1().size(), | |
| 471 static_cast<size_t>(leaf_handler->total_bytes_downloaded())); | |
| 472 | |
| 473 // Check that the data was written to the file. | |
| 474 std::string contents; | |
| 475 ASSERT_TRUE(base::ReadFileToString(temp_path, &contents)); | |
| 476 EXPECT_EQ(net::URLRequestTestJob::test_data_1(), contents); | |
| 477 | |
| 478 // Release the loader. The file should be gone now. | |
| 479 loader.reset(); | |
| 480 base::RunLoop().RunUntilIdle(); | |
| 481 EXPECT_FALSE(base::PathExists(temp_path)); | |
| 482 } | |
| 483 | |
| 484 // Tests that RedirectToFileResourceHandler handles errors in creating the | |
| 485 // temporary file. | |
| 486 TEST_F(ResourceLoaderTest, RedirectToFileCreateTemporaryError) { | |
| 487 MockTemporaryFileStreamFactory file_stream_factory; | |
| 488 file_stream_factory.set_next_error(base::PLATFORM_FILE_ERROR_FAILED); | |
| 489 | |
| 490 // Setup the request. | |
| 491 scoped_ptr<net::URLRequest> request = CreateTestRequest( | |
| 492 net::URLRequestTestJob::test_url_1()); | |
| 493 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); | |
| 494 scoped_ptr<ResourceHandler> resource_handler(leaf_handler); | |
| 495 resource_handler.reset( | |
| 496 new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(), | |
| 497 &file_stream_factory)); | |
| 498 scoped_ptr<ResourceLoader> loader(new ResourceLoader( | |
| 499 request.Pass(), resource_handler.Pass(), this)); | |
| 500 | |
| 501 // Run it to completion. | |
| 502 loader->StartRequest(); | |
| 503 base::RunLoop().RunUntilIdle(); | |
| 504 | |
| 505 // To downstream, the request was canceled. | |
| 506 EXPECT_TRUE(leaf_handler->received_response_completed()); | |
| 507 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status()); | |
| 508 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded()); | |
| 509 } | |
| 510 | |
| 511 // Tests that RedirectToFileResourceHandler handles synchronous write errors. | |
| 512 TEST_F(ResourceLoaderTest, RedirectToFileWriteError) { | |
| 513 MockTemporaryFileStreamFactory file_stream_factory; | |
| 514 base::FilePath temp_path = file_stream_factory.next_deletable_file()->path(); | |
| 515 net::testing::MockFileStream* mock_file_stream = | |
| 516 file_stream_factory.next_file_stream(); | |
| 517 mock_file_stream->set_forced_error(net::ERR_FAILED); | |
| 518 | |
| 519 // Setup the request. | |
| 520 scoped_ptr<net::URLRequest> request = CreateTestRequest( | |
| 521 net::URLRequestTestJob::test_url_1()); | |
| 522 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); | |
| 523 scoped_ptr<ResourceHandler> resource_handler(leaf_handler); | |
| 524 resource_handler.reset( | |
| 525 new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(), | |
| 526 &file_stream_factory)); | |
| 527 scoped_ptr<ResourceLoader> loader(new ResourceLoader( | |
| 528 request.Pass(), resource_handler.Pass(), this)); | |
| 529 | |
| 530 // Run it to completion. | |
| 531 loader->StartRequest(); | |
| 532 base::RunLoop().RunUntilIdle(); | |
| 533 | |
| 534 // To downstream, the request was canceled sometime after it started, but | |
| 535 // before any data was written. | |
| 536 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path); | |
| 537 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url()); | |
| 538 EXPECT_TRUE(leaf_handler->received_response_completed()); | |
| 539 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status()); | |
| 540 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded()); | |
| 541 } | |
| 542 | |
| 543 // Tests that RedirectToFileResourceHandler handles asynchronous write errors. | |
| 544 TEST_F(ResourceLoaderTest, RedirectToFileWriteErrorAsync) { | |
| 545 MockTemporaryFileStreamFactory file_stream_factory; | |
| 546 base::FilePath temp_path = file_stream_factory.next_deletable_file()->path(); | |
| 547 net::testing::MockFileStream* mock_file_stream = | |
| 548 file_stream_factory.next_file_stream(); | |
| 549 mock_file_stream->set_forced_error_async(net::ERR_FAILED); | |
| 550 | |
| 551 // Setup the request. | |
| 552 scoped_ptr<net::URLRequest> request = CreateTestRequest( | |
| 553 net::URLRequestTestJob::test_url_1()); | |
| 554 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); | |
| 555 scoped_ptr<ResourceHandler> resource_handler(leaf_handler); | |
| 556 resource_handler.reset( | |
| 557 new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(), | |
| 558 &file_stream_factory)); | |
| 559 scoped_ptr<ResourceLoader> loader(new ResourceLoader( | |
| 560 request.Pass(), resource_handler.Pass(), this)); | |
| 561 | |
| 562 // Run it to completion. | |
| 563 loader->StartRequest(); | |
| 564 base::RunLoop().RunUntilIdle(); | |
| 565 | |
| 566 // To downstream, the request was canceled sometime after it started, but | |
| 567 // before any data was written. | |
| 568 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path); | |
| 569 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url()); | |
| 570 EXPECT_TRUE(leaf_handler->received_response_completed()); | |
| 571 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status()); | |
| 572 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded()); | |
| 573 } | |
| 574 | |
| 575 // Tests that RedirectToFileHandler defers completion if there are outstanding | |
| 576 // writes and accounts for errors which occur in that time. | |
| 577 TEST_F(ResourceLoaderTest, RedirectToFileDeferCompletion) { | |
| 578 // Program the MockFileStream to error asynchronously, but throttle the | |
| 579 // callback. | |
| 580 MockTemporaryFileStreamFactory file_stream_factory; | |
| 581 base::FilePath temp_path = file_stream_factory.next_deletable_file()->path(); | |
| 582 net::testing::MockFileStream* mock_file_stream = | |
| 583 file_stream_factory.next_file_stream(); | |
| 584 mock_file_stream->set_forced_error_async(net::ERR_FAILED); | |
| 585 mock_file_stream->ThrottleCallbacks(); | |
| 586 | |
| 587 // Setup the request. | |
| 588 scoped_ptr<net::URLRequest> request = CreateTestRequest( | |
| 589 net::URLRequestTestJob::test_url_1()); | |
| 590 net::URLRequest* raw_ptr_to_request = request.get(); | |
| 591 ResourceHandlerStub* leaf_handler = new ResourceHandlerStub(request.get()); | |
| 592 scoped_ptr<ResourceHandler> resource_handler(leaf_handler); | |
| 593 resource_handler.reset( | |
| 594 new RedirectToFileResourceHandler(resource_handler.Pass(), request.get(), | |
| 595 &file_stream_factory)); | |
| 596 scoped_ptr<ResourceLoader> loader(new ResourceLoader( | |
| 597 request.Pass(), resource_handler.Pass(), this)); | |
| 598 | |
| 599 // Run it as far as it will go. | |
| 600 loader->StartRequest(); | |
| 601 base::RunLoop().RunUntilIdle(); | |
| 602 | |
| 603 // At this point, the request should have completed. | |
| 604 EXPECT_EQ(net::URLRequestStatus::SUCCESS, | |
| 605 raw_ptr_to_request->status().status()); | |
| 606 | |
| 607 // However, the resource loader stack is stuck somewhere after receiving the | |
| 608 // response. | |
| 609 EXPECT_EQ(temp_path, leaf_handler->response()->head.download_file_path); | |
| 610 EXPECT_EQ(net::URLRequestTestJob::test_url_1(), leaf_handler->start_url()); | |
| 611 EXPECT_FALSE(leaf_handler->received_response_completed()); | |
| 612 EXPECT_EQ(0, leaf_handler->total_bytes_downloaded()); | |
| 613 | |
| 614 // Now, release the floodgates. | |
| 615 mock_file_stream->ReleaseCallbacks(); | |
| 616 base::RunLoop().RunUntilIdle(); | |
| 617 | |
| 618 // Although the URLRequest was successful, the leaf handler sees a failure | |
| 619 // because the write never completed. | |
| 620 EXPECT_TRUE(leaf_handler->received_response_completed()); | |
| 621 EXPECT_EQ(net::URLRequestStatus::CANCELED, leaf_handler->status().status()); | |
| 622 } | |
| 623 | |
| 323 } // namespace content | 624 } // namespace content |
| OLD | NEW |