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