OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 // This file contains an implementation of the ResourceLoaderBridge class. | 5 // This file contains an implementation of the ResourceLoaderBridge class. |
6 // The class is implemented using URLRequest, meaning it is a "simple" version | 6 // The class is implemented using URLRequest, meaning it is a "simple" version |
7 // that directly issues requests. The more complicated one used in the | 7 // that directly issues requests. The more complicated one used in the |
8 // browser uses IPC. | 8 // browser uses IPC. |
9 // | 9 // |
10 // Because URLRequest only provides an asynchronous resource loading API, this | 10 // Because URLRequest only provides an asynchronous resource loading API, this |
(...skipping 15 matching lines...) Expand all Loading... |
26 // | 26 // |
27 // NOTE: The implementation in this file may be used to have WebKit fetch | 27 // NOTE: The implementation in this file may be used to have WebKit fetch |
28 // resources in-process. For example, it is handy for building a single- | 28 // resources in-process. For example, it is handy for building a single- |
29 // process WebKit embedding (e.g., test_shell) that can use URLRequest to | 29 // process WebKit embedding (e.g., test_shell) that can use URLRequest to |
30 // perform URL loads. See renderer/resource_dispatcher.h for details on an | 30 // perform URL loads. See renderer/resource_dispatcher.h for details on an |
31 // alternate implementation that defers fetching to another process. | 31 // alternate implementation that defers fetching to another process. |
32 | 32 |
33 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h" | 33 #include "webkit/tools/test_shell/simple_resource_loader_bridge.h" |
34 | 34 |
35 #include "base/file_path.h" | 35 #include "base/file_path.h" |
36 #include "base/file_util.h" | |
37 #include "base/logging.h" | 36 #include "base/logging.h" |
38 #include "base/message_loop.h" | 37 #include "base/message_loop.h" |
39 #include "base/message_loop_proxy.h" | |
40 #if defined(OS_MACOSX) || defined(OS_WIN) | 38 #if defined(OS_MACOSX) || defined(OS_WIN) |
41 #include "base/nss_util.h" | 39 #include "base/nss_util.h" |
42 #endif | 40 #endif |
43 #include "base/ref_counted.h" | 41 #include "base/ref_counted.h" |
44 #include "base/time.h" | 42 #include "base/time.h" |
45 #include "base/timer.h" | 43 #include "base/timer.h" |
46 #include "base/thread.h" | 44 #include "base/thread.h" |
47 #include "base/waitable_event.h" | 45 #include "base/waitable_event.h" |
48 #include "net/base/cookie_store.h" | 46 #include "net/base/cookie_store.h" |
49 #include "net/base/file_stream.h" | |
50 #include "net/base/io_buffer.h" | 47 #include "net/base/io_buffer.h" |
51 #include "net/base/load_flags.h" | 48 #include "net/base/load_flags.h" |
52 #include "net/base/net_errors.h" | 49 #include "net/base/net_errors.h" |
53 #include "net/base/net_util.h" | 50 #include "net/base/net_util.h" |
54 #include "net/base/static_cookie_policy.h" | 51 #include "net/base/static_cookie_policy.h" |
55 #include "net/base/upload_data.h" | 52 #include "net/base/upload_data.h" |
56 #include "net/http/http_cache.h" | 53 #include "net/http/http_cache.h" |
57 #include "net/http/http_request_headers.h" | 54 #include "net/http/http_request_headers.h" |
58 #include "net/http/http_response_headers.h" | 55 #include "net/http/http_response_headers.h" |
59 #include "net/proxy/proxy_service.h" | 56 #include "net/proxy/proxy_service.h" |
60 #if defined(OS_WIN) | 57 #if defined(OS_WIN) |
61 #include "net/socket/ssl_client_socket_nss_factory.h" | 58 #include "net/socket/ssl_client_socket_nss_factory.h" |
62 #endif | 59 #endif |
63 #include "net/url_request/url_request.h" | 60 #include "net/url_request/url_request.h" |
64 #include "net/url_request/url_request_job.h" | 61 #include "net/url_request/url_request_job.h" |
65 #include "webkit/appcache/appcache_interfaces.h" | 62 #include "webkit/appcache/appcache_interfaces.h" |
66 #include "webkit/blob/blob_storage_controller.h" | 63 #include "webkit/blob/blob_storage_controller.h" |
67 #include "webkit/blob/blob_url_request_job.h" | 64 #include "webkit/blob/blob_url_request_job.h" |
68 #include "webkit/blob/deletable_file_reference.h" | |
69 #include "webkit/glue/resource_loader_bridge.h" | 65 #include "webkit/glue/resource_loader_bridge.h" |
70 #include "webkit/tools/test_shell/simple_appcache_system.h" | 66 #include "webkit/tools/test_shell/simple_appcache_system.h" |
71 #include "webkit/tools/test_shell/simple_socket_stream_bridge.h" | 67 #include "webkit/tools/test_shell/simple_socket_stream_bridge.h" |
72 #include "webkit/tools/test_shell/test_shell_request_context.h" | 68 #include "webkit/tools/test_shell/test_shell_request_context.h" |
73 #include "webkit/tools/test_shell/test_shell_webblobregistry_impl.h" | 69 #include "webkit/tools/test_shell/test_shell_webblobregistry_impl.h" |
74 | 70 |
75 using webkit_glue::ResourceLoaderBridge; | 71 using webkit_glue::ResourceLoaderBridge; |
76 using net::StaticCookiePolicy; | 72 using net::StaticCookiePolicy; |
77 using net::HttpResponseHeaders; | 73 using net::HttpResponseHeaders; |
78 using webkit_blob::DeletableFileReference; | |
79 | 74 |
80 namespace { | 75 namespace { |
81 | 76 |
82 struct TestShellRequestContextParams { | 77 struct TestShellRequestContextParams { |
83 TestShellRequestContextParams( | 78 TestShellRequestContextParams( |
84 const FilePath& in_cache_path, | 79 const FilePath& in_cache_path, |
85 net::HttpCache::Mode in_cache_mode, | 80 net::HttpCache::Mode in_cache_mode, |
86 bool in_no_proxy) | 81 bool in_no_proxy) |
87 : cache_path(in_cache_path), | 82 : cache_path(in_cache_path), |
88 cache_mode(in_cache_mode), | 83 cache_mode(in_cache_mode), |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 | 167 |
173 struct RequestParams { | 168 struct RequestParams { |
174 std::string method; | 169 std::string method; |
175 GURL url; | 170 GURL url; |
176 GURL first_party_for_cookies; | 171 GURL first_party_for_cookies; |
177 GURL referrer; | 172 GURL referrer; |
178 std::string headers; | 173 std::string headers; |
179 int load_flags; | 174 int load_flags; |
180 ResourceType::Type request_type; | 175 ResourceType::Type request_type; |
181 int appcache_host_id; | 176 int appcache_host_id; |
182 bool download_to_file; | |
183 scoped_refptr<net::UploadData> upload; | 177 scoped_refptr<net::UploadData> upload; |
184 }; | 178 }; |
185 | 179 |
186 // The interval for calls to RequestProxy::MaybeUpdateUploadProgress | 180 // The interval for calls to RequestProxy::MaybeUpdateUploadProgress |
187 static const int kUpdateUploadProgressIntervalMsec = 100; | 181 static const int kUpdateUploadProgressIntervalMsec = 100; |
188 | 182 |
189 // The RequestProxy does most of its work on the IO thread. The Start and | 183 // The RequestProxy does most of its work on the IO thread. The Start and |
190 // Cancel methods are proxied over to the IO thread, where an URLRequest object | 184 // Cancel methods are proxied over to the IO thread, where an URLRequest object |
191 // is instantiated. | 185 // is instantiated. |
192 class RequestProxy : public URLRequest::Delegate, | 186 class RequestProxy : public URLRequest::Delegate, |
193 public base::RefCountedThreadSafe<RequestProxy> { | 187 public base::RefCountedThreadSafe<RequestProxy> { |
194 public: | 188 public: |
195 // Takes ownership of the params. | 189 // Takes ownership of the params. |
196 RequestProxy() | 190 RequestProxy() |
197 : download_to_file_(false), | 191 : buf_(new net::IOBuffer(kDataSize)), |
198 buf_(new net::IOBuffer(kDataSize)), | |
199 last_upload_position_(0) { | 192 last_upload_position_(0) { |
200 } | 193 } |
201 | 194 |
202 void DropPeer() { | 195 void DropPeer() { |
203 peer_ = NULL; | 196 peer_ = NULL; |
204 } | 197 } |
205 | 198 |
206 void Start(ResourceLoaderBridge::Peer* peer, RequestParams* params) { | 199 void Start(ResourceLoaderBridge::Peer* peer, RequestParams* params) { |
207 peer_ = peer; | 200 peer_ = peer; |
208 owner_loop_ = MessageLoop::current(); | 201 owner_loop_ = MessageLoop::current(); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 // race condition). If the order of the next 2 functions were reversed, the | 260 // race condition). If the order of the next 2 functions were reversed, the |
268 // peer could generate new requests in reponse to the received data, which | 261 // peer could generate new requests in reponse to the received data, which |
269 // when run on the io thread, could race against this function in doing | 262 // when run on the io thread, could race against this function in doing |
270 // another InvokeLater. See bug 769249. | 263 // another InvokeLater. See bug 769249. |
271 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | 264 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( |
272 this, &RequestProxy::AsyncReadData)); | 265 this, &RequestProxy::AsyncReadData)); |
273 | 266 |
274 peer_->OnReceivedData(buf_copy.get(), bytes_read); | 267 peer_->OnReceivedData(buf_copy.get(), bytes_read); |
275 } | 268 } |
276 | 269 |
277 void NotifyDownloadedData(int bytes_read) { | |
278 if (!peer_) | |
279 return; | |
280 | |
281 // Continue reading more data, see the comment in NotifyReceivedData. | |
282 g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( | |
283 this, &RequestProxy::AsyncReadData)); | |
284 | |
285 peer_->OnDownloadedData(bytes_read); | |
286 } | |
287 | |
288 void NotifyCompletedRequest(const URLRequestStatus& status, | 270 void NotifyCompletedRequest(const URLRequestStatus& status, |
289 const std::string& security_info, | 271 const std::string& security_info, |
290 const base::Time& complete_time) { | 272 const base::Time& complete_time) { |
291 if (peer_) { | 273 if (peer_) { |
292 peer_->OnCompletedRequest(status, security_info, complete_time); | 274 peer_->OnCompletedRequest(status, security_info, complete_time); |
293 DropPeer(); // ensure no further notifications | 275 DropPeer(); // ensure no further notifications |
294 } | 276 } |
295 } | 277 } |
296 | 278 |
297 void NotifyUploadProgress(uint64 position, uint64 size) { | 279 void NotifyUploadProgress(uint64 position, uint64 size) { |
(...skipping 19 matching lines...) Expand all Loading... |
317 request_->set_referrer(params->referrer.spec()); | 299 request_->set_referrer(params->referrer.spec()); |
318 net::HttpRequestHeaders headers; | 300 net::HttpRequestHeaders headers; |
319 headers.AddHeadersFromString(params->headers); | 301 headers.AddHeadersFromString(params->headers); |
320 request_->SetExtraRequestHeaders(headers); | 302 request_->SetExtraRequestHeaders(headers); |
321 request_->set_load_flags(params->load_flags); | 303 request_->set_load_flags(params->load_flags); |
322 request_->set_upload(params->upload.get()); | 304 request_->set_upload(params->upload.get()); |
323 request_->set_context(g_request_context); | 305 request_->set_context(g_request_context); |
324 SimpleAppCacheSystem::SetExtraRequestInfo( | 306 SimpleAppCacheSystem::SetExtraRequestInfo( |
325 request_.get(), params->appcache_host_id, params->request_type); | 307 request_.get(), params->appcache_host_id, params->request_type); |
326 | 308 |
327 download_to_file_ = params->download_to_file; | |
328 if (download_to_file_) { | |
329 FilePath path; | |
330 if (file_util::CreateTemporaryFile(&path)) { | |
331 downloaded_file_ = DeletableFileReference::GetOrCreate( | |
332 path, base::MessageLoopProxy::CreateForCurrentThread()); | |
333 file_stream_.Open( | |
334 path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE); | |
335 } | |
336 } | |
337 | |
338 request_->Start(); | 309 request_->Start(); |
339 | 310 |
340 if (request_->has_upload() && | 311 if (request_->has_upload() && |
341 params->load_flags & net::LOAD_ENABLE_UPLOAD_PROGRESS) { | 312 params->load_flags & net::LOAD_ENABLE_UPLOAD_PROGRESS) { |
342 upload_progress_timer_.Start( | 313 upload_progress_timer_.Start( |
343 base::TimeDelta::FromMilliseconds(kUpdateUploadProgressIntervalMsec), | 314 base::TimeDelta::FromMilliseconds(kUpdateUploadProgressIntervalMsec), |
344 this, &RequestProxy::MaybeUpdateUploadProgress); | 315 this, &RequestProxy::MaybeUpdateUploadProgress); |
345 } | 316 } |
346 | 317 |
347 delete params; | 318 delete params; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 } | 370 } |
400 | 371 |
401 virtual void OnReceivedResponse( | 372 virtual void OnReceivedResponse( |
402 const ResourceLoaderBridge::ResponseInfo& info, | 373 const ResourceLoaderBridge::ResponseInfo& info, |
403 bool content_filtered) { | 374 bool content_filtered) { |
404 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 375 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
405 this, &RequestProxy::NotifyReceivedResponse, info, content_filtered)); | 376 this, &RequestProxy::NotifyReceivedResponse, info, content_filtered)); |
406 } | 377 } |
407 | 378 |
408 virtual void OnReceivedData(int bytes_read) { | 379 virtual void OnReceivedData(int bytes_read) { |
409 if (download_to_file_) { | |
410 file_stream_.Write(buf_->data(), bytes_read, NULL); | |
411 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | |
412 this, &RequestProxy::NotifyDownloadedData, bytes_read)); | |
413 return; | |
414 } | |
415 | |
416 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 380 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
417 this, &RequestProxy::NotifyReceivedData, bytes_read)); | 381 this, &RequestProxy::NotifyReceivedData, bytes_read)); |
418 } | 382 } |
419 | 383 |
420 virtual void OnCompletedRequest(const URLRequestStatus& status, | 384 virtual void OnCompletedRequest(const URLRequestStatus& status, |
421 const std::string& security_info, | 385 const std::string& security_info, |
422 const base::Time& complete_time) { | 386 const base::Time& complete_time) { |
423 if (download_to_file_) | |
424 file_stream_.Close(); | |
425 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( | 387 owner_loop_->PostTask(FROM_HERE, NewRunnableMethod( |
426 this, | 388 this, |
427 &RequestProxy::NotifyCompletedRequest, | 389 &RequestProxy::NotifyCompletedRequest, |
428 status, | 390 status, |
429 security_info, | 391 security_info, |
430 complete_time)); | 392 complete_time)); |
431 } | 393 } |
432 | 394 |
433 // -------------------------------------------------------------------------- | 395 // -------------------------------------------------------------------------- |
434 // URLRequest::Delegate implementation: | 396 // URLRequest::Delegate implementation: |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 } | 479 } |
518 | 480 |
519 void PopulateResponseInfo(URLRequest* request, | 481 void PopulateResponseInfo(URLRequest* request, |
520 ResourceLoaderBridge::ResponseInfo* info) const { | 482 ResourceLoaderBridge::ResponseInfo* info) const { |
521 info->request_time = request->request_time(); | 483 info->request_time = request->request_time(); |
522 info->response_time = request->response_time(); | 484 info->response_time = request->response_time(); |
523 info->headers = request->response_headers(); | 485 info->headers = request->response_headers(); |
524 request->GetMimeType(&info->mime_type); | 486 request->GetMimeType(&info->mime_type); |
525 request->GetCharset(&info->charset); | 487 request->GetCharset(&info->charset); |
526 info->content_length = request->GetExpectedContentSize(); | 488 info->content_length = request->GetExpectedContentSize(); |
527 if (downloaded_file_) | |
528 info->download_file_path = downloaded_file_->path(); | |
529 SimpleAppCacheSystem::GetExtraResponseInfo( | 489 SimpleAppCacheSystem::GetExtraResponseInfo( |
530 request, | 490 request, |
531 &info->appcache_id, | 491 &info->appcache_id, |
532 &info->appcache_manifest_url); | 492 &info->appcache_manifest_url); |
533 } | 493 } |
534 | 494 |
535 scoped_ptr<URLRequest> request_; | 495 scoped_ptr<URLRequest> request_; |
536 | 496 |
537 // Support for request.download_to_file behavior. | |
538 bool download_to_file_; | |
539 net::FileStream file_stream_; | |
540 scoped_refptr<DeletableFileReference> downloaded_file_; | |
541 | |
542 // Size of our async IO data buffers | 497 // Size of our async IO data buffers |
543 static const int kDataSize = 16*1024; | 498 static const int kDataSize = 16*1024; |
544 | 499 |
545 // read buffer for async IO | 500 // read buffer for async IO |
546 scoped_refptr<net::IOBuffer> buf_; | 501 scoped_refptr<net::IOBuffer> buf_; |
547 | 502 |
548 MessageLoop* owner_loop_; | 503 MessageLoop* owner_loop_; |
549 | 504 |
550 // This is our peer in WebKit (implemented as ResourceHandleInternal). We do | 505 // This is our peer in WebKit (implemented as ResourceHandleInternal). We do |
551 // not manage its lifetime, and we may only access it from the owner's | 506 // not manage its lifetime, and we may only access it from the owner's |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 result_->url = new_url; | 546 result_->url = new_url; |
592 } | 547 } |
593 | 548 |
594 virtual void OnReceivedResponse( | 549 virtual void OnReceivedResponse( |
595 const ResourceLoaderBridge::ResponseInfo& info, | 550 const ResourceLoaderBridge::ResponseInfo& info, |
596 bool content_filtered) { | 551 bool content_filtered) { |
597 *static_cast<ResourceLoaderBridge::ResponseInfo*>(result_) = info; | 552 *static_cast<ResourceLoaderBridge::ResponseInfo*>(result_) = info; |
598 } | 553 } |
599 | 554 |
600 virtual void OnReceivedData(int bytes_read) { | 555 virtual void OnReceivedData(int bytes_read) { |
601 if (download_to_file_) | 556 result_->data.append(buf_->data(), bytes_read); |
602 file_stream_.Write(buf_->data(), bytes_read, NULL); | |
603 else | |
604 result_->data.append(buf_->data(), bytes_read); | |
605 AsyncReadData(); // read more (may recurse) | 557 AsyncReadData(); // read more (may recurse) |
606 } | 558 } |
607 | 559 |
608 virtual void OnCompletedRequest(const URLRequestStatus& status, | 560 virtual void OnCompletedRequest(const URLRequestStatus& status, |
609 const std::string& security_info, | 561 const std::string& security_info, |
610 const base::Time& complete_time) { | 562 const base::Time& complete_time) { |
611 if (download_to_file_) | |
612 file_stream_.Close(); | |
613 result_->status = status; | 563 result_->status = status; |
614 event_.Signal(); | 564 event_.Signal(); |
615 } | 565 } |
616 | 566 |
617 private: | 567 private: |
618 ResourceLoaderBridge::SyncLoadResponse* result_; | 568 ResourceLoaderBridge::SyncLoadResponse* result_; |
619 base::WaitableEvent event_; | 569 base::WaitableEvent event_; |
620 }; | 570 }; |
621 | 571 |
622 //----------------------------------------------------------------------------- | 572 //----------------------------------------------------------------------------- |
623 | 573 |
624 class ResourceLoaderBridgeImpl : public ResourceLoaderBridge { | 574 class ResourceLoaderBridgeImpl : public ResourceLoaderBridge { |
625 public: | 575 public: |
626 ResourceLoaderBridgeImpl( | 576 ResourceLoaderBridgeImpl( |
627 const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) | 577 const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) |
628 : params_(new RequestParams), | 578 : params_(new RequestParams), |
629 proxy_(NULL) { | 579 proxy_(NULL) { |
| 580 DCHECK(!request_info.download_to_file); // Not implemented yet! |
630 params_->method = request_info.method; | 581 params_->method = request_info.method; |
631 params_->url = request_info.url; | 582 params_->url = request_info.url; |
632 params_->first_party_for_cookies = request_info.first_party_for_cookies; | 583 params_->first_party_for_cookies = request_info.first_party_for_cookies; |
633 params_->referrer = request_info.referrer; | 584 params_->referrer = request_info.referrer; |
634 params_->headers = request_info.headers; | 585 params_->headers = request_info.headers; |
635 params_->load_flags = request_info.load_flags; | 586 params_->load_flags = request_info.load_flags; |
636 params_->request_type = request_info.request_type; | 587 params_->request_type = request_info.request_type; |
637 params_->appcache_host_id = request_info.appcache_host_id; | 588 params_->appcache_host_id = request_info.appcache_host_id; |
638 params_->download_to_file = request_info.download_to_file; | |
639 } | 589 } |
640 | 590 |
641 virtual ~ResourceLoaderBridgeImpl() { | 591 virtual ~ResourceLoaderBridgeImpl() { |
642 if (proxy_) { | 592 if (proxy_) { |
643 proxy_->DropPeer(); | 593 proxy_->DropPeer(); |
644 // Let the proxy die on the IO thread | 594 // Let the proxy die on the IO thread |
645 g_io_thread->message_loop()->ReleaseSoon(FROM_HERE, proxy_); | 595 g_io_thread->message_loop()->ReleaseSoon(FROM_HERE, proxy_); |
646 } | 596 } |
647 } | 597 } |
648 | 598 |
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
922 | 872 |
923 // static | 873 // static |
924 scoped_refptr<base::MessageLoopProxy> | 874 scoped_refptr<base::MessageLoopProxy> |
925 SimpleResourceLoaderBridge::GetIoThread() { | 875 SimpleResourceLoaderBridge::GetIoThread() { |
926 if (!EnsureIOThread()) { | 876 if (!EnsureIOThread()) { |
927 LOG(DFATAL) << "Failed to create IO thread."; | 877 LOG(DFATAL) << "Failed to create IO thread."; |
928 return NULL; | 878 return NULL; |
929 } | 879 } |
930 return g_io_thread->message_loop_proxy(); | 880 return g_io_thread->message_loop_proxy(); |
931 } | 881 } |
OLD | NEW |