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" |
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 | 482 |
483 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT); | 483 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT); |
484 | 484 |
485 TransitionTo(CANCELLED); | 485 TransitionTo(CANCELLED); |
486 if (user_cancel) | 486 if (user_cancel) |
487 delegate_->DownloadStopped(this); | 487 delegate_->DownloadStopped(this); |
488 } | 488 } |
489 | 489 |
490 // An error occurred somewhere. | 490 // An error occurred somewhere. |
491 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) { | 491 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) { |
492 // It should not be possible both to have an error and complete. | 492 // Somewhat counter-intuitively, it is possible for us to receive an |
493 DCHECK(IsInProgress()); | 493 // interrupt after we've already been interrupted. The generation of |
| 494 // interrupts from the file thread Renames and the generation of |
| 495 // interrupts from disk writes go through two different mechanisms (driven |
| 496 // by rename requests from UI thread and by write requests from IO thread, |
| 497 // respectively), and since we choose not to keep state on the File thread, |
| 498 // this is the place where the races collide. It's also possible for |
| 499 // interrupts to race with cancels. |
| 500 |
| 501 // Whatever happens, the first one to hit the UI thread wins. |
| 502 if (!IsInProgress()) |
| 503 return; |
| 504 |
494 last_reason_ = reason; | 505 last_reason_ = reason; |
495 TransitionTo(INTERRUPTED); | 506 TransitionTo(INTERRUPTED); |
496 download_stats::RecordDownloadInterrupted( | 507 download_stats::RecordDownloadInterrupted( |
497 reason, received_bytes_, total_bytes_); | 508 reason, received_bytes_, total_bytes_); |
498 delegate_->DownloadStopped(this); | 509 delegate_->DownloadStopped(this); |
499 } | 510 } |
500 | 511 |
501 void DownloadItemImpl::MarkAsComplete() { | 512 void DownloadItemImpl::MarkAsComplete() { |
502 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 513 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
503 | 514 |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 BrowserThread::FILE, FROM_HERE, | 743 BrowserThread::FILE, FROM_HERE, |
733 base::Bind(&DownloadFileManager::CompleteDownload, | 744 base::Bind(&DownloadFileManager::CompleteDownload, |
734 file_manager, GetGlobalId(), | 745 file_manager, GetGlobalId(), |
735 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, | 746 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, |
736 weak_ptr_factory_.GetWeakPtr()))); | 747 weak_ptr_factory_.GetWeakPtr()))); |
737 } | 748 } |
738 } | 749 } |
739 | 750 |
740 void DownloadItemImpl::OnDownloadRenamedToFinalName( | 751 void DownloadItemImpl::OnDownloadRenamedToFinalName( |
741 DownloadFileManager* file_manager, | 752 DownloadFileManager* file_manager, |
| 753 content::DownloadInterruptReason reason, |
742 const FilePath& full_path) { | 754 const FilePath& full_path) { |
743 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 755 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
744 | 756 |
745 VLOG(20) << __FUNCTION__ << "()" | 757 VLOG(20) << __FUNCTION__ << "()" |
746 << " full_path = \"" << full_path.value() << "\"" | 758 << " full_path = \"" << full_path.value() << "\"" |
747 << " needed rename = " << NeedsRename() | 759 << " needed rename = " << NeedsRename() |
748 << " " << DebugString(false); | 760 << " " << DebugString(false); |
749 DCHECK(NeedsRename()); | 761 DCHECK(NeedsRename()); |
750 | 762 |
751 if (full_path.empty()) | 763 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) { |
752 // Indicates error; also reported | 764 Interrupt(reason); |
753 // by DownloadManagerImpl::OnDownloadInterrupted. | |
754 return; | 765 return; |
| 766 } |
755 | 767 |
756 // full_path is now the current and target file path. | 768 // full_path is now the current and target file path. |
| 769 DCHECK(!full_path.empty()); |
757 target_path_ = full_path; | 770 target_path_ = full_path; |
758 SetFullPath(full_path); | 771 SetFullPath(full_path); |
759 delegate_->DownloadRenamedToFinalName(this); | 772 delegate_->DownloadRenamedToFinalName(this); |
760 | 773 |
761 // Complete the download and release the DownloadFile. | 774 // Complete the download and release the DownloadFile. |
762 BrowserThread::PostTask( | 775 BrowserThread::PostTask( |
763 BrowserThread::FILE, FROM_HERE, | 776 BrowserThread::FILE, FROM_HERE, |
764 base::Bind(&DownloadFileManager::CompleteDownload, | 777 base::Bind(&DownloadFileManager::CompleteDownload, |
765 file_manager, GetGlobalId(), | 778 file_manager, GetGlobalId(), |
766 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, | 779 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, |
767 weak_ptr_factory_.GetWeakPtr()))); | 780 weak_ptr_factory_.GetWeakPtr()))); |
768 } | 781 } |
769 | 782 |
770 void DownloadItemImpl::OnDownloadFileReleased() { | 783 void DownloadItemImpl::OnDownloadFileReleased() { |
771 if (delegate_->ShouldOpenDownload(this)) | 784 if (delegate_->ShouldOpenDownload(this)) |
772 Completed(); | 785 Completed(); |
773 else | 786 else |
774 delegate_delayed_complete_ = true; | 787 delegate_delayed_complete_ = true; |
775 } | 788 } |
776 | 789 |
777 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( | 790 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( |
| 791 content::DownloadInterruptReason reason, |
778 const FilePath& full_path) { | 792 const FilePath& full_path) { |
779 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 793 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
780 if (!full_path.empty()) { | 794 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) { |
| 795 Interrupt(reason); |
| 796 } else { |
781 SetFullPath(full_path); | 797 SetFullPath(full_path); |
782 UpdateObservers(); | 798 UpdateObservers(); |
783 } | 799 } |
| 800 |
784 delegate_->DownloadRenamedToIntermediateName(this); | 801 delegate_->DownloadRenamedToIntermediateName(this); |
785 } | 802 } |
786 | 803 |
787 bool DownloadItemImpl::MatchesQuery(const string16& query) const { | 804 bool DownloadItemImpl::MatchesQuery(const string16& query) const { |
788 if (query.empty()) | 805 if (query.empty()) |
789 return true; | 806 return true; |
790 | 807 |
791 DCHECK_EQ(query, base::i18n::ToLower(query)); | 808 DCHECK_EQ(query, base::i18n::ToLower(query)); |
792 | 809 |
793 string16 url_raw(UTF8ToUTF16(GetURL().spec())); | 810 string16 url_raw(UTF8ToUTF16(GetURL().spec())); |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1186 std::map<const void*, ExternalData*>::iterator it = | 1203 std::map<const void*, ExternalData*>::iterator it = |
1187 external_data_map_.find(key); | 1204 external_data_map_.find(key); |
1188 | 1205 |
1189 if (it == external_data_map_.end()) { | 1206 if (it == external_data_map_.end()) { |
1190 external_data_map_[key] = data; | 1207 external_data_map_[key] = data; |
1191 } else if (it->second != data) { | 1208 } else if (it->second != data) { |
1192 delete it->second; | 1209 delete it->second; |
1193 it->second = data; | 1210 it->second = data; |
1194 } | 1211 } |
1195 } | 1212 } |
OLD | NEW |