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

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

Issue 1751603002: [Downloads] Rework how hashes are calculated for download files. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address first round of comments Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // File method ordering: Methods in this file are in the same order as 5 // File method ordering: Methods in this file are in the same order as
6 // in download_item_impl.h, with the following exception: The public 6 // in download_item_impl.h, with the following exception: The public
7 // interface Start is placed in chronological order with the other 7 // interface Start is placed in chronological order with the other
8 // (private) routines that together define a DownloadItem's state 8 // (private) routines that together define a DownloadItem's state
9 // transitions as the download progresses. See "Download progression 9 // transitions as the download progresses. See "Download progression
10 // cascade" later in this file. 10 // cascade" later in this file.
(...skipping 20 matching lines...) Expand all
31 #include "base/format_macros.h" 31 #include "base/format_macros.h"
32 #include "base/logging.h" 32 #include "base/logging.h"
33 #include "base/metrics/histogram.h" 33 #include "base/metrics/histogram.h"
34 #include "base/stl_util.h" 34 #include "base/stl_util.h"
35 #include "base/strings/stringprintf.h" 35 #include "base/strings/stringprintf.h"
36 #include "base/strings/utf_string_conversions.h" 36 #include "base/strings/utf_string_conversions.h"
37 #include "content/browser/download/download_create_info.h" 37 #include "content/browser/download/download_create_info.h"
38 #include "content/browser/download/download_file.h" 38 #include "content/browser/download/download_file.h"
39 #include "content/browser/download/download_interrupt_reasons_impl.h" 39 #include "content/browser/download/download_interrupt_reasons_impl.h"
40 #include "content/browser/download/download_item_impl_delegate.h" 40 #include "content/browser/download/download_item_impl_delegate.h"
41 #include "content/browser/download/download_net_log_parameters.h"
41 #include "content/browser/download/download_request_handle.h" 42 #include "content/browser/download/download_request_handle.h"
42 #include "content/browser/download/download_stats.h" 43 #include "content/browser/download/download_stats.h"
43 #include "content/browser/renderer_host/render_view_host_impl.h" 44 #include "content/browser/renderer_host/render_view_host_impl.h"
44 #include "content/browser/web_contents/web_contents_impl.h" 45 #include "content/browser/web_contents/web_contents_impl.h"
45 #include "content/public/browser/browser_context.h" 46 #include "content/public/browser/browser_context.h"
46 #include "content/public/browser/browser_thread.h" 47 #include "content/public/browser/browser_thread.h"
47 #include "content/public/browser/content_browser_client.h" 48 #include "content/public/browser/content_browser_client.h"
48 #include "content/public/browser/download_danger_type.h" 49 #include "content/public/browser/download_danger_type.h"
49 #include "content/public/browser/download_interrupt_reasons.h" 50 #include "content/public/browser/download_interrupt_reasons.h"
50 #include "content/public/browser/download_url_parameters.h" 51 #include "content/public/browser/download_url_parameters.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 } 92 }
92 93
93 bool IsDownloadResumptionEnabled() { 94 bool IsDownloadResumptionEnabled() {
94 return base::FeatureList::IsEnabled(features::kDownloadResumption); 95 return base::FeatureList::IsEnabled(features::kDownloadResumption);
95 } 96 }
96 97
97 } // namespace 98 } // namespace
98 99
99 const uint32_t DownloadItem::kInvalidId = 0; 100 const uint32_t DownloadItem::kInvalidId = 0;
100 101
101 const char DownloadItem::kEmptyFileHash[] = "";
102
103 // The maximum number of attempts we will make to resume automatically. 102 // The maximum number of attempts we will make to resume automatically.
104 const int DownloadItemImpl::kMaxAutoResumeAttempts = 5; 103 const int DownloadItemImpl::kMaxAutoResumeAttempts = 5;
105 104
106 // Constructor for reading from the history service. 105 // Constructor for reading from the history service.
107 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, 106 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
108 uint32_t download_id, 107 uint32_t download_id,
109 const base::FilePath& current_path, 108 const base::FilePath& current_path,
110 const base::FilePath& target_path, 109 const base::FilePath& target_path,
111 const std::vector<GURL>& url_chain, 110 const std::vector<GURL>& url_chain,
112 const GURL& referrer_url, 111 const GURL& referrer_url,
113 const std::string& mime_type, 112 const std::string& mime_type,
114 const std::string& original_mime_type, 113 const std::string& original_mime_type,
115 const base::Time& start_time, 114 const base::Time& start_time,
116 const base::Time& end_time, 115 const base::Time& end_time,
117 const std::string& etag, 116 const std::string& etag,
118 const std::string& last_modified, 117 const std::string& last_modified,
119 int64_t received_bytes, 118 int64_t received_bytes,
120 int64_t total_bytes, 119 int64_t total_bytes,
120 const std::string& hash,
121 DownloadItem::DownloadState state, 121 DownloadItem::DownloadState state,
122 DownloadDangerType danger_type, 122 DownloadDangerType danger_type,
123 DownloadInterruptReason interrupt_reason, 123 DownloadInterruptReason interrupt_reason,
124 bool opened, 124 bool opened,
125 const net::BoundNetLog& bound_net_log) 125 const net::BoundNetLog& bound_net_log)
126 : download_id_(download_id), 126 : download_id_(download_id),
127 current_path_(current_path),
128 target_path_(target_path), 127 target_path_(target_path),
129 url_chain_(url_chain), 128 url_chain_(url_chain),
130 referrer_url_(referrer_url), 129 referrer_url_(referrer_url),
131 mime_type_(mime_type), 130 mime_type_(mime_type),
132 original_mime_type_(original_mime_type), 131 original_mime_type_(original_mime_type),
133 total_bytes_(total_bytes), 132 total_bytes_(total_bytes),
134 received_bytes_(received_bytes),
135 last_modified_time_(last_modified),
136 etag_(etag),
137 last_reason_(interrupt_reason), 133 last_reason_(interrupt_reason),
138 start_tick_(base::TimeTicks()), 134 start_tick_(base::TimeTicks()),
139 state_(ExternalToInternalState(state)), 135 state_(ExternalToInternalState(state)),
140 danger_type_(danger_type), 136 danger_type_(danger_type),
141 start_time_(start_time), 137 start_time_(start_time),
142 end_time_(end_time), 138 end_time_(end_time),
143 delegate_(delegate), 139 delegate_(delegate),
140 opened_(opened),
141 current_path_(current_path),
142 received_bytes_(received_bytes),
144 all_data_saved_(state == COMPLETE), 143 all_data_saved_(state == COMPLETE),
145 opened_(opened), 144 hash_(hash),
145 last_modified_time_(last_modified),
146 etag_(etag),
146 bound_net_log_(bound_net_log), 147 bound_net_log_(bound_net_log),
147 weak_ptr_factory_(this) { 148 weak_ptr_factory_(this) {
148 delegate_->Attach(); 149 delegate_->Attach();
149 DCHECK(state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL || 150 DCHECK(state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL ||
150 state_ == CANCELLED_INTERNAL); 151 state_ == CANCELLED_INTERNAL);
151 Init(false /* not actively downloading */, SRC_HISTORY_IMPORT); 152 Init(false /* not actively downloading */, SRC_HISTORY_IMPORT);
152 } 153 }
153 154
154 // Constructing for a regular download: 155 // Constructing for a regular download:
155 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, 156 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
(...skipping 10 matching lines...) Expand all
166 tab_referrer_url_(info.tab_referrer_url), 167 tab_referrer_url_(info.tab_referrer_url),
167 suggested_filename_(base::UTF16ToUTF8(info.save_info->suggested_name)), 168 suggested_filename_(base::UTF16ToUTF8(info.save_info->suggested_name)),
168 forced_file_path_(info.save_info->file_path), 169 forced_file_path_(info.save_info->file_path),
169 transition_type_(info.transition_type), 170 transition_type_(info.transition_type),
170 has_user_gesture_(info.has_user_gesture), 171 has_user_gesture_(info.has_user_gesture),
171 content_disposition_(info.content_disposition), 172 content_disposition_(info.content_disposition),
172 mime_type_(info.mime_type), 173 mime_type_(info.mime_type),
173 original_mime_type_(info.original_mime_type), 174 original_mime_type_(info.original_mime_type),
174 remote_address_(info.remote_address), 175 remote_address_(info.remote_address),
175 total_bytes_(info.total_bytes), 176 total_bytes_(info.total_bytes),
176 last_modified_time_(info.last_modified),
177 etag_(info.etag),
178 last_reason_(info.result), 177 last_reason_(info.result),
179 start_tick_(base::TimeTicks::Now()), 178 start_tick_(base::TimeTicks::Now()),
180 state_(INITIAL_INTERNAL), 179 state_(INITIAL_INTERNAL),
181 start_time_(info.start_time), 180 start_time_(info.start_time),
182 delegate_(delegate), 181 delegate_(delegate),
183 is_temporary_(!info.save_info->file_path.empty()), 182 is_temporary_(!info.save_info->file_path.empty()),
183 last_modified_time_(info.last_modified),
184 etag_(info.etag),
184 bound_net_log_(bound_net_log), 185 bound_net_log_(bound_net_log),
185 weak_ptr_factory_(this) { 186 weak_ptr_factory_(this) {
186 delegate_->Attach(); 187 delegate_->Attach();
187 Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD); 188 Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD);
188 189
189 // Link the event sources. 190 // Link the event sources.
190 bound_net_log_.AddEvent( 191 bound_net_log_.AddEvent(
191 net::NetLog::TYPE_DOWNLOAD_URL_REQUEST, 192 net::NetLog::TYPE_DOWNLOAD_URL_REQUEST,
192 info.request_bound_net_log.source().ToEventParametersCallback()); 193 info.request_bound_net_log.source().ToEventParametersCallback());
193 194
194 info.request_bound_net_log.AddEvent( 195 info.request_bound_net_log.AddEvent(
195 net::NetLog::TYPE_DOWNLOAD_STARTED, 196 net::NetLog::TYPE_DOWNLOAD_STARTED,
196 bound_net_log_.source().ToEventParametersCallback()); 197 bound_net_log_.source().ToEventParametersCallback());
197 } 198 }
198 199
199 // Constructing for the "Save Page As..." feature: 200 // Constructing for the "Save Page As..." feature:
200 DownloadItemImpl::DownloadItemImpl( 201 DownloadItemImpl::DownloadItemImpl(
201 DownloadItemImplDelegate* delegate, 202 DownloadItemImplDelegate* delegate,
202 uint32_t download_id, 203 uint32_t download_id,
203 const base::FilePath& path, 204 const base::FilePath& path,
204 const GURL& url, 205 const GURL& url,
205 const std::string& mime_type, 206 const std::string& mime_type,
206 scoped_ptr<DownloadRequestHandleInterface> request_handle, 207 scoped_ptr<DownloadRequestHandleInterface> request_handle,
207 const net::BoundNetLog& bound_net_log) 208 const net::BoundNetLog& bound_net_log)
208 : is_save_package_download_(true), 209 : is_save_package_download_(true),
209 request_handle_(std::move(request_handle)), 210 request_handle_(std::move(request_handle)),
210 download_id_(download_id), 211 download_id_(download_id),
211 current_path_(path),
212 target_path_(path), 212 target_path_(path),
213 url_chain_(1, url), 213 url_chain_(1, url),
214 mime_type_(mime_type), 214 mime_type_(mime_type),
215 original_mime_type_(mime_type), 215 original_mime_type_(mime_type),
216 start_tick_(base::TimeTicks::Now()), 216 start_tick_(base::TimeTicks::Now()),
217 state_(IN_PROGRESS_INTERNAL), 217 state_(IN_PROGRESS_INTERNAL),
218 start_time_(base::Time::Now()), 218 start_time_(base::Time::Now()),
219 delegate_(delegate), 219 delegate_(delegate),
220 current_path_(path),
220 bound_net_log_(bound_net_log), 221 bound_net_log_(bound_net_log),
221 weak_ptr_factory_(this) { 222 weak_ptr_factory_(this) {
222 delegate_->Attach(); 223 delegate_->Attach();
223 Init(true /* actively downloading */, SRC_SAVE_PAGE_AS); 224 Init(true /* actively downloading */, SRC_SAVE_PAGE_AS);
224 } 225 }
225 226
226 DownloadItemImpl::~DownloadItemImpl() { 227 DownloadItemImpl::~DownloadItemImpl() {
227 DCHECK_CURRENTLY_ON(BrowserThread::UI); 228 DCHECK_CURRENTLY_ON(BrowserThread::UI);
228 229
229 // Should always have been nuked before now, at worst in 230 // Should always have been nuked before now, at worst in
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 365
365 case MAX_DOWNLOAD_INTERNAL_STATE: 366 case MAX_DOWNLOAD_INTERNAL_STATE:
366 case TARGET_RESOLVED_INTERNAL: 367 case TARGET_RESOLVED_INTERNAL:
367 NOTREACHED(); 368 NOTREACHED();
368 } 369 }
369 } 370 }
370 371
371 void DownloadItemImpl::Cancel(bool user_cancel) { 372 void DownloadItemImpl::Cancel(bool user_cancel) {
372 DCHECK_CURRENTLY_ON(BrowserThread::UI); 373 DCHECK_CURRENTLY_ON(BrowserThread::UI);
373 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 374 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
374 Interrupt(user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED 375 InterruptAndDiscardPartialState(
375 : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN); 376 user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
377 : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN);
376 UpdateObservers(); 378 UpdateObservers();
377 } 379 }
378 380
379 void DownloadItemImpl::Remove() { 381 void DownloadItemImpl::Remove() {
380 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 382 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
381 DCHECK_CURRENTLY_ON(BrowserThread::UI); 383 DCHECK_CURRENTLY_ON(BrowserThread::UI);
382 384
383 delegate_->AssertStateConsistent(this); 385 delegate_->AssertStateConsistent(this);
384 Interrupt(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); 386 InterruptAndDiscardPartialState(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
385 UpdateObservers(); 387 UpdateObservers();
386 delegate_->AssertStateConsistent(this); 388 delegate_->AssertStateConsistent(this);
387 389
388 NotifyRemoved(); 390 NotifyRemoved();
389 delegate_->DownloadRemoved(this); 391 delegate_->DownloadRemoved(this);
390 // We have now been deleted. 392 // We have now been deleted.
391 } 393 }
392 394
393 void DownloadItemImpl::OpenDownload() { 395 void DownloadItemImpl::OpenDownload() {
394 DCHECK_CURRENTLY_ON(BrowserThread::UI); 396 DCHECK_CURRENTLY_ON(BrowserThread::UI);
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 } 585 }
584 586
585 DownloadItem::TargetDisposition DownloadItemImpl::GetTargetDisposition() const { 587 DownloadItem::TargetDisposition DownloadItemImpl::GetTargetDisposition() const {
586 return target_disposition_; 588 return target_disposition_;
587 } 589 }
588 590
589 const std::string& DownloadItemImpl::GetHash() const { 591 const std::string& DownloadItemImpl::GetHash() const {
590 return hash_; 592 return hash_;
591 } 593 }
592 594
593 const std::string& DownloadItemImpl::GetHashState() const {
594 return hash_state_;
595 }
596
597 bool DownloadItemImpl::GetFileExternallyRemoved() const { 595 bool DownloadItemImpl::GetFileExternallyRemoved() const {
598 return file_externally_removed_; 596 return file_externally_removed_;
599 } 597 }
600 598
601 void DownloadItemImpl::DeleteFile(const base::Callback<void(bool)>& callback) { 599 void DownloadItemImpl::DeleteFile(const base::Callback<void(bool)>& callback) {
602 DCHECK_CURRENTLY_ON(BrowserThread::UI); 600 DCHECK_CURRENTLY_ON(BrowserThread::UI);
603 if (GetState() != DownloadItem::COMPLETE) { 601 if (GetState() != DownloadItem::COMPLETE) {
604 // Pass a null WeakPtr so it doesn't call OnDownloadedFileRemoved. 602 // Pass a null WeakPtr so it doesn't call OnDownloadedFileRemoved.
605 BrowserThread::PostTask( 603 BrowserThread::PostTask(
606 BrowserThread::UI, FROM_HERE, 604 BrowserThread::UI, FROM_HERE,
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 ++iter; 776 ++iter;
779 for ( ; verbose && (iter != last); ++iter) { 777 for ( ; verbose && (iter != last); ++iter) {
780 url_list += " ->\n\t"; 778 url_list += " ->\n\t";
781 const GURL& next_url = *iter; 779 const GURL& next_url = *iter;
782 url_list += next_url.is_valid() ? next_url.spec() : "<invalid>"; 780 url_list += next_url.is_valid() ? next_url.spec() : "<invalid>";
783 } 781 }
784 } 782 }
785 783
786 if (verbose) { 784 if (verbose) {
787 description += base::StringPrintf( 785 description += base::StringPrintf(
788 " total = %" PRId64 786 " total = %" PRId64 " received = %" PRId64
789 " received = %" PRId64
790 " reason = %s" 787 " reason = %s"
791 " paused = %c" 788 " paused = %c"
792 " resume_mode = %s" 789 " resume_mode = %s"
793 " auto_resume_count = %d" 790 " auto_resume_count = %d"
794 " danger = %d" 791 " danger = %d"
795 " all_data_saved = %c" 792 " all_data_saved = %c"
796 " last_modified = '%s'" 793 " last_modified = '%s'"
797 " etag = '%s'" 794 " etag = '%s'"
798 " has_download_file = %s" 795 " has_download_file = %s"
799 " url_chain = \n\t\"%s\"\n\t" 796 " url_chain = \n\t\"%s\"\n\t"
800 " full_path = \"%" PRFilePath "\"\n\t" 797 " current_path = \"%" PRFilePath
798 "\"\n\t"
801 " target_path = \"%" PRFilePath "\"", 799 " target_path = \"%" PRFilePath "\"",
802 GetTotalBytes(), 800 GetTotalBytes(), GetReceivedBytes(),
803 GetReceivedBytes(),
804 DownloadInterruptReasonToString(last_reason_).c_str(), 801 DownloadInterruptReasonToString(last_reason_).c_str(),
805 IsPaused() ? 'T' : 'F', 802 IsPaused() ? 'T' : 'F', DebugResumeModeString(GetResumeMode()),
806 DebugResumeModeString(GetResumeMode()), 803 auto_resume_count_, GetDangerType(), AllDataSaved() ? 'T' : 'F',
807 auto_resume_count_, 804 GetLastModifiedTime().c_str(), GetETag().c_str(),
808 GetDangerType(), 805 download_file_.get() ? "true" : "false", url_list.c_str(),
809 AllDataSaved() ? 'T' : 'F', 806 GetFullPath().value().c_str(), GetTargetFilePath().value().c_str());
810 GetLastModifiedTime().c_str(),
811 GetETag().c_str(),
812 download_file_.get() ? "true" : "false",
813 url_list.c_str(),
814 GetFullPath().value().c_str(),
815 GetTargetFilePath().value().c_str());
816 } else { 807 } else {
817 description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); 808 description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
818 } 809 }
819 810
820 description += " }"; 811 description += " }";
821 812
822 return description; 813 return description;
823 } 814 }
824 815
825 DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const { 816 DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const {
(...skipping 18 matching lines...) Expand all
844 (auto_resume_count_ >= kMaxAutoResumeAttempts || is_paused_); 835 (auto_resume_count_ >= kMaxAutoResumeAttempts || is_paused_);
845 836
846 switch(last_reason_) { 837 switch(last_reason_) {
847 case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR: 838 case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
848 case DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT: 839 case DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
849 break; 840 break;
850 841
851 case DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE: 842 case DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
852 // The server disagreed with the file offset that we sent. 843 // The server disagreed with the file offset that we sent.
853 844
845 case DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH:
846 // The file on disk was found to not match the expected hash. Discard and
847 // start from beginning.
848
854 case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT: 849 case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:
855 // The [possibly persisted] file offset disagreed with the file on disk. 850 // The [possibly persisted] file offset disagreed with the file on disk.
856 851
857 // The intermediate stub is not usable and the server is resonding. Hence 852 // The intermediate stub is not usable and the server is responding. Hence
858 // retrying the request from the beginning is likely to work. 853 // retrying the request from the beginning is likely to work.
859 restart_required = true; 854 restart_required = true;
860 break; 855 break;
861 856
862 case DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED: 857 case DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
863 case DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED: 858 case DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
864 case DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN: 859 case DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
865 case DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED: 860 case DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
866 case DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE: 861 case DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE:
867 case DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN: 862 case DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
939 // HTTP_PRECONDITION_FAILED), then the download will automatically retried as 934 // HTTP_PRECONDITION_FAILED), then the download will automatically retried as
940 // a full request rather than a partial. Full restarts clobber validators. 935 // a full request rather than a partial. Full restarts clobber validators.
941 int origin_state = 0; 936 int origin_state = 0;
942 if (chain_iter != new_create_info.url_chain.end()) 937 if (chain_iter != new_create_info.url_chain.end())
943 origin_state |= ORIGIN_STATE_ON_RESUMPTION_ADDITIONAL_REDIRECTS; 938 origin_state |= ORIGIN_STATE_ON_RESUMPTION_ADDITIONAL_REDIRECTS;
944 if (etag_ != new_create_info.etag || 939 if (etag_ != new_create_info.etag ||
945 last_modified_time_ != new_create_info.last_modified) 940 last_modified_time_ != new_create_info.last_modified)
946 origin_state |= ORIGIN_STATE_ON_RESUMPTION_VALIDATORS_CHANGED; 941 origin_state |= ORIGIN_STATE_ON_RESUMPTION_VALIDATORS_CHANGED;
947 if (content_disposition_ != new_create_info.content_disposition) 942 if (content_disposition_ != new_create_info.content_disposition)
948 origin_state |= ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED; 943 origin_state |= ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED;
949 RecordOriginStateOnResumption(new_create_info.save_info->offset != 0, 944 RecordOriginStateOnResumption(received_bytes_ != 0, origin_state);
950 origin_state);
951 945
952 url_chain_.insert( 946 url_chain_.insert(
953 url_chain_.end(), chain_iter, new_create_info.url_chain.end()); 947 url_chain_.end(), chain_iter, new_create_info.url_chain.end());
954 etag_ = new_create_info.etag; 948 etag_ = new_create_info.etag;
955 last_modified_time_ = new_create_info.last_modified; 949 last_modified_time_ = new_create_info.last_modified;
956 content_disposition_ = new_create_info.content_disposition; 950 content_disposition_ = new_create_info.content_disposition;
957 951
958 // Don't update observers. This method is expected to be called just before a 952 // Don't update observers. This method is expected to be called just before a
959 // DownloadFile is created and Start() is called. The observers will be 953 // DownloadFile is created and Start() is called. The observers will be
960 // notified when the download transitions to the IN_PROGRESS state. 954 // notified when the download transitions to the IN_PROGRESS state.
(...skipping 15 matching lines...) Expand all
976 } 970 }
977 971
978 const net::BoundNetLog& DownloadItemImpl::GetBoundNetLog() const { 972 const net::BoundNetLog& DownloadItemImpl::GetBoundNetLog() const {
979 return bound_net_log_; 973 return bound_net_log_;
980 } 974 }
981 975
982 void DownloadItemImpl::SetTotalBytes(int64_t total_bytes) { 976 void DownloadItemImpl::SetTotalBytes(int64_t total_bytes) {
983 total_bytes_ = total_bytes; 977 total_bytes_ = total_bytes;
984 } 978 }
985 979
986 void DownloadItemImpl::OnAllDataSaved(const std::string& final_hash) { 980 void DownloadItemImpl::OnAllDataSaved(
981 int64_t total_bytes,
982 scoped_ptr<crypto::SecureHash> hash_state) {
987 DCHECK_CURRENTLY_ON(BrowserThread::UI); 983 DCHECK_CURRENTLY_ON(BrowserThread::UI);
988 DCHECK(!all_data_saved_); 984 DCHECK(!all_data_saved_);
989 all_data_saved_ = true; 985 all_data_saved_ = true;
986 SetTotalBytes(total_bytes);
987 UpdateProgress(total_bytes, 0);
988 hash_state_ = std::move(hash_state);
989 UpdatePrefixHash();
990 hash_state_.reset();
991
990 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 992 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
991
992 // Store final hash and null out intermediate serialized hash state.
993 hash_ = final_hash;
994 hash_state_ = "";
995
996 UpdateObservers(); 993 UpdateObservers();
997 } 994 }
998 995
999 void DownloadItemImpl::MarkAsComplete() { 996 void DownloadItemImpl::MarkAsComplete() {
1000 DCHECK_CURRENTLY_ON(BrowserThread::UI); 997 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1001 998
1002 DCHECK(all_data_saved_); 999 DCHECK(all_data_saved_);
1003 end_time_ = base::Time::Now(); 1000 end_time_ = base::Time::Now();
1004 TransitionTo(COMPLETE_INTERNAL); 1001 TransitionTo(COMPLETE_INTERNAL);
1005 UpdateObservers(); 1002 UpdateObservers();
1006 } 1003 }
1007 1004
1008 void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far, 1005 void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far,
1009 int64_t bytes_per_sec, 1006 int64_t bytes_per_sec) {
1010 const std::string& hash_state) {
1011 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1007 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1012 // If the download is in any other state we don't expect any 1008 // If the download is in any other state we don't expect any
1013 // DownloadDestinationObserver callbacks. An interruption or a cancellation 1009 // DownloadDestinationObserver callbacks. An interruption or a cancellation
1014 // results in a call to ReleaseDownloadFile which invalidates the weak 1010 // results in a call to ReleaseDownloadFile which invalidates the weak
1015 // reference held by the DownloadFile and hence cuts off any pending 1011 // reference held by the DownloadFile and hence cuts off any pending
1016 // callbacks. 1012 // callbacks.
1017 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL); 1013 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
1014
1015 // There must be no pending destination_error_.
1016 DCHECK_EQ(destination_error_, DOWNLOAD_INTERRUPT_REASON_NONE);
1017
1018 DVLOG(20) << __FUNCTION__ << " so_far=" << bytes_so_far 1018 DVLOG(20) << __FUNCTION__ << " so_far=" << bytes_so_far
1019 << " per_sec=" << bytes_per_sec 1019 << " per_sec=" << bytes_per_sec
1020 << " download=" << DebugString(true); 1020 << " download=" << DebugString(true);
1021 1021
1022 bytes_per_sec_ = bytes_per_sec; 1022 UpdateProgress(bytes_so_far, bytes_per_sec);
1023 hash_state_ = hash_state;
1024 received_bytes_ = bytes_so_far;
1025
1026 // If we've received more data than we were expecting (bad server info?),
1027 // revert to 'unknown size mode'.
1028 if (received_bytes_ > total_bytes_)
1029 total_bytes_ = 0;
1030
1031 if (bound_net_log_.IsCapturing()) { 1023 if (bound_net_log_.IsCapturing()) {
1032 bound_net_log_.AddEvent( 1024 bound_net_log_.AddEvent(
1033 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED, 1025 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED,
1034 net::NetLog::Int64Callback("bytes_so_far", received_bytes_)); 1026 net::NetLog::Int64Callback("bytes_so_far", received_bytes_));
1035 } 1027 }
1036 1028
1037 UpdateObservers(); 1029 UpdateObservers();
1038 } 1030 }
1039 1031
1040 void DownloadItemImpl::DestinationError(DownloadInterruptReason reason) { 1032 void DownloadItemImpl::DestinationError(
1033 DownloadInterruptReason reason,
1034 int64_t bytes_so_far,
1035 scoped_ptr<crypto::SecureHash> secure_hash) {
1041 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1036 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1042 // If the download is in any other state we don't expect any 1037 // If the download is in any other state we don't expect any
1043 // DownloadDestinationObserver callbacks. An interruption or a cancellation 1038 // DownloadDestinationObserver callbacks. An interruption or a cancellation
1044 // results in a call to ReleaseDownloadFile which invalidates the weak 1039 // results in a call to ReleaseDownloadFile which invalidates the weak
1045 // reference held by the DownloadFile and hence cuts off any pending 1040 // reference held by the DownloadFile and hence cuts off any pending
1046 // callbacks. 1041 // callbacks.
1047 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL); 1042 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
1048 DVLOG(20) << __FUNCTION__ 1043 DVLOG(20) << __FUNCTION__
1049 << "() reason:" << DownloadInterruptReasonToString(reason); 1044 << "() reason:" << DownloadInterruptReasonToString(reason);
1050 1045
1051 // Postpone recognition of this error until after file name determination 1046 // Postpone recognition of this error until after file name determination
1052 // has completed and the intermediate file has been renamed to simplify 1047 // has completed and the intermediate file has been renamed to simplify
1053 // resumption conditions. 1048 // resumption conditions.
1054 if (state_ == TARGET_PENDING_INTERNAL) { 1049 if (state_ == TARGET_PENDING_INTERNAL) {
1050 received_bytes_ = bytes_so_far;
1051 hash_state_ = std::move(secure_hash);
1052 hash_.clear();
1055 destination_error_ = reason; 1053 destination_error_ = reason;
1056 return; 1054 return;
1057 } 1055 }
1058 Interrupt(reason); 1056 InterruptWithPartialState(bytes_so_far, std::move(secure_hash), reason);
1059 UpdateObservers(); 1057 UpdateObservers();
1060 } 1058 }
1061 1059
1062 void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) { 1060 void DownloadItemImpl::DestinationCompleted(
1061 int64_t total_bytes,
1062 scoped_ptr<crypto::SecureHash> secure_hash) {
1063 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1063 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1064 // If the download is in any other state we don't expect any 1064 // If the download is in any other state we don't expect any
1065 // DownloadDestinationObserver callbacks. An interruption or a cancellation 1065 // DownloadDestinationObserver callbacks. An interruption or a cancellation
1066 // results in a call to ReleaseDownloadFile which invalidates the weak 1066 // results in a call to ReleaseDownloadFile which invalidates the weak
1067 // reference held by the DownloadFile and hence cuts off any pending 1067 // reference held by the DownloadFile and hence cuts off any pending
1068 // callbacks. 1068 // callbacks.
1069 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL); 1069 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
1070 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 1070 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
1071 1071
1072 OnAllDataSaved(final_hash); 1072 OnAllDataSaved(total_bytes, std::move(secure_hash));
1073 MaybeCompleteDownload(); 1073 MaybeCompleteDownload();
1074 } 1074 }
1075 1075
1076 // **** Download progression cascade 1076 // **** Download progression cascade
1077 1077
1078 void DownloadItemImpl::Init(bool active, 1078 void DownloadItemImpl::Init(bool active,
1079 DownloadType download_type) { 1079 DownloadType download_type) {
1080 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1080 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1081 1081
1082 if (active) 1082 if (active)
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 DCHECK(state_ == INITIAL_INTERNAL || state_ == RESUMING_INTERNAL); 1141 DCHECK(state_ == INITIAL_INTERNAL || state_ == RESUMING_INTERNAL);
1142 1142
1143 // If the state_ is INITIAL_INTERNAL, then the target path must be empty. 1143 // If the state_ is INITIAL_INTERNAL, then the target path must be empty.
1144 DCHECK(state_ != INITIAL_INTERNAL || target_path_.empty()); 1144 DCHECK(state_ != INITIAL_INTERNAL || target_path_.empty());
1145 1145
1146 // If a resumption attempted failed, or if the download was DOA, then the 1146 // If a resumption attempted failed, or if the download was DOA, then the
1147 // download should go back to being interrupted. 1147 // download should go back to being interrupted.
1148 if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) { 1148 if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) {
1149 DCHECK(!download_file_.get()); 1149 DCHECK(!download_file_.get());
1150 1150
1151 // Download requests that are interrupted by Start() should result in a
1152 // DownloadCreateInfo with an intact DownloadSaveInfo.
1153 DCHECK(new_create_info.save_info);
1154
1155 int64_t offset = new_create_info.save_info->offset;
1156 scoped_ptr<crypto::SecureHash> hash_state =
1157 make_scoped_ptr(new_create_info.save_info->hash_state
1158 ? new_create_info.save_info->hash_state->Clone()
1159 : nullptr);
1160
1151 // Interrupted downloads also need a target path. 1161 // Interrupted downloads also need a target path.
1152 if (target_path_.empty()) { 1162 if (target_path_.empty()) {
1163 received_bytes_ = offset;
1164 hash_state_ = std::move(hash_state);
1165 hash_.clear();
1166 destination_error_ = new_create_info.result;
1153 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL); 1167 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
1154 destination_error_ = new_create_info.result;
1155 DetermineDownloadTarget(); 1168 DetermineDownloadTarget();
1156 return; 1169 return;
1157 } 1170 }
1158 1171
1159 // Otherwise, this was a resumption attempt which ended with an 1172 // Otherwise, this was a resumption attempt which ended with an
1160 // interruption. Continue with current target path. 1173 // interruption. Continue with current target path.
1161 TransitionTo(TARGET_RESOLVED_INTERNAL); 1174 TransitionTo(TARGET_RESOLVED_INTERNAL);
1162 Interrupt(new_create_info.result); 1175 InterruptWithPartialState(offset, std::move(hash_state),
1176 new_create_info.result);
1163 UpdateObservers(); 1177 UpdateObservers();
1164 return; 1178 return;
1165 } 1179 }
1166 1180
1167 // Successful download start. 1181 // Successful download start.
1168 DCHECK(download_file_.get()); 1182 DCHECK(download_file_.get());
1169 DCHECK(request_handle_.get()); 1183 DCHECK(request_handle_.get());
1170 1184
1171 if (state_ == RESUMING_INTERNAL) 1185 if (state_ == RESUMING_INTERNAL)
1172 UpdateValidatorsOnResumption(new_create_info); 1186 UpdateValidatorsOnResumption(new_create_info);
1173 1187
1174 TransitionTo(TARGET_PENDING_INTERNAL); 1188 TransitionTo(TARGET_PENDING_INTERNAL);
1175 1189
1176 BrowserThread::PostTask( 1190 BrowserThread::PostTask(
1177 BrowserThread::FILE, FROM_HERE, 1191 BrowserThread::FILE, FROM_HERE,
1178 base::Bind(&DownloadFile::Initialize, 1192 base::Bind(&DownloadFile::Initialize,
1179 // Safe because we control download file lifetime. 1193 // Safe because we control download file lifetime.
1180 base::Unretained(download_file_.get()), 1194 base::Unretained(download_file_.get()),
1181 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, 1195 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
1182 weak_ptr_factory_.GetWeakPtr()))); 1196 weak_ptr_factory_.GetWeakPtr())));
1183 } 1197 }
1184 1198
1185 void DownloadItemImpl::OnDownloadFileInitialized( 1199 void DownloadItemImpl::OnDownloadFileInitialized(
1186 DownloadInterruptReason result) { 1200 DownloadInterruptReason result) {
1187 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1201 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1188 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL); 1202 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL);
1189 DVLOG(20) << __FUNCTION__ 1203 DVLOG(20) << __FUNCTION__
1190 << "() result:" << DownloadInterruptReasonToString(result); 1204 << "() result:" << DownloadInterruptReasonToString(result);
1191 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { 1205 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
1192 // Whoops. That didn't work. Proceed as an interrupted download. 1206 // Whoops. That didn't work. Proceed as an interrupted download, but reset
1207 // the partial state. Currently, the partial stub cannot be recovered if the
1208 // download file initialization fails.
1209 received_bytes_ = 0;
1210 hash_state_.reset();
1211 hash_.clear();
1193 destination_error_ = result; 1212 destination_error_ = result;
1194 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL); 1213 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
1195 } 1214 }
1196 1215
1197 DetermineDownloadTarget(); 1216 DetermineDownloadTarget();
1198 } 1217 }
1199 1218
1200 void DownloadItemImpl::DetermineDownloadTarget() { 1219 void DownloadItemImpl::DetermineDownloadTarget() {
1201 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1220 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1202 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true); 1221 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true);
(...skipping 24 matching lines...) Expand all
1227 << " disposition:" << disposition << " danger_type:" << danger_type 1246 << " disposition:" << disposition << " danger_type:" << danger_type
1228 << " this:" << DebugString(true); 1247 << " this:" << DebugString(true);
1229 1248
1230 target_path_ = target_path; 1249 target_path_ = target_path;
1231 target_disposition_ = disposition; 1250 target_disposition_ = disposition;
1232 SetDangerType(danger_type); 1251 SetDangerType(danger_type);
1233 1252
1234 // This was an interrupted download that was looking for a filename. Now that 1253 // This was an interrupted download that was looking for a filename. Now that
1235 // it has one, transition to interrupted. 1254 // it has one, transition to interrupted.
1236 if (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL) { 1255 if (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL) {
1237 Interrupt(destination_error_); 1256 InterruptWithPartialState(received_bytes_, std::move(hash_state_),
1257 destination_error_);
1238 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE; 1258 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
1239 UpdateObservers(); 1259 UpdateObservers();
1240 return; 1260 return;
1241 } 1261 }
1242 1262
1243 // We want the intermediate and target paths to refer to the same directory so 1263 // We want the intermediate and target paths to refer to the same directory so
1244 // that they are both on the same device and subject to same 1264 // that they are both on the same device and subject to same
1245 // space/permission/availability constraints. 1265 // space/permission/availability constraints.
1246 DCHECK(intermediate_path.DirName() == target_path.DirName()); 1266 DCHECK(intermediate_path.DirName() == target_path.DirName());
1247 1267
(...skipping 27 matching lines...) Expand all
1275 base::Unretained(download_file_.get()), 1295 base::Unretained(download_file_.get()),
1276 intermediate_path, callback)); 1296 intermediate_path, callback));
1277 } 1297 }
1278 1298
1279 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( 1299 void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
1280 DownloadInterruptReason reason, 1300 DownloadInterruptReason reason,
1281 const base::FilePath& full_path) { 1301 const base::FilePath& full_path) {
1282 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1302 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1283 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL); 1303 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL);
1284 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 1304 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
1305
1285 TransitionTo(TARGET_RESOLVED_INTERNAL); 1306 TransitionTo(TARGET_RESOLVED_INTERNAL);
1286 1307
1308 // If the intermediate rename fails while there's also a destination_error_,
1309 // then the former is considered the critical error since it requires
1310 // discarding the partial state.
1311 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1312 // TODO(asanka): Even though the rename failed, it may still be possible to
1313 // recover the partial state from the 'before' name.
1314 InterruptAndDiscardPartialState(reason);
1315 UpdateObservers();
1316 return;
1317 }
1318
1287 if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) { 1319 if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) {
1288 // Process destination error. If both |reason| and |destination_error_| 1320 SetFullPath(full_path);
1289 // refer to actual errors, we want to use the |destination_error_| as the 1321 InterruptWithPartialState(received_bytes_, std::move(hash_state_),
1290 // argument to the Interrupt() routine, as it happened first. 1322 destination_error_);
1291 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE)
1292 SetFullPath(full_path);
1293 Interrupt(destination_error_);
1294 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE; 1323 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
1295 UpdateObservers(); 1324 UpdateObservers();
1296 } else if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1325 return;
1297 Interrupt(reason);
1298 // All file errors result in file deletion above; no need to cleanup. The
1299 // current_path_ should be empty. Resuming this download will force a
1300 // restart and a re-doing of filename determination.
1301 DCHECK(current_path_.empty());
1302 UpdateObservers();
1303 } else {
1304 SetFullPath(full_path);
1305 TransitionTo(IN_PROGRESS_INTERNAL);
1306 // TODO(asanka): Calling UpdateObservers() prior to MaybeCompleteDownload()
1307 // is not safe. The download could be in an underminate state after invoking
1308 // observers. http://crbug.com/586610
1309 UpdateObservers();
1310 MaybeCompleteDownload();
1311 } 1326 }
1327
1328 SetFullPath(full_path);
1329 TransitionTo(IN_PROGRESS_INTERNAL);
1330 // TODO(asanka): Calling UpdateObservers() prior to MaybeCompleteDownload() is
1331 // not safe. The download could be in an underminate state after invoking
1332 // observers. http://crbug.com/586610
1333 UpdateObservers();
1334 MaybeCompleteDownload();
1312 } 1335 }
1313 1336
1314 // When SavePackage downloads MHTML to GData (see 1337 // When SavePackage downloads MHTML to GData (see
1315 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it 1338 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it
1316 // does for non-SavePackage downloads, but SavePackage downloads never satisfy 1339 // does for non-SavePackage downloads, but SavePackage downloads never satisfy
1317 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls 1340 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls
1318 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage 1341 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage
1319 // notices that the upload has completed and runs its normal Finish() pathway. 1342 // notices that the upload has completed and runs its normal Finish() pathway.
1320 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes 1343 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes
1321 // downloads. SavePackage always uses its own Finish() to mark downloads 1344 // downloads. SavePackage always uses its own Finish() to mark downloads
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1363 1386
1364 DCHECK(download_file_.get()); 1387 DCHECK(download_file_.get());
1365 // Unilaterally rename; even if it already has the right name, 1388 // Unilaterally rename; even if it already has the right name,
1366 // we need theannotation. 1389 // we need theannotation.
1367 DownloadFile::RenameCompletionCallback callback = 1390 DownloadFile::RenameCompletionCallback callback =
1368 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, 1391 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
1369 weak_ptr_factory_.GetWeakPtr()); 1392 weak_ptr_factory_.GetWeakPtr());
1370 BrowserThread::PostTask( 1393 BrowserThread::PostTask(
1371 BrowserThread::FILE, FROM_HERE, 1394 BrowserThread::FILE, FROM_HERE,
1372 base::Bind(&DownloadFile::RenameAndAnnotate, 1395 base::Bind(&DownloadFile::RenameAndAnnotate,
1373 base::Unretained(download_file_.get()), 1396 base::Unretained(download_file_.get()), GetTargetFilePath(),
1374 GetTargetFilePath(), callback)); 1397 delegate_->GetApplicationClientIdForFileScanning(), GetURL(),
1398 GetReferrerUrl(), callback));
1375 } 1399 }
1376 1400
1377 void DownloadItemImpl::OnDownloadRenamedToFinalName( 1401 void DownloadItemImpl::OnDownloadRenamedToFinalName(
1378 DownloadInterruptReason reason, 1402 DownloadInterruptReason reason,
1379 const base::FilePath& full_path) { 1403 const base::FilePath& full_path) {
1380 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1404 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1381 DCHECK(!is_save_package_download_); 1405 DCHECK(!is_save_package_download_);
1382 1406
1383 // If a cancel or interrupt hit, we'll cancel the DownloadFile, which 1407 // If a cancel or interrupt hit, we'll cancel the DownloadFile, which
1384 // will result in deleting the file on the file thread. So we don't 1408 // will result in deleting the file on the file thread. So we don't
1385 // care about the name having been changed. 1409 // care about the name having been changed.
1386 if (state_ != IN_PROGRESS_INTERNAL) 1410 if (state_ != IN_PROGRESS_INTERNAL)
1387 return; 1411 return;
1388 1412
1389 DVLOG(20) << __FUNCTION__ << "()" 1413 DVLOG(20) << __FUNCTION__ << "()"
1390 << " full_path = \"" << full_path.value() << "\"" 1414 << " full_path = \"" << full_path.value() << "\""
1391 << " " << DebugString(false); 1415 << " " << DebugString(false);
1392 1416
1393 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1417 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1394 Interrupt(reason); 1418 // Failure to perform the final rename is considered fatal. TODO(asanka): It
1395 1419 // may not be, in which case we should figure out whether we can recover the
1396 // All file errors should have resulted in in file deletion above. On 1420 // state.
1397 // resumption we will need to re-do filename determination. 1421 InterruptAndDiscardPartialState(reason);
1398 DCHECK(current_path_.empty());
1399 UpdateObservers(); 1422 UpdateObservers();
1400 return; 1423 return;
1401 } 1424 }
1402 1425
1403 DCHECK(target_path_ == full_path); 1426 DCHECK(target_path_ == full_path);
1404 1427
1405 if (full_path != current_path_) { 1428 if (full_path != current_path_) {
1406 // full_path is now the current and target file path. 1429 // full_path is now the current and target file path.
1407 DCHECK(!full_path.empty()); 1430 DCHECK(!full_path.empty());
1408 SetFullPath(full_path); 1431 SetFullPath(full_path);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1456 if (!IsTemporary()) 1479 if (!IsTemporary())
1457 OpenDownload(); 1480 OpenDownload();
1458 1481
1459 auto_opened_ = true; 1482 auto_opened_ = true;
1460 } 1483 }
1461 UpdateObservers(); 1484 UpdateObservers();
1462 } 1485 }
1463 1486
1464 // **** End of Download progression cascade 1487 // **** End of Download progression cascade
1465 1488
1466 // An error occurred somewhere. 1489 void DownloadItemImpl::InterruptAndDiscardPartialState(
1467 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { 1490 DownloadInterruptReason reason) {
1491 InterruptWithPartialState(0, scoped_ptr<crypto::SecureHash>(), reason);
1492 }
1493
1494 void DownloadItemImpl::InterruptWithPartialState(
1495 int64_t bytes_so_far,
1496 scoped_ptr<crypto::SecureHash> hash_state,
1497 DownloadInterruptReason reason) {
1468 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1498 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1469 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason); 1499 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason);
1470 DVLOG(20) << __FUNCTION__ 1500 DVLOG(20) << __FUNCTION__
1471 << "() reason:" << DownloadInterruptReasonToString(reason) 1501 << "() reason:" << DownloadInterruptReasonToString(reason)
1502 << " bytes_so_far:" << bytes_so_far
1503 << " hash_state:" << (hash_state ? "Valid" : "Invalid")
1472 << " this=" << DebugString(true); 1504 << " this=" << DebugString(true);
1473 1505
1474 // Somewhat counter-intuitively, it is possible for us to receive an 1506 // Somewhat counter-intuitively, it is possible for us to receive an
1475 // interrupt after we've already been interrupted. The generation of 1507 // interrupt after we've already been interrupted. The generation of
1476 // interrupts from the file thread Renames and the generation of 1508 // interrupts from the file thread Renames and the generation of
1477 // interrupts from disk writes go through two different mechanisms (driven 1509 // interrupts from disk writes go through two different mechanisms (driven
1478 // by rename requests from UI thread and by write requests from IO thread, 1510 // by rename requests from UI thread and by write requests from IO thread,
1479 // respectively), and since we choose not to keep state on the File thread, 1511 // respectively), and since we choose not to keep state on the File thread,
1480 // this is the place where the races collide. It's also possible for 1512 // this is the place where the races collide. It's also possible for
1481 // interrupts to race with cancels. 1513 // interrupts to race with cancels.
(...skipping 20 matching lines...) Expand all
1502 1534
1503 if (download_file_) { 1535 if (download_file_) {
1504 ResumeMode resume_mode = GetResumeMode(); 1536 ResumeMode resume_mode = GetResumeMode();
1505 ReleaseDownloadFile(resume_mode != RESUME_MODE_IMMEDIATE_CONTINUE && 1537 ReleaseDownloadFile(resume_mode != RESUME_MODE_IMMEDIATE_CONTINUE &&
1506 resume_mode != RESUME_MODE_USER_CONTINUE); 1538 resume_mode != RESUME_MODE_USER_CONTINUE);
1507 } 1539 }
1508 break; 1540 break;
1509 1541
1510 case RESUMING_INTERNAL: 1542 case RESUMING_INTERNAL:
1511 case INTERRUPTED_INTERNAL: 1543 case INTERRUPTED_INTERNAL:
1544 DCHECK(!download_file_);
1512 // The first non-cancel interrupt reason wins in cases where multiple 1545 // The first non-cancel interrupt reason wins in cases where multiple
1513 // things go wrong. 1546 // things go wrong.
1514 if (reason != DOWNLOAD_INTERRUPT_REASON_USER_CANCELED && 1547 if (reason != DOWNLOAD_INTERRUPT_REASON_USER_CANCELED &&
1515 reason != DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) 1548 reason != DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN)
1516 return; 1549 return;
1517 1550
1518 last_reason_ = reason; 1551 last_reason_ = reason;
1519 if (!current_path_.empty()) { 1552 if (!current_path_.empty()) {
1520 // There is no download file and this is transitioning from INTERRUPTED 1553 // There is no download file and this is transitioning from INTERRUPTED
1521 // to CANCELLED. The intermediate file is no longer usable, and should 1554 // to CANCELLED. The intermediate file is no longer usable, and should
(...skipping 11 matching lines...) Expand all
1533 // through another round of downloading when we resume. There's a potential 1566 // through another round of downloading when we resume. There's a potential
1534 // problem here in the abstract, as if we did download all the data and then 1567 // problem here in the abstract, as if we did download all the data and then
1535 // run into a continuable error, on resumption we won't download any more 1568 // run into a continuable error, on resumption we won't download any more
1536 // data. However, a) there are currently no continuable errors that can occur 1569 // data. However, a) there are currently no continuable errors that can occur
1537 // after we download all the data, and b) if there were, that would probably 1570 // after we download all the data, and b) if there were, that would probably
1538 // simply result in a null range request, which would generate a 1571 // simply result in a null range request, which would generate a
1539 // DestinationCompleted() notification from the DownloadFile, which would 1572 // DestinationCompleted() notification from the DownloadFile, which would
1540 // behave properly with setting all_data_saved_ to false here. 1573 // behave properly with setting all_data_saved_ to false here.
1541 all_data_saved_ = false; 1574 all_data_saved_ = false;
1542 1575
1576 if (current_path_.empty()) {
1577 hash_state_.reset();
1578 hash_.clear();
1579 received_bytes_ = 0;
1580 } else {
1581 UpdateProgress(bytes_so_far, 0);
1582 hash_state_ = std::move(hash_state);
1583 UpdatePrefixHash();
1584 }
1585
1543 if (request_handle_) 1586 if (request_handle_)
1544 request_handle_->CancelRequest(); 1587 request_handle_->CancelRequest();
1545 1588
1546 if (reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED || 1589 if (reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED ||
1547 reason == DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) { 1590 reason == DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) {
1548 if (IsDangerous()) { 1591 if (IsDangerous()) {
1549 RecordDangerousDownloadDiscard( 1592 RecordDangerousDownloadDiscard(
1550 reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED 1593 reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
1551 ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION 1594 ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION
1552 : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN, 1595 : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN,
1553 GetDangerType(), GetTargetFilePath()); 1596 GetDangerType(), GetTargetFilePath());
1554 } 1597 }
1555 1598
1556 RecordDownloadCount(CANCELLED_COUNT); 1599 RecordDownloadCount(CANCELLED_COUNT);
1557 TransitionTo(CANCELLED_INTERNAL); 1600 TransitionTo(CANCELLED_INTERNAL);
1558 return; 1601 return;
1559 } 1602 }
1560 1603
1561 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_); 1604 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_);
1562 if (!GetWebContents()) 1605 if (!GetWebContents())
1563 RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS); 1606 RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS);
1564 1607
1565 TransitionTo(INTERRUPTED_INTERNAL); 1608 TransitionTo(INTERRUPTED_INTERNAL);
1566 AutoResumeIfValid(); 1609 AutoResumeIfValid();
1567 } 1610 }
1568 1611
1612 void DownloadItemImpl::UpdateProgress(int64_t bytes_so_far,
1613 int64_t bytes_per_sec) {
1614 received_bytes_ = bytes_so_far;
1615 bytes_per_sec_ = bytes_per_sec;
1616
1617 // If we've received more data than we were expecting (bad server info?),
1618 // revert to 'unknown size mode'.
1619 if (received_bytes_ > total_bytes_)
1620 total_bytes_ = 0;
1621 }
1622
1623 void DownloadItemImpl::UpdatePrefixHash() {
svaldez 2016/03/10 17:45:34 Is it possible to get rid of hash_ and make GetHas
asanka 2016/03/11 16:25:09 GetHash() may be called at a time where there's no
1624 if (!hash_state_) {
1625 hash_.clear();
1626 return;
1627 }
1628
1629 scoped_ptr<crypto::SecureHash> clone(hash_state_->Clone());
1630 std::vector<char> hash_value(clone->GetHashLength());
1631 clone->Finish(&hash_value.front(), hash_value.size());
1632 hash_.assign(hash_value.begin(), hash_value.end());
1633 }
1634
1569 void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) { 1635 void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) {
1570 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1636 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1571 DVLOG(20) << __FUNCTION__ << "() destroy_file:" << destroy_file; 1637 DVLOG(20) << __FUNCTION__ << "() destroy_file:" << destroy_file;
1572 1638
1573 if (destroy_file) { 1639 if (destroy_file) {
1574 BrowserThread::PostTask( 1640 BrowserThread::PostTask(
1575 BrowserThread::FILE, FROM_HERE, 1641 BrowserThread::FILE, FROM_HERE,
1576 // Will be deleted at end of task execution. 1642 // Will be deleted at end of task execution.
1577 base::Bind(&DownloadFileCancel, base::Passed(&download_file_))); 1643 base::Bind(&DownloadFileCancel, base::Passed(&download_file_)));
1578 // Avoid attempting to reuse the intermediate file by clearing out 1644 // Avoid attempting to reuse the intermediate file by clearing out
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
1674 base::Bind(&ItemCompletingNetLogCallback, received_bytes_, &hash_)); 1740 base::Bind(&ItemCompletingNetLogCallback, received_bytes_, &hash_));
1675 break; 1741 break;
1676 1742
1677 case COMPLETE_INTERNAL: 1743 case COMPLETE_INTERNAL:
1678 bound_net_log_.AddEvent( 1744 bound_net_log_.AddEvent(
1679 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED, 1745 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED,
1680 base::Bind(&ItemFinishedNetLogCallback, auto_opened_)); 1746 base::Bind(&ItemFinishedNetLogCallback, auto_opened_));
1681 break; 1747 break;
1682 1748
1683 case INTERRUPTED_INTERNAL: 1749 case INTERRUPTED_INTERNAL:
1684 bound_net_log_.AddEvent( 1750 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED,
1685 net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED, 1751 base::Bind(&ItemInterruptedNetLogCallback,
1686 base::Bind(&ItemInterruptedNetLogCallback, last_reason_, 1752 last_reason_, received_bytes_));
1687 received_bytes_, &hash_state_));
1688 break; 1753 break;
1689 1754
1690 case RESUMING_INTERNAL: 1755 case RESUMING_INTERNAL:
1691 bound_net_log_.AddEvent( 1756 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED,
1692 net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED, 1757 base::Bind(&ItemResumingNetLogCallback, false,
1693 base::Bind(&ItemResumingNetLogCallback, false, last_reason_, 1758 last_reason_, received_bytes_));
1694 received_bytes_, &hash_state_));
1695 break; 1759 break;
1696 1760
1697 case CANCELLED_INTERNAL: 1761 case CANCELLED_INTERNAL:
1698 bound_net_log_.AddEvent( 1762 bound_net_log_.AddEvent(
1699 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED, 1763 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED,
1700 base::Bind(&ItemCanceledNetLogCallback, received_bytes_, 1764 base::Bind(&ItemCanceledNetLogCallback, received_bytes_));
1701 &hash_state_));
1702 break; 1765 break;
1703 1766
1704 case MAX_DOWNLOAD_INTERNAL_STATE: 1767 case MAX_DOWNLOAD_INTERNAL_STATE:
1705 NOTREACHED(); 1768 NOTREACHED();
1706 break; 1769 break;
1707 } 1770 }
1708 1771
1709 DVLOG(20) << " " << __FUNCTION__ << "()" 1772 DVLOG(20) << " " << __FUNCTION__ << "()"
1710 << " from:" << DebugDownloadStateString(old_state) 1773 << " from:" << DebugDownloadStateString(old_state)
1711 << " to:" << DebugDownloadStateString(state_) 1774 << " to:" << DebugDownloadStateString(state_)
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1792 1855
1793 // We are starting a new request. Shake off all pending operations. 1856 // We are starting a new request. Shake off all pending operations.
1794 DCHECK(!download_file_); 1857 DCHECK(!download_file_);
1795 weak_ptr_factory_.InvalidateWeakPtrs(); 1858 weak_ptr_factory_.InvalidateWeakPtrs();
1796 1859
1797 // Reset the appropriate state if restarting. 1860 // Reset the appropriate state if restarting.
1798 ResumeMode mode = GetResumeMode(); 1861 ResumeMode mode = GetResumeMode();
1799 if (mode == RESUME_MODE_IMMEDIATE_RESTART || 1862 if (mode == RESUME_MODE_IMMEDIATE_RESTART ||
1800 mode == RESUME_MODE_USER_RESTART) { 1863 mode == RESUME_MODE_USER_RESTART) {
1801 received_bytes_ = 0; 1864 received_bytes_ = 0;
1802 hash_state_ = ""; 1865 last_modified_time_.clear();
1803 last_modified_time_ = ""; 1866 etag_.clear();
1804 etag_ = ""; 1867 hash_.clear();
1868 hash_state_.reset();
1805 } 1869 }
1806 1870
1807 // Avoid using the WebContents even if it's still around. Resumption requests 1871 // Avoid using the WebContents even if it's still around. Resumption requests
1808 // are consistently routed through the no-renderer code paths so that the 1872 // are consistently routed through the no-renderer code paths so that the
1809 // request will not be dropped if the WebContents (and by extension, the 1873 // request will not be dropped if the WebContents (and by extension, the
1810 // associated renderer) goes away before a response is received. 1874 // associated renderer) goes away before a response is received.
1811 scoped_ptr<DownloadUrlParameters> download_params(new DownloadUrlParameters( 1875 scoped_ptr<DownloadUrlParameters> download_params(new DownloadUrlParameters(
1812 GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext())); 1876 GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext()));
1813 download_params->set_file_path(GetFullPath()); 1877 download_params->set_file_path(GetFullPath());
1814 download_params->set_offset(GetReceivedBytes()); 1878 download_params->set_offset(GetReceivedBytes());
1815 download_params->set_hash_state(GetHashState());
1816 download_params->set_last_modified(GetLastModifiedTime()); 1879 download_params->set_last_modified(GetLastModifiedTime());
1817 download_params->set_etag(GetETag()); 1880 download_params->set_etag(GetETag());
1881 download_params->set_prefix_hash(hash_);
1882 download_params->set_hash_state(std::move(hash_state_));
1818 1883
1819 TransitionTo(RESUMING_INTERNAL); 1884 TransitionTo(RESUMING_INTERNAL);
1820 delegate_->ResumeInterruptedDownload(std::move(download_params), GetId()); 1885 delegate_->ResumeInterruptedDownload(std::move(download_params), GetId());
1821 // Just in case we were interrupted while paused. 1886 // Just in case we were interrupted while paused.
1822 is_paused_ = false; 1887 is_paused_ = false;
1823 } 1888 }
1824 1889
1825 // static 1890 // static
1826 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState( 1891 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState(
1827 DownloadInternalState internal_state) { 1892 DownloadInternalState internal_state) {
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1992 case RESUME_MODE_USER_CONTINUE: 2057 case RESUME_MODE_USER_CONTINUE:
1993 return "USER_CONTINUE"; 2058 return "USER_CONTINUE";
1994 case RESUME_MODE_USER_RESTART: 2059 case RESUME_MODE_USER_RESTART:
1995 return "USER_RESTART"; 2060 return "USER_RESTART";
1996 } 2061 }
1997 NOTREACHED() << "Unknown resume mode " << mode; 2062 NOTREACHED() << "Unknown resume mode " << mode;
1998 return "unknown"; 2063 return "unknown";
1999 } 2064 }
2000 2065
2001 } // namespace content 2066 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698