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