Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(501)

Side by Side Diff: webkit/tools/test_shell/simple_resource_loader_bridge.cc

Issue 3396029: Flesh out URLLoader's download_to_file function.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/glue/weburlloader_impl.cc ('k') | webkit/tools/test_shell/test_shell.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « webkit/glue/weburlloader_impl.cc ('k') | webkit/tools/test_shell/test_shell.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698