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