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