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

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

Issue 10799005: Replace the DownloadFileManager with direct ownership (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed Windows compile error. Created 8 years, 4 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_item_impl.h" 5 #include "content/browser/download/download_item_impl.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/format_macros.h" 12 #include "base/format_macros.h"
13 #include "base/i18n/case_conversion.h" 13 #include "base/i18n/case_conversion.h"
14 #include "base/i18n/string_search.h" 14 #include "base/i18n/string_search.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/metrics/histogram.h" 16 #include "base/metrics/histogram.h"
17 #include "base/stl_util.h" 17 #include "base/stl_util.h"
18 #include "base/stringprintf.h" 18 #include "base/stringprintf.h"
19 #include "base/utf_string_conversions.h" 19 #include "base/utf_string_conversions.h"
20 #include "content/browser/download/download_create_info.h" 20 #include "content/browser/download/download_create_info.h"
21 #include "content/browser/download/download_file.h" 21 #include "content/browser/download/download_file.h"
22 #include "content/browser/download/download_file_manager.h"
23 #include "content/browser/download/download_interrupt_reasons_impl.h" 22 #include "content/browser/download/download_interrupt_reasons_impl.h"
24 #include "content/browser/download/download_item_impl_delegate.h" 23 #include "content/browser/download/download_item_impl_delegate.h"
25 #include "content/browser/download/download_request_handle.h" 24 #include "content/browser/download/download_request_handle.h"
26 #include "content/browser/download/download_stats.h" 25 #include "content/browser/download/download_stats.h"
27 #include "content/browser/web_contents/web_contents_impl.h" 26 #include "content/browser/web_contents/web_contents_impl.h"
28 #include "content/public/browser/browser_thread.h" 27 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/content_browser_client.h" 28 #include "content/public/browser/content_browser_client.h"
30 #include "content/public/browser/download_persistent_store_info.h" 29 #include "content/public/browser/download_persistent_store_info.h"
31 #include "net/base/net_util.h" 30 #include "net/base/net_util.h"
32 31
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 return NULL; 111 return NULL;
113 } 112 }
114 virtual void PauseRequest() const OVERRIDE {} 113 virtual void PauseRequest() const OVERRIDE {}
115 virtual void ResumeRequest() const OVERRIDE {} 114 virtual void ResumeRequest() const OVERRIDE {}
116 virtual void CancelRequest() const OVERRIDE {} 115 virtual void CancelRequest() const OVERRIDE {}
117 virtual std::string DebugString() const OVERRIDE { 116 virtual std::string DebugString() const OVERRIDE {
118 return "Null DownloadRequestHandle"; 117 return "Null DownloadRequestHandle";
119 } 118 }
120 }; 119 };
121 120
121 // Detach the specified download file, then invoke the callback on the
122 // UI thread. Note that this will also delete the DownloadFile object,
123 // as the function accepts ownership and does not transfer it on.
124 //
125 // This is effectively a "PostTaskAndReply" targeted at
126 // download_file->Detach(), with the difference that the destruction of the
127 // task arguments is done on the target thread rather than the originating
128 // thread. If |ui_callback| wasn't needed, we could have just used
129 // PostTask transferring ownership of download_file, and if download_file
130 // FILE thread destruction wasn't needed, we could have used PostTaskAndReply.
131 static void ReleaseDownloadFile(scoped_ptr<DownloadFile> download_file,
132 const base::Closure& ui_callback) {
133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
134 download_file->Detach();
135
136 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, ui_callback);
137 }
138
122 } // namespace 139 } // namespace
123 140
124 namespace content { 141 namespace content {
125 142
126 // Our download table ID starts at 1, so we use 0 to represent a download that 143 // Our download table ID starts at 1, so we use 0 to represent a download that
127 // has started, but has not yet had its data persisted in the table. We use fake 144 // has started, but has not yet had its data persisted in the table. We use fake
128 // database handles in incognito mode starting at -1 and progressively getting 145 // database handles in incognito mode starting at -1 and progressively getting
129 // more negative. 146 // more negative.
130 // static 147 // static
131 const int DownloadItem::kUninitializedHandle = 0; 148 const int DownloadItem::kUninitializedHandle = 0;
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 delegate_delayed_complete_(false), 307 delegate_delayed_complete_(false),
291 bound_net_log_(bound_net_log), 308 bound_net_log_(bound_net_log),
292 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { 309 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
293 delegate_->Attach(); 310 delegate_->Attach();
294 Init(true /* actively downloading */, 311 Init(true /* actively downloading */,
295 download_net_logs::SRC_SAVE_PAGE_AS); 312 download_net_logs::SRC_SAVE_PAGE_AS);
296 } 313 }
297 314
298 DownloadItemImpl::~DownloadItemImpl() { 315 DownloadItemImpl::~DownloadItemImpl() {
299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
317
318 // Should always have been nuked before now, at worst in
319 // DownloadManager shutdown.
320 DCHECK(!download_file_.get());
321
300 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadDestroyed(this)); 322 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadDestroyed(this));
301 STLDeleteContainerPairSecondPointers( 323 STLDeleteContainerPairSecondPointers(
302 external_data_map_.begin(), external_data_map_.end()); 324 external_data_map_.begin(), external_data_map_.end());
303 delegate_->AssertStateConsistent(this); 325 delegate_->AssertStateConsistent(this);
304 delegate_->Detach(); 326 delegate_->Detach();
305 } 327 }
306 328
329 base::WeakPtr<content::DownloadDestinationObserver>
330 DownloadItemImpl::DestinationObserverAsWeakPtr() {
331 // Return does private downcast.
332 return weak_ptr_factory_.GetWeakPtr();
333 }
334
307 void DownloadItemImpl::AddObserver(Observer* observer) { 335 void DownloadItemImpl::AddObserver(Observer* observer) {
308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
309 337
310 observers_.AddObserver(observer); 338 observers_.AddObserver(observer);
311 } 339 }
312 340
313 void DownloadItemImpl::RemoveObserver(Observer* observer) { 341 void DownloadItemImpl::RemoveObserver(Observer* observer) {
314 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
315 343
316 observers_.RemoveObserver(observer); 344 observers_.RemoveObserver(observer);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 bound_net_log_.AddEvent( 413 bound_net_log_.AddEvent(
386 net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED, 414 net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED,
387 base::Bind(&download_net_logs::ItemCheckedCallback, 415 base::Bind(&download_net_logs::ItemCheckedCallback,
388 GetDangerType(), GetSafetyState())); 416 GetDangerType(), GetSafetyState()));
389 417
390 UpdateObservers(); 418 UpdateObservers();
391 419
392 delegate_->MaybeCompleteDownload(this); 420 delegate_->MaybeCompleteDownload(this);
393 } 421 }
394 422
395 void DownloadItemImpl::ProgressComplete(int64 bytes_so_far,
396 const std::string& final_hash) {
397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
398
399 hash_ = final_hash;
400 hash_state_ = "";
401
402 received_bytes_ = bytes_so_far;
403
404 // If we've received more data than we were expecting (bad server info?),
405 // revert to 'unknown size mode'.
406 if (received_bytes_ > total_bytes_)
407 total_bytes_ = 0;
408 }
409
410 // Updates from the download thread may have been posted while this download 423 // Updates from the download thread may have been posted while this download
411 // was being cancelled in the UI thread, so we'll accept them unless we're 424 // was being cancelled in the UI thread, so we'll accept them unless we're
412 // complete. 425 // complete.
413 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, 426 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far,
414 int64 bytes_per_sec, 427 int64 bytes_per_sec,
415 const std::string& hash_state) { 428 const std::string& hash_state) {
416 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
417 430
418 if (!IsInProgress()) { 431 if (!IsInProgress()) {
419 // Ignore if we're no longer in-progress. This can happen if we race a 432 // Ignore if we're no longer in-progress. This can happen if we race a
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 469 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
457 if (!IsPartialDownload()) { 470 if (!IsPartialDownload()) {
458 // Small downloads might be complete before this method has 471 // Small downloads might be complete before this method has
459 // a chance to run. 472 // a chance to run.
460 return; 473 return;
461 } 474 }
462 475
463 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT); 476 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT);
464 477
465 TransitionTo(CANCELLED); 478 TransitionTo(CANCELLED);
479
480 // Cancel and remove the download file.
481 DCHECK(download_file_.get());
482 BrowserThread::PostTask(
483 BrowserThread::FILE, FROM_HERE,
484 // Will be deleted at end of task execution.
485 base::Bind(&DownloadFile::Cancel, base::Owned(download_file_.release())));
486
487 // Cancel the originating URL request.
488 request_handle_->CancelRequest();
489
466 if (user_cancel) 490 if (user_cancel)
467 delegate_->DownloadStopped(this); 491 delegate_->DownloadStopped(this);
468 } 492 }
469 493
494 // We're starting the download.
495 void DownloadItemImpl::Start(scoped_ptr<content::DownloadFile> download_file) {
496 DCHECK(!download_file_.get());
497 download_file_ = download_file.Pass();
498
499 BrowserThread::PostTask(
500 BrowserThread::FILE, FROM_HERE,
501 base::Bind(&DownloadFile::Initialize,
502 // Safe because we control download file lifetime.
503 base::Unretained(download_file_.get()),
504 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
505 weak_ptr_factory_.GetWeakPtr())));
506 }
507
470 // An error occurred somewhere. 508 // An error occurred somewhere.
471 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) { 509 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) {
472 // Somewhat counter-intuitively, it is possible for us to receive an 510 // Somewhat counter-intuitively, it is possible for us to receive an
473 // interrupt after we've already been interrupted. The generation of 511 // interrupt after we've already been interrupted. The generation of
474 // interrupts from the file thread Renames and the generation of 512 // interrupts from the file thread Renames and the generation of
475 // interrupts from disk writes go through two different mechanisms (driven 513 // interrupts from disk writes go through two different mechanisms (driven
476 // by rename requests from UI thread and by write requests from IO thread, 514 // by rename requests from UI thread and by write requests from IO thread,
477 // respectively), and since we choose not to keep state on the File thread, 515 // respectively), and since we choose not to keep state on the File thread,
478 // this is the place where the races collide. It's also possible for 516 // this is the place where the races collide. It's also possible for
479 // interrupts to race with cancels. 517 // interrupts to race with cancels.
480 518
481 // Whatever happens, the first one to hit the UI thread wins. 519 // Whatever happens, the first one to hit the UI thread wins.
482 if (!IsInProgress()) 520 if (!IsInProgress())
483 return; 521 return;
484 522
485 last_reason_ = reason; 523 last_reason_ = reason;
486 TransitionTo(INTERRUPTED); 524 TransitionTo(INTERRUPTED);
525
526 // Cancel and remove the download file.
527 DCHECK(download_file_.get());
528 BrowserThread::PostTask(
529 BrowserThread::FILE, FROM_HERE,
530 // Will be deleted at end of task execution.
531 base::Bind(&DownloadFile::Cancel, base::Owned(download_file_.release())));
532
533 // Cancel the originating URL request.
534 request_handle_->CancelRequest();
535
487 download_stats::RecordDownloadInterrupted( 536 download_stats::RecordDownloadInterrupted(
488 reason, received_bytes_, total_bytes_); 537 reason, received_bytes_, total_bytes_);
489 delegate_->DownloadStopped(this); 538 delegate_->DownloadStopped(this);
490 } 539 }
491 540
492 void DownloadItemImpl::MarkAsComplete() { 541 void DownloadItemImpl::MarkAsComplete() {
493 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 542 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
494 543
495 DCHECK(all_data_saved_); 544 DCHECK(all_data_saved_);
496 end_time_ = base::Time::Now(); 545 end_time_ = base::Time::Now();
497 TransitionTo(COMPLETE); 546 TransitionTo(COMPLETE);
498 } 547 }
499 548
500 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { 549 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) {
501 auto_opened_ = auto_opened; 550 auto_opened_ = auto_opened;
502 Completed(); 551 Completed();
503 } 552 }
504 553
505 void DownloadItemImpl::OnAllDataSaved( 554 void DownloadItemImpl::OnAllDataSaved(
506 int64 size, const std::string& final_hash) { 555 const std::string& final_hash) {
507 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 556 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
508 557
558 DCHECK_EQ(IN_PROGRESS, state_);
509 DCHECK(!all_data_saved_); 559 DCHECK(!all_data_saved_);
510 all_data_saved_ = true; 560 all_data_saved_ = true;
511 ProgressComplete(size, final_hash); 561
562 // Store final hash and null out intermediate serialized hash state.
563 hash_ = final_hash;
564 hash_state_ = "";
565
512 UpdateObservers(); 566 UpdateObservers();
513 } 567 }
514 568
515 void DownloadItemImpl::OnDownloadedFileRemoved() { 569 void DownloadItemImpl::OnDownloadedFileRemoved() {
516 file_externally_removed_ = true; 570 file_externally_removed_ = true;
517 UpdateObservers(); 571 UpdateObservers();
518 } 572 }
519 573
520 void DownloadItemImpl::MaybeCompleteDownload() { 574 void DownloadItemImpl::MaybeCompleteDownload() {
521 // TODO(rdsmith): Move logic for this function here. 575 // TODO(rdsmith): Move logic for this function here.
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 request_handle_->ResumeRequest(); 750 request_handle_->ResumeRequest();
697 else 751 else
698 request_handle_->PauseRequest(); 752 request_handle_->PauseRequest();
699 is_paused_ = !is_paused_; 753 is_paused_ = !is_paused_;
700 UpdateObservers(); 754 UpdateObservers();
701 } 755 }
702 756
703 void DownloadItemImpl::OnDownloadCompleting() { 757 void DownloadItemImpl::OnDownloadCompleting() {
704 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 758 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
705 759
760 if (!IsInProgress())
761 return;
762
706 VLOG(20) << __FUNCTION__ << "()" 763 VLOG(20) << __FUNCTION__ << "()"
707 << " needs rename = " << NeedsRename() 764 << " needs rename = " << NeedsRename()
708 << " " << DebugString(true); 765 << " " << DebugString(true);
709 DCHECK(!GetTargetName().empty()); 766 DCHECK(!GetTargetName().empty());
710 DCHECK_NE(DANGEROUS, GetSafetyState()); 767 DCHECK_NE(DANGEROUS, GetSafetyState());
711 768
769 DCHECK(download_file_.get());
712 if (NeedsRename()) { 770 if (NeedsRename()) {
713 DownloadFileManager::RenameCompletionCallback callback = 771 content::DownloadFile::RenameCompletionCallback callback =
714 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, 772 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
715 weak_ptr_factory_.GetWeakPtr()); 773 weak_ptr_factory_.GetWeakPtr());
716 BrowserThread::PostTask( 774 BrowserThread::PostTask(
717 BrowserThread::FILE, FROM_HERE, 775 BrowserThread::FILE, FROM_HERE,
718 base::Bind(&DownloadFileManager::RenameDownloadFile, 776 base::Bind(&DownloadFile::Rename,
719 delegate_->GetDownloadFileManager(), GetGlobalId(), 777 base::Unretained(download_file_.get()),
720 GetTargetFilePath(), true, callback)); 778 GetTargetFilePath(), true, callback));
721 } else { 779 } else {
722 // Complete the download and release the DownloadFile. 780 // Complete the download and release the DownloadFile.
723 BrowserThread::PostTask( 781 BrowserThread::PostTask(
724 BrowserThread::FILE, FROM_HERE, 782 BrowserThread::FILE, FROM_HERE,
725 base::Bind(&DownloadFileManager::CompleteDownload, 783 base::Bind(&ReleaseDownloadFile, base::Passed(download_file_.Pass()),
726 delegate_->GetDownloadFileManager(), GetGlobalId(),
727 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, 784 base::Bind(&DownloadItemImpl::OnDownloadFileReleased,
728 weak_ptr_factory_.GetWeakPtr()))); 785 weak_ptr_factory_.GetWeakPtr())));
729 } 786 }
730 } 787 }
731 788
732 void DownloadItemImpl::OnDownloadRenamedToFinalName( 789 void DownloadItemImpl::OnDownloadRenamedToFinalName(
733 content::DownloadInterruptReason reason, 790 content::DownloadInterruptReason reason,
734 const FilePath& full_path) { 791 const FilePath& full_path) {
735 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 792 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
736 793
794 if (!IsInProgress())
795 return;
796
737 VLOG(20) << __FUNCTION__ << "()" 797 VLOG(20) << __FUNCTION__ << "()"
738 << " full_path = \"" << full_path.value() << "\"" 798 << " full_path = \"" << full_path.value() << "\""
739 << " needed rename = " << NeedsRename() 799 << " needed rename = " << NeedsRename()
740 << " " << DebugString(false); 800 << " " << DebugString(false);
741 DCHECK(NeedsRename()); 801 DCHECK(NeedsRename());
742 802
743 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 803 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
744 Interrupt(reason); 804 Interrupt(reason);
745 return; 805 return;
746 } 806 }
747 807
748 // full_path is now the current and target file path. 808 // full_path is now the current and target file path.
749 DCHECK(!full_path.empty()); 809 DCHECK(!full_path.empty());
750 target_path_ = full_path; 810 target_path_ = full_path;
751 SetFullPath(full_path); 811 SetFullPath(full_path);
752 delegate_->DownloadRenamedToFinalName(this); 812 delegate_->DownloadRenamedToFinalName(this);
753 813
754 // Complete the download and release the DownloadFile. 814 // Complete the download and release the DownloadFile.
815 // TODO(rdsmith): Unify this path with the !NeedsRename() path in
816 // OnDownloadCompleting above. This can happen easily after history
817 // is made into an observer and the path accessors are cleaned up;
818 // that should allow OnDownloadCompleting to simply call
819 // OnDownloadRenamedToFinalName directly.
820 DCHECK(download_file_.get());
755 BrowserThread::PostTask( 821 BrowserThread::PostTask(
756 BrowserThread::FILE, FROM_HERE, 822 BrowserThread::FILE, FROM_HERE,
757 base::Bind(&DownloadFileManager::CompleteDownload, 823 base::Bind(&ReleaseDownloadFile, base::Passed(download_file_.Pass()),
758 delegate_->GetDownloadFileManager(), GetGlobalId(),
759 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, 824 base::Bind(&DownloadItemImpl::OnDownloadFileReleased,
760 weak_ptr_factory_.GetWeakPtr()))); 825 weak_ptr_factory_.GetWeakPtr())));
761 } 826 }
762 827
828 void DownloadItemImpl::OnDownloadFileInitialized(
829 content::DownloadInterruptReason result) {
830 if (result != content::DOWNLOAD_INTERRUPT_REASON_NONE) {
831 Interrupt(result);
832 // TODO(rdsmith): It makes no sense to continue along the
833 // regular download path after we've gotten an error. But it's
834 // the way the code has historically worked, and this allows us
835 // to get the download persisted and observers of the download manager
836 // notified, so tests work. When we execute all side effects of cancel
837 // (including queue removal) immedately rather than waiting for
838 // persistence we should replace this comment with a "return;".
839 }
840
841 delegate_->DelegateStart(this);
842 }
843
763 void DownloadItemImpl::OnDownloadFileReleased() { 844 void DownloadItemImpl::OnDownloadFileReleased() {
764 if (delegate_->ShouldOpenDownload(this)) 845 if (delegate_->ShouldOpenDownload(this))
765 Completed(); 846 Completed();
766 else 847 else
767 delegate_delayed_complete_ = true; 848 delegate_delayed_complete_ = true;
768 } 849 }
769 850
770 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( 851 void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
771 content::DownloadInterruptReason reason, 852 content::DownloadInterruptReason reason,
772 const FilePath& full_path) { 853 const FilePath& full_path) {
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 target_path_ = target_path; 962 target_path_ = target_path;
882 target_disposition_ = disposition; 963 target_disposition_ = disposition;
883 SetDangerType(danger_type); 964 SetDangerType(danger_type);
884 // TODO(asanka): SetDangerType() doesn't need to send a notification here. 965 // TODO(asanka): SetDangerType() doesn't need to send a notification here.
885 966
886 // We want the intermediate and target paths to refer to the same directory so 967 // We want the intermediate and target paths to refer to the same directory so
887 // that they are both on the same device and subject to same 968 // that they are both on the same device and subject to same
888 // space/permission/availability constraints. 969 // space/permission/availability constraints.
889 DCHECK(intermediate_path.DirName() == target_path.DirName()); 970 DCHECK(intermediate_path.DirName() == target_path.DirName());
890 971
972 if (!IsInProgress()) {
973 // If we've been cancelled or interrupted while the target was being
974 // determined, continue the cascade with a null name.
975 // The error doesn't matter as the cause of download stoppaged
976 // will already have been recorded.
977 OnDownloadRenamedToIntermediateName(
978 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, FilePath());
979 return;
980 }
981
891 // Rename to intermediate name. 982 // Rename to intermediate name.
892 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a 983 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a
893 // spurious rename when we can just rename to the final 984 // spurious rename when we can just rename to the final
894 // filename. Unnecessary renames may cause bugs like 985 // filename. Unnecessary renames may cause bugs like
895 // http://crbug.com/74187. 986 // http://crbug.com/74187.
896 DownloadFileManager::RenameCompletionCallback callback = 987 DCHECK(download_file_.get());
988 DownloadFile::RenameCompletionCallback callback =
897 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, 989 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName,
898 weak_ptr_factory_.GetWeakPtr()); 990 weak_ptr_factory_.GetWeakPtr());
899 BrowserThread::PostTask( 991 BrowserThread::PostTask(
900 BrowserThread::FILE, FROM_HERE, 992 BrowserThread::FILE, FROM_HERE,
901 base::Bind(&DownloadFileManager::RenameDownloadFile, 993 base::Bind(&DownloadFile::Rename,
902 delegate_->GetDownloadFileManager(), GetGlobalId(), 994 // Safe because we control download file lifetime.
995 base::Unretained(download_file_.get()),
903 intermediate_path, false, callback)); 996 intermediate_path, false, callback));
904 } 997 }
905 998
906 void DownloadItemImpl::OnContentCheckCompleted( 999 void DownloadItemImpl::OnContentCheckCompleted(
907 content::DownloadDangerType danger_type) { 1000 content::DownloadDangerType danger_type) {
908 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1001 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
909 DCHECK(AllDataSaved()); 1002 DCHECK(AllDataSaved());
910 SetDangerType(danger_type); 1003 SetDangerType(danger_type);
911 UpdateObservers(); 1004 UpdateObservers();
912 } 1005 }
(...skipping 10 matching lines...) Expand all
923 1016
924 void DownloadItemImpl::SetDisplayName(const FilePath& name) { 1017 void DownloadItemImpl::SetDisplayName(const FilePath& name) {
925 display_name_ = name; 1018 display_name_ = name;
926 } 1019 }
927 1020
928 FilePath DownloadItemImpl::GetUserVerifiedFilePath() const { 1021 FilePath DownloadItemImpl::GetUserVerifiedFilePath() const {
929 return (safety_state_ == DownloadItem::SAFE) ? 1022 return (safety_state_ == DownloadItem::SAFE) ?
930 GetTargetFilePath() : GetFullPath(); 1023 GetTargetFilePath() : GetFullPath();
931 } 1024 }
932 1025
933 void DownloadItemImpl::OffThreadCancel() { 1026 void DownloadItemImpl::DestinationUpdate(int64 bytes_so_far,
1027 int64 bytes_per_sec,
1028 const std::string& hash_state) {
934 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1029 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
935 request_handle_->CancelRequest();
936 1030
937 BrowserThread::PostTask( 1031 if (!IsInProgress()) {
938 BrowserThread::FILE, FROM_HERE, 1032 // Ignore if we're no longer in-progress. This can happen if we race a
939 base::Bind(&DownloadFileManager::CancelDownload, 1033 // Cancel on the UI thread with an update on the FILE thread.
940 delegate_->GetDownloadFileManager(), download_id_)); 1034 //
1035 // TODO(rdsmith): Arguably we should let this go through, as this means
1036 // the download really did get further than we know before it was
1037 // cancelled. But the gain isn't very large, and the code is more
1038 // fragile if it has to support in progress updates in a non-in-progress
1039 // state. This issue should be readdressed when we revamp performance
1040 // reporting.
1041 return;
1042 }
1043 bytes_per_sec_ = bytes_per_sec;
1044 hash_state_ = hash_state;
1045 received_bytes_ = bytes_so_far;
1046
1047 // If we've received more data than we were expecting (bad server info?),
1048 // revert to 'unknown size mode'.
1049 if (received_bytes_ > total_bytes_)
1050 total_bytes_ = 0;
1051
1052 if (bound_net_log_.IsLoggingAllEvents()) {
1053 bound_net_log_.AddEvent(
1054 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED,
1055 net::NetLog::Int64Callback("bytes_so_far", received_bytes_));
1056 }
1057
1058 UpdateObservers();
1059 }
1060
1061 void DownloadItemImpl::DestinationError(
1062 content::DownloadInterruptReason reason) {
1063 // The DestinationError and Interrupt routines are being kept separate
1064 // to allow for a future merging of the Cancel and Interrupt routines..
1065 Interrupt(reason);
1066 }
1067
1068 void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) {
1069 if (!IsInProgress())
1070 return;
1071 OnAllDataSaved(final_hash);
1072 delegate_->MaybeCompleteDownload(this);
941 } 1073 }
942 1074
943 void DownloadItemImpl::Init(bool active, 1075 void DownloadItemImpl::Init(bool active,
944 download_net_logs::DownloadType download_type) { 1076 download_net_logs::DownloadType download_type) {
945 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1077 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
946 1078
947 if (active) 1079 if (active)
948 download_stats::RecordDownloadCount(download_stats::START_COUNT); 1080 download_stats::RecordDownloadCount(download_stats::START_COUNT);
949 1081
950 if (target_path_.empty()) 1082 if (target_path_.empty())
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 " total = %" PRId64 1173 " total = %" PRId64
1042 " received = %" PRId64 1174 " received = %" PRId64
1043 " reason = %s" 1175 " reason = %s"
1044 " paused = %c" 1176 " paused = %c"
1045 " otr = %c" 1177 " otr = %c"
1046 " safety = %s" 1178 " safety = %s"
1047 " last_modified = '%s'" 1179 " last_modified = '%s'"
1048 " etag = '%s'" 1180 " etag = '%s'"
1049 " url_chain = \n\t\"%s\"\n\t" 1181 " url_chain = \n\t\"%s\"\n\t"
1050 " full_path = \"%" PRFilePath "\"" 1182 " full_path = \"%" PRFilePath "\""
1051 " target_path = \"%" PRFilePath "\"", 1183 " target_path = \"%" PRFilePath "\""
1184 " has download file = %s",
1052 GetDbHandle(), 1185 GetDbHandle(),
1053 GetTotalBytes(), 1186 GetTotalBytes(),
1054 GetReceivedBytes(), 1187 GetReceivedBytes(),
1055 InterruptReasonDebugString(last_reason_).c_str(), 1188 InterruptReasonDebugString(last_reason_).c_str(),
1056 IsPaused() ? 'T' : 'F', 1189 IsPaused() ? 'T' : 'F',
1057 IsOtr() ? 'T' : 'F', 1190 IsOtr() ? 'T' : 'F',
1058 DebugSafetyStateString(GetSafetyState()), 1191 DebugSafetyStateString(GetSafetyState()),
1059 GetLastModifiedTime().c_str(), 1192 GetLastModifiedTime().c_str(),
1060 GetETag().c_str(), 1193 GetETag().c_str(),
1061 url_list.c_str(), 1194 url_list.c_str(),
1062 GetFullPath().value().c_str(), 1195 GetFullPath().value().c_str(),
1063 GetTargetFilePath().value().c_str()); 1196 GetTargetFilePath().value().c_str(),
1197 download_file_.get() ? "true" : "false");
1064 } else { 1198 } else {
1065 description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); 1199 description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
1066 } 1200 }
1067 1201
1068 description += " }"; 1202 description += " }";
1069 1203
1070 return description; 1204 return description;
1071 } 1205 }
1072 1206
1073 bool DownloadItemImpl::AllDataSaved() const { return all_data_saved_; } 1207 bool DownloadItemImpl::AllDataSaved() const { return all_data_saved_; }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1192 std::map<const void*, ExternalData*>::iterator it = 1326 std::map<const void*, ExternalData*>::iterator it =
1193 external_data_map_.find(key); 1327 external_data_map_.find(key);
1194 1328
1195 if (it == external_data_map_.end()) { 1329 if (it == external_data_map_.end()) {
1196 external_data_map_[key] = data; 1330 external_data_map_[key] = data;
1197 } else if (it->second != data) { 1331 } else if (it->second != data) {
1198 delete it->second; 1332 delete it->second;
1199 it->second = data; 1333 it->second = data;
1200 } 1334 }
1201 } 1335 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698