Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 114 return NULL; | 113 return NULL; |
| 115 } | 114 } |
| 116 virtual void PauseRequest() const OVERRIDE {} | 115 virtual void PauseRequest() const OVERRIDE {} |
| 117 virtual void ResumeRequest() const OVERRIDE {} | 116 virtual void ResumeRequest() const OVERRIDE {} |
| 118 virtual void CancelRequest() const OVERRIDE {} | 117 virtual void CancelRequest() const OVERRIDE {} |
| 119 virtual std::string DebugString() const OVERRIDE { | 118 virtual std::string DebugString() const OVERRIDE { |
| 120 return "Null DownloadRequestHandle"; | 119 return "Null DownloadRequestHandle"; |
| 121 } | 120 } |
| 122 }; | 121 }; |
| 123 | 122 |
| 123 // Detach the specified download file, then invoke the callback on the | |
| 124 // UI thread. Note that this will also delete the DownloadFile object, | |
| 125 // as the function accepts ownership and does not transfer it on. | |
| 126 static void ReleaseDownloadFile(scoped_ptr<DownloadFile> download_file, | |
| 127 const base::Closure& ui_callback) { | |
| 128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
| 129 download_file->Detach(); | |
| 130 | |
| 131 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, ui_callback); | |
| 132 } | |
| 133 | |
| 124 } // namespace | 134 } // namespace |
| 125 | 135 |
| 126 namespace content { | 136 namespace content { |
| 127 | 137 |
| 128 // Our download table ID starts at 1, so we use 0 to represent a download that | 138 // Our download table ID starts at 1, so we use 0 to represent a download that |
| 129 // has started, but has not yet had its data persisted in the table. We use fake | 139 // has started, but has not yet had its data persisted in the table. We use fake |
| 130 // database handles in incognito mode starting at -1 and progressively getting | 140 // database handles in incognito mode starting at -1 and progressively getting |
| 131 // more negative. | 141 // more negative. |
| 132 // static | 142 // static |
| 133 const int DownloadItem::kUninitializedHandle = 0; | 143 const int DownloadItem::kUninitializedHandle = 0; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 bound_net_log_(bound_net_log), | 303 bound_net_log_(bound_net_log), |
| 294 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 304 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
| 295 delegate_->Attach(); | 305 delegate_->Attach(); |
| 296 Init(true /* actively downloading */, | 306 Init(true /* actively downloading */, |
| 297 download_net_logs::SRC_SAVE_PAGE_AS); | 307 download_net_logs::SRC_SAVE_PAGE_AS); |
| 298 } | 308 } |
| 299 | 309 |
| 300 DownloadItemImpl::~DownloadItemImpl() { | 310 DownloadItemImpl::~DownloadItemImpl() { |
| 301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 302 | 312 |
| 313 // Should always have been nuked before now, at worst in | |
| 314 // DownloadManager shutdown. | |
| 315 DCHECK(!download_file_.get()); | |
| 316 | |
| 303 TransitionTo(REMOVING); | 317 TransitionTo(REMOVING); |
| 304 STLDeleteContainerPairSecondPointers( | 318 STLDeleteContainerPairSecondPointers( |
| 305 external_data_map_.begin(), external_data_map_.end()); | 319 external_data_map_.begin(), external_data_map_.end()); |
| 306 delegate_->AssertStateConsistent(this); | 320 delegate_->AssertStateConsistent(this); |
| 307 delegate_->Detach(); | 321 delegate_->Detach(); |
| 308 } | 322 } |
| 309 | 323 |
| 324 base::WeakPtr<content::DownloadDestinationController> | |
| 325 DownloadItemImpl::DestinationControllerAsWeakPtr() { | |
| 326 // Return does private downcast. | |
| 327 return weak_ptr_factory_.GetWeakPtr(); | |
|
benjhayden
2012/07/25 15:19:16
Why don't you want to use SupportsWeakPtr::AsWeakP
Randy Smith (Not in Mondays)
2012/07/30 01:07:23
A couple of reasons. My usual reason (I don't wan
| |
| 328 } | |
| 329 | |
| 310 void DownloadItemImpl::AddObserver(Observer* observer) { | 330 void DownloadItemImpl::AddObserver(Observer* observer) { |
| 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 331 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 312 | 332 |
| 313 observers_.AddObserver(observer); | 333 observers_.AddObserver(observer); |
| 314 } | 334 } |
| 315 | 335 |
| 316 void DownloadItemImpl::RemoveObserver(Observer* observer) { | 336 void DownloadItemImpl::RemoveObserver(Observer* observer) { |
| 317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 337 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 318 | 338 |
| 319 observers_.RemoveObserver(observer); | 339 observers_.RemoveObserver(observer); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 388 bound_net_log_.AddEvent( | 408 bound_net_log_.AddEvent( |
| 389 net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED, | 409 net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED, |
| 390 base::Bind(&download_net_logs::ItemCheckedCallback, | 410 base::Bind(&download_net_logs::ItemCheckedCallback, |
| 391 GetDangerType(), GetSafetyState())); | 411 GetDangerType(), GetSafetyState())); |
| 392 | 412 |
| 393 UpdateObservers(); | 413 UpdateObservers(); |
| 394 | 414 |
| 395 delegate_->MaybeCompleteDownload(this); | 415 delegate_->MaybeCompleteDownload(this); |
| 396 } | 416 } |
| 397 | 417 |
| 398 void DownloadItemImpl::ProgressComplete(int64 bytes_so_far, | |
| 399 const std::string& final_hash) { | |
| 400 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 401 | |
| 402 hash_ = final_hash; | |
| 403 hash_state_ = ""; | |
| 404 | |
| 405 received_bytes_ = bytes_so_far; | |
| 406 | |
| 407 // If we've received more data than we were expecting (bad server info?), | |
| 408 // revert to 'unknown size mode'. | |
| 409 if (received_bytes_ > total_bytes_) | |
| 410 total_bytes_ = 0; | |
| 411 } | |
| 412 | |
| 413 // Updates from the download thread may have been posted while this download | 418 // Updates from the download thread may have been posted while this download |
| 414 // was being cancelled in the UI thread, so we'll accept them unless we're | 419 // was being cancelled in the UI thread, so we'll accept them unless we're |
| 415 // complete. | 420 // complete. |
| 416 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, | 421 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, |
| 417 int64 bytes_per_sec, | 422 int64 bytes_per_sec, |
| 418 const std::string& hash_state) { | 423 const std::string& hash_state) { |
| 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 420 | 425 |
| 421 if (!IsInProgress()) { | 426 if (!IsInProgress()) { |
| 422 // Ignore if we're no longer in-progress. This can happen if we race a | 427 // Ignore if we're no longer in-progress. This can happen if we race a |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 return; | 468 return; |
| 464 } | 469 } |
| 465 | 470 |
| 466 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT); | 471 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT); |
| 467 | 472 |
| 468 TransitionTo(CANCELLED); | 473 TransitionTo(CANCELLED); |
| 469 if (user_cancel) | 474 if (user_cancel) |
| 470 delegate_->DownloadStopped(this); | 475 delegate_->DownloadStopped(this); |
| 471 } | 476 } |
| 472 | 477 |
| 478 // We're starting the download. | |
| 479 void DownloadItemImpl::Start(scoped_ptr<content::DownloadFile> download_file) { | |
| 480 DCHECK(!download_file_.get()); | |
| 481 download_file_ = download_file.Pass(); | |
| 482 | |
| 483 BrowserThread::PostTask( | |
| 484 BrowserThread::FILE, FROM_HERE, | |
| 485 base::Bind(&DownloadFile::Initialize, | |
| 486 // Safe because we control download file lifetime. | |
|
benjhayden
2012/07/25 15:19:16
Couldn't you use weak pointers to bounce a callbac
Randy Smith (Not in Mondays)
2012/07/30 01:07:23
I assume you mean off of the DownloadFile; I am us
| |
| 487 base::Unretained(download_file_.get()), | |
| 488 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, | |
| 489 weak_ptr_factory_.GetWeakPtr()))); | |
| 490 } | |
| 491 | |
| 473 // An error occurred somewhere. | 492 // An error occurred somewhere. |
| 474 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) { | 493 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) { |
| 475 // Somewhat counter-intuitively, it is possible for us to receive an | 494 // Somewhat counter-intuitively, it is possible for us to receive an |
| 476 // interrupt after we've already been interrupted. The generation of | 495 // interrupt after we've already been interrupted. The generation of |
| 477 // interrupts from the file thread Renames and the generation of | 496 // interrupts from the file thread Renames and the generation of |
| 478 // interrupts from disk writes go through two different mechanisms (driven | 497 // interrupts from disk writes go through two different mechanisms (driven |
| 479 // by rename requests from UI thread and by write requests from IO thread, | 498 // by rename requests from UI thread and by write requests from IO thread, |
| 480 // respectively), and since we choose not to keep state on the File thread, | 499 // respectively), and since we choose not to keep state on the File thread, |
| 481 // this is the place where the races collide. It's also possible for | 500 // this is the place where the races collide. It's also possible for |
| 482 // interrupts to race with cancels. | 501 // interrupts to race with cancels. |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 499 end_time_ = base::Time::Now(); | 518 end_time_ = base::Time::Now(); |
| 500 TransitionTo(COMPLETE); | 519 TransitionTo(COMPLETE); |
| 501 } | 520 } |
| 502 | 521 |
| 503 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { | 522 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { |
| 504 auto_opened_ = auto_opened; | 523 auto_opened_ = auto_opened; |
| 505 Completed(); | 524 Completed(); |
| 506 } | 525 } |
| 507 | 526 |
| 508 void DownloadItemImpl::OnAllDataSaved( | 527 void DownloadItemImpl::OnAllDataSaved( |
| 509 int64 size, const std::string& final_hash) { | 528 const std::string& final_hash) { |
| 510 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 529 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 511 | 530 |
| 512 DCHECK(!all_data_saved_); | 531 DCHECK(!all_data_saved_); |
| 513 all_data_saved_ = true; | 532 all_data_saved_ = true; |
| 514 ProgressComplete(size, final_hash); | 533 |
| 534 // Store final hash and null out intermediate serialized hash state. | |
| 535 hash_ = final_hash; | |
| 536 hash_state_ = ""; | |
| 537 | |
| 515 UpdateObservers(); | 538 UpdateObservers(); |
| 516 } | 539 } |
| 517 | 540 |
| 518 void DownloadItemImpl::OnDownloadedFileRemoved() { | 541 void DownloadItemImpl::OnDownloadedFileRemoved() { |
| 519 file_externally_removed_ = true; | 542 file_externally_removed_ = true; |
| 520 UpdateObservers(); | 543 UpdateObservers(); |
| 521 } | 544 } |
| 522 | 545 |
| 523 void DownloadItemImpl::MaybeCompleteDownload() { | 546 void DownloadItemImpl::MaybeCompleteDownload() { |
| 524 // TODO(rdsmith): Move logic for this function here. | 547 // TODO(rdsmith): Move logic for this function here. |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 693 | 716 |
| 694 DCHECK(IsInProgress()); | 717 DCHECK(IsInProgress()); |
| 695 if (is_paused_) | 718 if (is_paused_) |
| 696 request_handle_->ResumeRequest(); | 719 request_handle_->ResumeRequest(); |
| 697 else | 720 else |
| 698 request_handle_->PauseRequest(); | 721 request_handle_->PauseRequest(); |
| 699 is_paused_ = !is_paused_; | 722 is_paused_ = !is_paused_; |
| 700 UpdateObservers(); | 723 UpdateObservers(); |
| 701 } | 724 } |
| 702 | 725 |
| 703 void DownloadItemImpl::OnDownloadCompleting(DownloadFileManager* file_manager) { | 726 void DownloadItemImpl::OnDownloadCompleting() { |
| 704 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 727 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 705 | 728 |
| 729 // Lost Cancel race. | |
| 730 if (!IsInProgress()) | |
| 731 return; | |
| 732 | |
| 706 VLOG(20) << __FUNCTION__ << "()" | 733 VLOG(20) << __FUNCTION__ << "()" |
| 707 << " needs rename = " << NeedsRename() | 734 << " needs rename = " << NeedsRename() |
| 708 << " " << DebugString(true); | 735 << " " << DebugString(true); |
| 709 DCHECK(!GetTargetName().empty()); | 736 DCHECK(!GetTargetName().empty()); |
| 710 DCHECK_NE(DANGEROUS, GetSafetyState()); | 737 DCHECK_NE(DANGEROUS, GetSafetyState()); |
| 711 DCHECK(file_manager); | |
| 712 | 738 |
| 713 if (NeedsRename()) { | 739 if (NeedsRename()) { |
| 714 DownloadFileManager::RenameCompletionCallback callback = | 740 content::DownloadFile::RenameCompletionCallback callback = |
| 715 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, | 741 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, |
| 716 weak_ptr_factory_.GetWeakPtr(), | 742 weak_ptr_factory_.GetWeakPtr()); |
| 717 base::Unretained(file_manager)); | |
| 718 BrowserThread::PostTask( | 743 BrowserThread::PostTask( |
| 719 BrowserThread::FILE, FROM_HERE, | 744 BrowserThread::FILE, FROM_HERE, |
| 720 base::Bind(&DownloadFileManager::RenameDownloadFile, | 745 base::Bind(&DownloadFile::Rename, |
| 721 file_manager, GetGlobalId(), GetTargetFilePath(), | 746 base::Unretained(download_file_.get()), |
| 722 true, callback)); | 747 GetTargetFilePath(), true, callback)); |
| 723 } else { | 748 } else { |
| 724 // Complete the download and release the DownloadFile. | 749 // Complete the download and release the DownloadFile. |
| 725 BrowserThread::PostTask( | 750 BrowserThread::PostTask( |
| 726 BrowserThread::FILE, FROM_HERE, | 751 BrowserThread::FILE, FROM_HERE, |
| 727 base::Bind(&DownloadFileManager::CompleteDownload, | 752 base::Bind(&ReleaseDownloadFile, base::Passed(download_file_.Pass()), |
| 728 file_manager, GetGlobalId(), | |
| 729 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, | 753 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, |
| 730 weak_ptr_factory_.GetWeakPtr()))); | 754 weak_ptr_factory_.GetWeakPtr()))); |
| 731 } | 755 } |
| 732 } | 756 } |
| 733 | 757 |
| 734 void DownloadItemImpl::OnDownloadRenamedToFinalName( | 758 void DownloadItemImpl::OnDownloadRenamedToFinalName( |
| 735 DownloadFileManager* file_manager, | |
| 736 content::DownloadInterruptReason reason, | 759 content::DownloadInterruptReason reason, |
| 737 const FilePath& full_path) { | 760 const FilePath& full_path) { |
| 738 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 761 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 739 | 762 |
| 763 // Lost Cancel race. | |
| 764 if (!IsInProgress()) | |
| 765 return; | |
| 766 | |
| 740 VLOG(20) << __FUNCTION__ << "()" | 767 VLOG(20) << __FUNCTION__ << "()" |
| 741 << " full_path = \"" << full_path.value() << "\"" | 768 << " full_path = \"" << full_path.value() << "\"" |
| 742 << " needed rename = " << NeedsRename() | 769 << " needed rename = " << NeedsRename() |
| 743 << " " << DebugString(false); | 770 << " " << DebugString(false); |
| 744 DCHECK(NeedsRename()); | 771 DCHECK(NeedsRename()); |
| 745 | 772 |
| 746 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) { | 773 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) { |
| 747 Interrupt(reason); | 774 Interrupt(reason); |
| 748 return; | 775 return; |
| 749 } | 776 } |
| 750 | 777 |
| 751 // full_path is now the current and target file path. | 778 // full_path is now the current and target file path. |
| 752 DCHECK(!full_path.empty()); | 779 DCHECK(!full_path.empty()); |
| 753 target_path_ = full_path; | 780 target_path_ = full_path; |
| 754 SetFullPath(full_path); | 781 SetFullPath(full_path); |
| 755 delegate_->DownloadRenamedToFinalName(this); | 782 delegate_->DownloadRenamedToFinalName(this); |
| 756 | 783 |
| 757 // Complete the download and release the DownloadFile. | 784 // Complete the download and release the DownloadFile. |
| 785 DCHECK(download_file_.get()); | |
| 758 BrowserThread::PostTask( | 786 BrowserThread::PostTask( |
| 759 BrowserThread::FILE, FROM_HERE, | 787 BrowserThread::FILE, FROM_HERE, |
| 760 base::Bind(&DownloadFileManager::CompleteDownload, | 788 base::Bind(&ReleaseDownloadFile, base::Passed(download_file_.Pass()), |
| 761 file_manager, GetGlobalId(), | |
| 762 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, | 789 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, |
| 763 weak_ptr_factory_.GetWeakPtr()))); | 790 weak_ptr_factory_.GetWeakPtr()))); |
| 764 } | 791 } |
| 765 | 792 |
| 793 void DownloadItemImpl::OnDownloadFileInitialized( | |
| 794 content::DownloadInterruptReason result) { | |
| 795 if (result != content::DOWNLOAD_INTERRUPT_REASON_NONE) { | |
| 796 Interrupt(result); | |
| 797 // TODO(rdsmith): It makes no sense to continue along the | |
| 798 // regular download path after we've gotten an error. But it's | |
| 799 // the way the code has historically worked, and this allows us | |
| 800 // to get the download persisted and observers of the download manager | |
| 801 // notified, so tests work. When we execute all side effects of cancel | |
| 802 // (including queue removal) immedately rather than waiting for | |
| 803 // persistence we should replace this comment with a "return;". | |
| 804 } | |
| 805 | |
| 806 delegate_->DelegateStart(this); | |
| 807 } | |
| 808 | |
| 766 void DownloadItemImpl::OnDownloadFileReleased() { | 809 void DownloadItemImpl::OnDownloadFileReleased() { |
| 767 if (delegate_->ShouldOpenDownload(this)) | 810 if (delegate_->ShouldOpenDownload(this)) |
| 768 Completed(); | 811 Completed(); |
| 769 else | 812 else |
| 770 delegate_delayed_complete_ = true; | 813 delegate_delayed_complete_ = true; |
| 771 } | 814 } |
| 772 | 815 |
| 773 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( | 816 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( |
| 774 content::DownloadInterruptReason reason, | 817 content::DownloadInterruptReason reason, |
| 775 const FilePath& full_path) { | 818 const FilePath& full_path) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 886 | 929 |
| 887 void DownloadItemImpl::OnContentCheckCompleted( | 930 void DownloadItemImpl::OnContentCheckCompleted( |
| 888 content::DownloadDangerType danger_type) { | 931 content::DownloadDangerType danger_type) { |
| 889 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved. | 932 // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved. |
| 890 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 933 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 891 DCHECK(AllDataSaved()); | 934 DCHECK(AllDataSaved()); |
| 892 SetDangerType(danger_type); | 935 SetDangerType(danger_type); |
| 893 } | 936 } |
| 894 | 937 |
| 895 void DownloadItemImpl::OnIntermediatePathDetermined( | 938 void DownloadItemImpl::OnIntermediatePathDetermined( |
| 896 DownloadFileManager* file_manager, | |
| 897 const FilePath& intermediate_path) { | 939 const FilePath& intermediate_path) { |
| 898 DownloadFileManager::RenameCompletionCallback callback = | 940 if (!IsInProgress()) { |
| 941 // Lost interrupt/cancel race. We need to continue the cascade | |
| 942 // anyway, so that we get this entry persisted and made visible | |
| 943 // to observers. Actual error code doesn't matter as we've | |
| 944 // already stored the original reason for failure. | |
| 945 // | |
| 946 // TODO(rdsmith): Remove this code when we make downloads visible to | |
| 947 // observers earlier in the cascade so they can see immediate transitions | |
| 948 // to INTERRUPTED. | |
| 949 OnDownloadRenamedToIntermediateName( | |
| 950 content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, FilePath()); | |
| 951 return; | |
| 952 } | |
| 953 | |
| 954 content::DownloadFile::RenameCompletionCallback callback = | |
| 899 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, | 955 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, |
| 900 weak_ptr_factory_.GetWeakPtr()); | 956 weak_ptr_factory_.GetWeakPtr()); |
| 957 | |
| 958 DCHECK(download_file_.get()); | |
| 901 BrowserThread::PostTask( | 959 BrowserThread::PostTask( |
| 902 BrowserThread::FILE, FROM_HERE, | 960 BrowserThread::FILE, FROM_HERE, |
| 903 base::Bind(&DownloadFileManager::RenameDownloadFile, | 961 base::Bind(&DownloadFile::Rename, |
| 904 file_manager, GetGlobalId(), intermediate_path, | 962 base::Unretained(download_file_.get()), |
| 905 false, callback)); | 963 intermediate_path, false, callback)); |
| 906 } | 964 } |
| 907 | 965 |
| 908 const FilePath& DownloadItemImpl::GetFullPath() const { | 966 const FilePath& DownloadItemImpl::GetFullPath() const { |
| 909 return current_path_; | 967 return current_path_; |
| 910 } | 968 } |
| 911 | 969 |
| 912 FilePath DownloadItemImpl::GetFileNameToReportUser() const { | 970 FilePath DownloadItemImpl::GetFileNameToReportUser() const { |
| 913 if (!display_name_.empty()) | 971 if (!display_name_.empty()) |
| 914 return display_name_; | 972 return display_name_; |
| 915 return target_path_.BaseName(); | 973 return target_path_.BaseName(); |
| 916 } | 974 } |
| 917 | 975 |
| 918 void DownloadItemImpl::SetDisplayName(const FilePath& name) { | 976 void DownloadItemImpl::SetDisplayName(const FilePath& name) { |
| 919 display_name_ = name; | 977 display_name_ = name; |
| 920 } | 978 } |
| 921 | 979 |
| 922 FilePath DownloadItemImpl::GetUserVerifiedFilePath() const { | 980 FilePath DownloadItemImpl::GetUserVerifiedFilePath() const { |
| 923 return (safety_state_ == DownloadItem::SAFE) ? | 981 return (safety_state_ == DownloadItem::SAFE) ? |
| 924 GetTargetFilePath() : GetFullPath(); | 982 GetTargetFilePath() : GetFullPath(); |
| 925 } | 983 } |
| 926 | 984 |
| 927 void DownloadItemImpl::OffThreadCancel(DownloadFileManager* file_manager) { | 985 void DownloadItemImpl::OffThreadCancel() { |
| 928 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 986 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 929 request_handle_->CancelRequest(); | 987 request_handle_->CancelRequest(); |
| 930 | 988 |
| 989 DCHECK(download_file_.get()); | |
| 931 BrowserThread::PostTask( | 990 BrowserThread::PostTask( |
| 932 BrowserThread::FILE, FROM_HERE, | 991 BrowserThread::FILE, FROM_HERE, |
| 933 base::Bind(&DownloadFileManager::CancelDownload, | 992 // Will be deleted at end of task execution. |
| 934 file_manager, download_id_)); | 993 base::Bind(&DownloadFile::Cancel, base::Owned(download_file_.release()))); |
| 994 } | |
| 995 | |
| 996 void DownloadItemImpl::DestinationUpdate(int64 bytes_so_far, | |
| 997 int64 bytes_per_sec, | |
| 998 const std::string& hash_state) { | |
| 999 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 1000 | |
| 1001 if (!IsInProgress()) { | |
| 1002 // Ignore if we're no longer in-progress. This can happen if we race a | |
| 1003 // Cancel on the UI thread with an update on the FILE thread. | |
| 1004 // | |
| 1005 // TODO(rdsmith): Arguably we should let this go through, as this means | |
| 1006 // the download really did get further than we know before it was | |
| 1007 // cancelled. But the gain isn't very large, and the code is more | |
| 1008 // fragile if it has to support in progress updates in a non-in-progress | |
| 1009 // state. This issue should be readdressed when we revamp performance | |
| 1010 // reporting. | |
| 1011 return; | |
| 1012 } | |
| 1013 bytes_per_sec_ = bytes_per_sec; | |
| 1014 hash_state_ = hash_state; | |
| 1015 received_bytes_ = bytes_so_far; | |
| 1016 | |
| 1017 // If we've received more data than we were expecting (bad server info?), | |
| 1018 // revert to 'unknown size mode'. | |
| 1019 if (received_bytes_ > total_bytes_) | |
| 1020 total_bytes_ = 0; | |
| 1021 | |
| 1022 if (bound_net_log_.IsLoggingAllEvents()) { | |
| 1023 bound_net_log_.AddEvent( | |
| 1024 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED, | |
| 1025 net::NetLog::Int64Callback("bytes_so_far", received_bytes_)); | |
| 1026 } | |
| 1027 | |
| 1028 UpdateObservers(); | |
| 1029 } | |
| 1030 | |
| 1031 void DownloadItemImpl::DestinationError( | |
| 1032 content::DownloadInterruptReason reason) { | |
| 1033 Interrupt(reason); | |
| 1034 } | |
| 1035 | |
| 1036 void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) { | |
| 1037 if (!IsInProgress()) | |
| 1038 return; | |
| 1039 OnAllDataSaved(final_hash); | |
| 1040 delegate_->MaybeCompleteDownload(this); | |
| 935 } | 1041 } |
| 936 | 1042 |
| 937 void DownloadItemImpl::Init(bool active, | 1043 void DownloadItemImpl::Init(bool active, |
| 938 download_net_logs::DownloadType download_type) { | 1044 download_net_logs::DownloadType download_type) { |
| 939 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1045 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 940 | 1046 |
| 941 if (active) | 1047 if (active) |
| 942 download_stats::RecordDownloadCount(download_stats::START_COUNT); | 1048 download_stats::RecordDownloadCount(download_stats::START_COUNT); |
| 943 | 1049 |
| 944 if (target_path_.empty()) | 1050 if (target_path_.empty()) |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1035 " total = %" PRId64 | 1141 " total = %" PRId64 |
| 1036 " received = %" PRId64 | 1142 " received = %" PRId64 |
| 1037 " reason = %s" | 1143 " reason = %s" |
| 1038 " paused = %c" | 1144 " paused = %c" |
| 1039 " otr = %c" | 1145 " otr = %c" |
| 1040 " safety = %s" | 1146 " safety = %s" |
| 1041 " last_modified = '%s'" | 1147 " last_modified = '%s'" |
| 1042 " etag = '%s'" | 1148 " etag = '%s'" |
| 1043 " url_chain = \n\t\"%s\"\n\t" | 1149 " url_chain = \n\t\"%s\"\n\t" |
| 1044 " full_path = \"%" PRFilePath "\"" | 1150 " full_path = \"%" PRFilePath "\"" |
| 1045 " target_path = \"%" PRFilePath "\"", | 1151 " target_path = \"%" PRFilePath "\"" |
| 1152 " has download file = %s", | |
| 1046 GetDbHandle(), | 1153 GetDbHandle(), |
| 1047 GetTotalBytes(), | 1154 GetTotalBytes(), |
| 1048 GetReceivedBytes(), | 1155 GetReceivedBytes(), |
| 1049 InterruptReasonDebugString(last_reason_).c_str(), | 1156 InterruptReasonDebugString(last_reason_).c_str(), |
| 1050 IsPaused() ? 'T' : 'F', | 1157 IsPaused() ? 'T' : 'F', |
| 1051 IsOtr() ? 'T' : 'F', | 1158 IsOtr() ? 'T' : 'F', |
| 1052 DebugSafetyStateString(GetSafetyState()), | 1159 DebugSafetyStateString(GetSafetyState()), |
| 1053 GetLastModifiedTime().c_str(), | 1160 GetLastModifiedTime().c_str(), |
| 1054 GetETag().c_str(), | 1161 GetETag().c_str(), |
| 1055 url_list.c_str(), | 1162 url_list.c_str(), |
| 1056 GetFullPath().value().c_str(), | 1163 GetFullPath().value().c_str(), |
| 1057 GetTargetFilePath().value().c_str()); | 1164 GetTargetFilePath().value().c_str(), |
| 1165 download_file_.get() ? "true" : "false"); | |
| 1058 } else { | 1166 } else { |
| 1059 description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); | 1167 description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); |
| 1060 } | 1168 } |
| 1061 | 1169 |
| 1062 description += " }"; | 1170 description += " }"; |
| 1063 | 1171 |
| 1064 return description; | 1172 return description; |
| 1065 } | 1173 } |
| 1066 | 1174 |
| 1067 bool DownloadItemImpl::AllDataSaved() const { return all_data_saved_; } | 1175 bool DownloadItemImpl::AllDataSaved() const { return all_data_saved_; } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1186 std::map<const void*, ExternalData*>::iterator it = | 1294 std::map<const void*, ExternalData*>::iterator it = |
| 1187 external_data_map_.find(key); | 1295 external_data_map_.find(key); |
| 1188 | 1296 |
| 1189 if (it == external_data_map_.end()) { | 1297 if (it == external_data_map_.end()) { |
| 1190 external_data_map_[key] = data; | 1298 external_data_map_[key] = data; |
| 1191 } else if (it->second != data) { | 1299 } else if (it->second != data) { |
| 1192 delete it->second; | 1300 delete it->second; |
| 1193 it->second = data; | 1301 it->second = data; |
| 1194 } | 1302 } |
| 1195 } | 1303 } |
| OLD | NEW |