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