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

Side by Side Diff: content/browser/download/download_manager_impl.cc

Issue 11571025: Initial CL for Downloads resumption. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Incorporated comments. Created 7 years, 11 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/download/download_manager_impl.h" 5 #include "content/browser/download/download_manager_impl.h"
6 6
7 #include <iterator> 7 #include <iterator>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
(...skipping 21 matching lines...) Expand all
32 #include "content/public/browser/browser_thread.h" 32 #include "content/public/browser/browser_thread.h"
33 #include "content/public/browser/content_browser_client.h" 33 #include "content/public/browser/content_browser_client.h"
34 #include "content/public/browser/download_interrupt_reasons.h" 34 #include "content/public/browser/download_interrupt_reasons.h"
35 #include "content/public/browser/download_manager_delegate.h" 35 #include "content/public/browser/download_manager_delegate.h"
36 #include "content/public/browser/download_url_parameters.h" 36 #include "content/public/browser/download_url_parameters.h"
37 #include "content/public/browser/notification_service.h" 37 #include "content/public/browser/notification_service.h"
38 #include "content/public/browser/notification_types.h" 38 #include "content/public/browser/notification_types.h"
39 #include "content/public/browser/render_process_host.h" 39 #include "content/public/browser/render_process_host.h"
40 #include "content/public/browser/resource_context.h" 40 #include "content/public/browser/resource_context.h"
41 #include "content/public/browser/web_contents_delegate.h" 41 #include "content/public/browser/web_contents_delegate.h"
42 #include "content/public/common/referrer.h"
42 #include "net/base/load_flags.h" 43 #include "net/base/load_flags.h"
43 #include "net/base/upload_bytes_element_reader.h" 44 #include "net/base/upload_bytes_element_reader.h"
44 #include "net/base/upload_data_stream.h" 45 #include "net/base/upload_data_stream.h"
45 #include "net/url_request/url_request_context.h" 46 #include "net/url_request/url_request_context.h"
46 #include "webkit/glue/webkit_glue.h" 47 #include "webkit/glue/webkit_glue.h"
47 48
48 namespace content { 49 namespace content {
49 namespace { 50 namespace {
50 51
51 void BeginDownload(scoped_ptr<DownloadUrlParameters> params) { 52 void BeginDownload(scoped_ptr<DownloadUrlParameters> params,
53 DownloadId download_id) {
52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
53 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and 55 // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and
54 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so 56 // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so
55 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4. 57 // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4.
56 scoped_ptr<net::URLRequest> request( 58 scoped_ptr<net::URLRequest> request(
57 params->resource_context()->GetRequestContext()->CreateRequest( 59 params->resource_context()->GetRequestContext()->CreateRequest(
58 params->url(), NULL)); 60 params->url(), NULL));
59 request->set_referrer(params->referrer().url.spec()); 61 request->set_referrer(params->referrer().url.spec());
60 webkit_glue::ConfigureURLRequestForReferrerPolicy( 62 webkit_glue::ConfigureURLRequestForReferrerPolicy(
61 request.get(), params->referrer().policy); 63 request.get(), params->referrer().policy);
(...skipping 10 matching lines...) Expand all
72 // The POST in this case does not have an actual body, and only works 74 // The POST in this case does not have an actual body, and only works
73 // when retrieving data from cache. This is done because we don't want 75 // when retrieving data from cache. This is done because we don't want
74 // to do a re-POST without user consent, and currently don't have a good 76 // to do a re-POST without user consent, and currently don't have a good
75 // plan on how to display the UI for that. 77 // plan on how to display the UI for that.
76 DCHECK(params->prefer_cache()); 78 DCHECK(params->prefer_cache());
77 DCHECK(params->method() == "POST"); 79 DCHECK(params->method() == "POST");
78 ScopedVector<net::UploadElementReader> element_readers; 80 ScopedVector<net::UploadElementReader> element_readers;
79 request->set_upload(make_scoped_ptr( 81 request->set_upload(make_scoped_ptr(
80 new net::UploadDataStream(&element_readers, params->post_id()))); 82 new net::UploadDataStream(&element_readers, params->post_id())));
81 } 83 }
84
85 // If we're not at the beginning of the file, retrieve only the remaining
86 // portion.
87 if (params->offset() > 0) {
88 request->SetExtraRequestHeaderByName(
89 "Range",
90 StringPrintf("bytes=%" PRId64 "-", params->offset()),
91 true);
92
93 // If we've asked for a range, we want to make sure that we only
94 // get that range if our current copy of the information is good.
95 if (!params->last_modified().empty()) {
96 request->SetExtraRequestHeaderByName("If-Unmodified-Since",
97 params->last_modified(),
98 true);
99 }
100 if (!params->etag().empty()) {
101 request->SetExtraRequestHeaderByName("If-Match", params->etag(), true);
102 }
103 }
104
82 for (DownloadUrlParameters::RequestHeadersType::const_iterator iter 105 for (DownloadUrlParameters::RequestHeadersType::const_iterator iter
83 = params->request_headers_begin(); 106 = params->request_headers_begin();
84 iter != params->request_headers_end(); 107 iter != params->request_headers_end();
85 ++iter) { 108 ++iter) {
86 request->SetExtraRequestHeaderByName( 109 request->SetExtraRequestHeaderByName(
87 iter->first, iter->second, false/*overwrite*/); 110 iter->first, iter->second, false/*overwrite*/);
88 } 111 }
89 112
90 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo()); 113 scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
91 save_info->file_path = params->file_path(); 114 save_info->file_path = params->file_path();
92 save_info->suggested_name = params->suggested_name(); 115 save_info->suggested_name = params->suggested_name();
93 save_info->offset = params->offset(); 116 save_info->offset = params->offset();
94 save_info->hash_state = params->hash_state(); 117 save_info->hash_state = params->hash_state();
95 save_info->prompt_for_save_location = params->prompt(); 118 save_info->prompt_for_save_location = params->prompt();
96 save_info->file_stream = params->GetFileStream(); 119 save_info->file_stream = params->GetFileStream();
97 120
98 params->resource_dispatcher_host()->BeginDownload( 121 params->resource_dispatcher_host()->BeginDownload(
99 request.Pass(), 122 request.Pass(),
100 params->content_initiated(), 123 params->content_initiated(),
101 params->resource_context(), 124 params->resource_context(),
102 params->render_process_host_id(), 125 params->render_process_host_id(),
103 params->render_view_host_routing_id(), 126 params->render_view_host_routing_id(),
104 params->prefer_cache(), 127 params->prefer_cache(),
105 save_info.Pass(), 128 save_info.Pass(),
129 download_id,
106 params->callback()); 130 params->callback());
107 } 131 }
108 132
109 class MapValueIteratorAdapter { 133 class MapValueIteratorAdapter {
110 public: 134 public:
111 explicit MapValueIteratorAdapter( 135 explicit MapValueIteratorAdapter(
112 base::hash_map<int64, DownloadItem*>::const_iterator iter) 136 base::hash_map<int64, DownloadItem*>::const_iterator iter)
113 : iter_(iter) { 137 : iter_(iter) {
114 } 138 }
115 ~MapValueIteratorAdapter() {} 139 ~MapValueIteratorAdapter() {}
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 received_bytes, 190 received_bytes,
167 total_bytes, 191 total_bytes,
168 state, 192 state,
169 opened, 193 opened,
170 bound_net_log); 194 bound_net_log);
171 } 195 }
172 196
173 virtual DownloadItemImpl* CreateActiveItem( 197 virtual DownloadItemImpl* CreateActiveItem(
174 DownloadItemImplDelegate* delegate, 198 DownloadItemImplDelegate* delegate,
175 const DownloadCreateInfo& info, 199 const DownloadCreateInfo& info,
176 scoped_ptr<DownloadRequestHandleInterface> request_handle,
177 const net::BoundNetLog& bound_net_log) OVERRIDE { 200 const net::BoundNetLog& bound_net_log) OVERRIDE {
178 return new DownloadItemImpl(delegate, info, request_handle.Pass(), 201 return new DownloadItemImpl(delegate, info, bound_net_log);
179 bound_net_log);
180 } 202 }
181 203
182 virtual DownloadItemImpl* CreateSavePageItem( 204 virtual DownloadItemImpl* CreateSavePageItem(
183 DownloadItemImplDelegate* delegate, 205 DownloadItemImplDelegate* delegate,
184 const FilePath& path, 206 const FilePath& path,
185 const GURL& url, 207 const GURL& url,
186 DownloadId download_id, 208 DownloadId download_id,
187 const std::string& mime_type, 209 const std::string& mime_type,
188 const net::BoundNetLog& bound_net_log) OVERRIDE { 210 const net::BoundNetLog& bound_net_log) OVERRIDE {
189 return new DownloadItemImpl(delegate, path, url, download_id, 211 return new DownloadItemImpl(delegate, path, url, download_id,
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 browser_context_ = browser_context; 355 browser_context_ = browser_context;
334 356
335 return true; 357 return true;
336 } 358 }
337 359
338 DownloadItem* DownloadManagerImpl::StartDownload( 360 DownloadItem* DownloadManagerImpl::StartDownload(
339 scoped_ptr<DownloadCreateInfo> info, 361 scoped_ptr<DownloadCreateInfo> info,
340 scoped_ptr<ByteStreamReader> stream) { 362 scoped_ptr<ByteStreamReader> stream) {
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
342 364
343 net::BoundNetLog bound_net_log =
344 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
345
346 FilePath default_download_directory; 365 FilePath default_download_directory;
347 if (delegate_) { 366 if (delegate_) {
348 FilePath website_save_directory; // Unused 367 FilePath website_save_directory; // Unused
349 bool skip_dir_check = false; // Unused 368 bool skip_dir_check = false; // Unused
350 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory, 369 delegate_->GetSaveDir(GetBrowserContext(), &website_save_directory,
351 &default_download_directory, &skip_dir_check); 370 &default_download_directory, &skip_dir_check);
352 } 371 }
353 372
354 // We create the DownloadItem before the DownloadFile because the 373 // We create the DownloadItem before the DownloadFile because the
355 // DownloadItem already needs to handle a state in which there is 374 // DownloadItem already needs to handle a state in which there is
356 // no associated DownloadFile (history downloads, !IN_PROGRESS downloads) 375 // no associated DownloadFile (history downloads, !IN_PROGRESS downloads)
357 DownloadItemImpl* download = 376 DownloadItemImpl* download = GetOrCreateDownloadItem(info.get());
358 CreateDownloadItem(info.get(), bound_net_log);
359 scoped_ptr<DownloadFile> download_file( 377 scoped_ptr<DownloadFile> download_file(
360 file_factory_->CreateFile( 378 file_factory_->CreateFile(
361 info->save_info.Pass(), default_download_directory, 379 info->save_info.Pass(), default_download_directory,
362 info->url(), info->referrer_url, 380 info->url(), info->referrer_url,
363 delegate_->GenerateFileHash(), 381 delegate_->GenerateFileHash(),
364 stream.Pass(), bound_net_log, 382 stream.Pass(), download->GetBoundNetLog(),
365 download->DestinationObserverAsWeakPtr())); 383 download->DestinationObserverAsWeakPtr()));
366 download->Start(download_file.Pass()); 384 scoped_ptr<DownloadRequestHandleInterface> req_handle(
385 new DownloadRequestHandle(info->request_handle));
386 download->Start(download_file.Pass(), req_handle.Pass());
367 387
368 // Delay notification until after Start() so that download_file is bound 388 // Delay notification until after Start() so that download_file is bound
369 // to download and all the usual setters (e.g. Cancel) work. 389 // to download and all the usual setters (e.g. Cancel) work.
370 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download)); 390 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, download));
371 391
372 return download; 392 return download;
373 } 393 }
374 394
375 void DownloadManagerImpl::CheckForHistoryFilesRemoval() { 395 void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) { 428 void DownloadManagerImpl::OnFileRemovalDetected(int32 download_id) {
409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
410 if (ContainsKey(downloads_, download_id)) 430 if (ContainsKey(downloads_, download_id))
411 downloads_[download_id]->OnDownloadedFileRemoved(); 431 downloads_[download_id]->OnDownloadedFileRemoved();
412 } 432 }
413 433
414 BrowserContext* DownloadManagerImpl::GetBrowserContext() const { 434 BrowserContext* DownloadManagerImpl::GetBrowserContext() const {
415 return browser_context_; 435 return browser_context_;
416 } 436 }
417 437
418 DownloadItemImpl* DownloadManagerImpl::CreateDownloadItem( 438 DownloadItemImpl* DownloadManagerImpl::GetOrCreateDownloadItem(
419 DownloadCreateInfo* info, const net::BoundNetLog& bound_net_log) { 439 DownloadCreateInfo* info) {
420 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
421 441
422 if (!info->download_id.IsValid()) 442 if (!info->download_id.IsValid())
benjhayden 2013/01/08 16:41:17 Just to be clear, this allows mischievous callers
Randy Smith (Not in Mondays) 2013/01/09 22:34:37 That's why I didn't want it as part of the Downloa
423 info->download_id = GetNextId(); 443 info->download_id = GetNextId();
424 DownloadItemImpl* download = item_factory_->CreateActiveItem(
425 this, *info,
426 scoped_ptr<DownloadRequestHandleInterface>(
427 new DownloadRequestHandle(info->request_handle)).Pass(),
428 bound_net_log);
429 444
430 DCHECK(!ContainsKey(downloads_, download->GetId())); 445 DownloadItemImpl* download = NULL;
431 downloads_[download->GetId()] = download; 446 if (ContainsKey(downloads_, info->download_id.local())) {
447 // Resuming an existing download.
448 download = downloads_[info->download_id.local()];
449 DCHECK(download->IsInterrupted());
450 } else {
451 // New download
452 net::BoundNetLog bound_net_log =
453 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
454 download = item_factory_->CreateActiveItem(this, *info, bound_net_log);
455 downloads_[download->GetId()] = download;
456 }
457
432 return download; 458 return download;
433 } 459 }
434 460
435 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem( 461 DownloadItemImpl* DownloadManagerImpl::CreateSavePackageDownloadItem(
436 const FilePath& main_file_path, 462 const FilePath& main_file_path,
437 const GURL& page_url, 463 const GURL& page_url,
438 const std::string& mime_type, 464 const std::string& mime_type,
439 DownloadItem::Observer* observer) { 465 DownloadItem::Observer* observer) {
440 net::BoundNetLog bound_net_log = 466 net::BoundNetLog bound_net_log =
441 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD); 467 net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD);
(...skipping 17 matching lines...) Expand all
459 return download_item; 485 return download_item;
460 } 486 }
461 487
462 void DownloadManagerImpl::CancelDownload(int32 download_id) { 488 void DownloadManagerImpl::CancelDownload(int32 download_id) {
463 DownloadItem* download = GetDownload(download_id); 489 DownloadItem* download = GetDownload(download_id);
464 if (!download || !download->IsInProgress()) 490 if (!download || !download->IsInProgress())
465 return; 491 return;
466 download->Cancel(true); 492 download->Cancel(true);
467 } 493 }
468 494
495 // Resume a download of a specific URL. We send the request to the
496 // ResourceDispatcherHost, and let it send us responses like a regular
497 // download.
498 void DownloadManagerImpl::ResumeInterruptedDownload(
499 scoped_ptr<content::DownloadUrlParameters> params,
500 content::DownloadId id) {
501 BrowserThread::PostTask(
502 BrowserThread::IO,
503 FROM_HERE,
504 base::Bind(&BeginDownload, base::Passed(params.Pass()), id));
505 }
506
469 void DownloadManagerImpl::SetDownloadItemFactoryForTesting( 507 void DownloadManagerImpl::SetDownloadItemFactoryForTesting(
470 scoped_ptr<DownloadItemFactory> item_factory) { 508 scoped_ptr<DownloadItemFactory> item_factory) {
471 item_factory_ = item_factory.Pass(); 509 item_factory_ = item_factory.Pass();
472 } 510 }
473 511
474 void DownloadManagerImpl::SetDownloadFileFactoryForTesting( 512 void DownloadManagerImpl::SetDownloadFileFactoryForTesting(
475 scoped_ptr<DownloadFileFactory> file_factory) { 513 scoped_ptr<DownloadFileFactory> file_factory) {
476 file_factory_ = file_factory.Pass(); 514 file_factory_ = file_factory.Pass();
477 } 515 }
478 516
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 } 576 }
539 577
540 void DownloadManagerImpl::DownloadUrl( 578 void DownloadManagerImpl::DownloadUrl(
541 scoped_ptr<DownloadUrlParameters> params) { 579 scoped_ptr<DownloadUrlParameters> params) {
542 if (params->post_id() >= 0) { 580 if (params->post_id() >= 0) {
543 // Check this here so that the traceback is more useful. 581 // Check this here so that the traceback is more useful.
544 DCHECK(params->prefer_cache()); 582 DCHECK(params->prefer_cache());
545 DCHECK(params->method() == "POST"); 583 DCHECK(params->method() == "POST");
546 } 584 }
547 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( 585 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
548 &BeginDownload, base::Passed(&params))); 586 &BeginDownload, base::Passed(&params), DownloadId()));
549 } 587 }
550 588
551 void DownloadManagerImpl::AddObserver(Observer* observer) { 589 void DownloadManagerImpl::AddObserver(Observer* observer) {
552 observers_.AddObserver(observer); 590 observers_.AddObserver(observer);
553 } 591 }
554 592
555 void DownloadManagerImpl::RemoveObserver(Observer* observer) { 593 void DownloadManagerImpl::RemoveObserver(Observer* observer) {
556 observers_.RemoveObserver(observer); 594 observers_.RemoveObserver(observer);
557 } 595 }
558 596
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
628 it != downloads_.end(); ++it) { 666 it != downloads_.end(); ++it) {
629 DownloadItemImpl* item = it->second; 667 DownloadItemImpl* item = it->second;
630 if (item->IsComplete() && 668 if (item->IsComplete() &&
631 !item->GetOpened()) 669 !item->GetOpened())
632 ++num_unopened; 670 ++num_unopened;
633 } 671 }
634 RecordOpensOutstanding(num_unopened); 672 RecordOpensOutstanding(num_unopened);
635 } 673 }
636 674
637 } // namespace content 675 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698