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