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

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: Rebase on top of https://codereview.chromium.org/1781983002 since that's going in first. 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 22 matching lines...) Expand all
33 #include "base/logging.h" 33 #include "base/logging.h"
34 #include "base/metrics/histogram.h" 34 #include "base/metrics/histogram.h"
35 #include "base/stl_util.h" 35 #include "base/stl_util.h"
36 #include "base/strings/string_util.h" 36 #include "base/strings/string_util.h"
37 #include "base/strings/stringprintf.h" 37 #include "base/strings/stringprintf.h"
38 #include "base/strings/utf_string_conversions.h" 38 #include "base/strings/utf_string_conversions.h"
39 #include "content/browser/download/download_create_info.h" 39 #include "content/browser/download/download_create_info.h"
40 #include "content/browser/download/download_file.h" 40 #include "content/browser/download/download_file.h"
41 #include "content/browser/download/download_interrupt_reasons_impl.h" 41 #include "content/browser/download/download_interrupt_reasons_impl.h"
42 #include "content/browser/download/download_item_impl_delegate.h" 42 #include "content/browser/download/download_item_impl_delegate.h"
43 #include "content/browser/download/download_net_log_parameters.h"
43 #include "content/browser/download/download_request_handle.h" 44 #include "content/browser/download/download_request_handle.h"
44 #include "content/browser/download/download_stats.h" 45 #include "content/browser/download/download_stats.h"
45 #include "content/browser/renderer_host/render_view_host_impl.h" 46 #include "content/browser/renderer_host/render_view_host_impl.h"
46 #include "content/browser/web_contents/web_contents_impl.h" 47 #include "content/browser/web_contents/web_contents_impl.h"
47 #include "content/public/browser/browser_context.h" 48 #include "content/public/browser/browser_context.h"
48 #include "content/public/browser/browser_thread.h" 49 #include "content/public/browser/browser_thread.h"
49 #include "content/public/browser/content_browser_client.h" 50 #include "content/public/browser/content_browser_client.h"
50 #include "content/public/browser/download_danger_type.h" 51 #include "content/public/browser/download_danger_type.h"
51 #include "content/public/browser/download_interrupt_reasons.h" 52 #include "content/public/browser/download_interrupt_reasons.h"
52 #include "content/public/browser/download_url_parameters.h" 53 #include "content/public/browser/download_url_parameters.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 } 94 }
94 95
95 bool IsDownloadResumptionEnabled() { 96 bool IsDownloadResumptionEnabled() {
96 return base::FeatureList::IsEnabled(features::kDownloadResumption); 97 return base::FeatureList::IsEnabled(features::kDownloadResumption);
97 } 98 }
98 99
99 } // namespace 100 } // namespace
100 101
101 const uint32_t DownloadItem::kInvalidId = 0; 102 const uint32_t DownloadItem::kInvalidId = 0;
102 103
103 const char DownloadItem::kEmptyFileHash[] = "";
104
105 // The maximum number of attempts we will make to resume automatically. 104 // The maximum number of attempts we will make to resume automatically.
106 const int DownloadItemImpl::kMaxAutoResumeAttempts = 5; 105 const int DownloadItemImpl::kMaxAutoResumeAttempts = 5;
107 106
108 // Constructor for reading from the history service. 107 // Constructor for reading from the history service.
109 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, 108 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
110 const std::string& guid, 109 const std::string& guid,
111 uint32_t download_id, 110 uint32_t download_id,
112 const base::FilePath& current_path, 111 const base::FilePath& current_path,
113 const base::FilePath& target_path, 112 const base::FilePath& target_path,
114 const std::vector<GURL>& url_chain, 113 const std::vector<GURL>& url_chain,
115 const GURL& referrer_url, 114 const GURL& referrer_url,
116 const std::string& mime_type, 115 const std::string& mime_type,
117 const std::string& original_mime_type, 116 const std::string& original_mime_type,
118 const base::Time& start_time, 117 const base::Time& start_time,
119 const base::Time& end_time, 118 const base::Time& end_time,
120 const std::string& etag, 119 const std::string& etag,
121 const std::string& last_modified, 120 const std::string& last_modified,
122 int64_t received_bytes, 121 int64_t received_bytes,
123 int64_t total_bytes, 122 int64_t total_bytes,
123 const std::string& hash,
124 DownloadItem::DownloadState state, 124 DownloadItem::DownloadState state,
125 DownloadDangerType danger_type, 125 DownloadDangerType danger_type,
126 DownloadInterruptReason interrupt_reason, 126 DownloadInterruptReason interrupt_reason,
127 bool opened, 127 bool opened,
128 const net::BoundNetLog& bound_net_log) 128 const net::BoundNetLog& bound_net_log)
129 : guid_(base::ToUpperASCII(guid)), 129 : guid_(base::ToUpperASCII(guid)),
130 download_id_(download_id), 130 download_id_(download_id),
131 current_path_(current_path),
132 target_path_(target_path), 131 target_path_(target_path),
133 url_chain_(url_chain), 132 url_chain_(url_chain),
134 referrer_url_(referrer_url), 133 referrer_url_(referrer_url),
135 mime_type_(mime_type), 134 mime_type_(mime_type),
136 original_mime_type_(original_mime_type), 135 original_mime_type_(original_mime_type),
137 total_bytes_(total_bytes), 136 total_bytes_(total_bytes),
138 received_bytes_(received_bytes),
139 last_modified_time_(last_modified),
140 etag_(etag),
141 last_reason_(interrupt_reason), 137 last_reason_(interrupt_reason),
142 start_tick_(base::TimeTicks()), 138 start_tick_(base::TimeTicks()),
143 state_(ExternalToInternalState(state)), 139 state_(ExternalToInternalState(state)),
144 danger_type_(danger_type), 140 danger_type_(danger_type),
145 start_time_(start_time), 141 start_time_(start_time),
146 end_time_(end_time), 142 end_time_(end_time),
147 delegate_(delegate), 143 delegate_(delegate),
144 opened_(opened),
145 current_path_(current_path),
146 received_bytes_(received_bytes),
148 all_data_saved_(state == COMPLETE), 147 all_data_saved_(state == COMPLETE),
149 opened_(opened), 148 hash_(hash),
149 last_modified_time_(last_modified),
150 etag_(etag),
150 bound_net_log_(bound_net_log), 151 bound_net_log_(bound_net_log),
151 weak_ptr_factory_(this) { 152 weak_ptr_factory_(this) {
152 delegate_->Attach(); 153 delegate_->Attach();
153 DCHECK(state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL || 154 DCHECK(state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL ||
154 state_ == CANCELLED_INTERNAL); 155 state_ == CANCELLED_INTERNAL);
155 DCHECK(base::IsValidGUID(guid_)); 156 DCHECK(base::IsValidGUID(guid_));
156 Init(false /* not actively downloading */, SRC_HISTORY_IMPORT); 157 Init(false /* not actively downloading */, SRC_HISTORY_IMPORT);
157 } 158 }
158 159
159 // Constructing for a regular download: 160 // Constructing for a regular download:
(...skipping 12 matching lines...) Expand all
172 tab_referrer_url_(info.tab_referrer_url), 173 tab_referrer_url_(info.tab_referrer_url),
173 suggested_filename_(base::UTF16ToUTF8(info.save_info->suggested_name)), 174 suggested_filename_(base::UTF16ToUTF8(info.save_info->suggested_name)),
174 forced_file_path_(info.save_info->file_path), 175 forced_file_path_(info.save_info->file_path),
175 transition_type_(info.transition_type), 176 transition_type_(info.transition_type),
176 has_user_gesture_(info.has_user_gesture), 177 has_user_gesture_(info.has_user_gesture),
177 content_disposition_(info.content_disposition), 178 content_disposition_(info.content_disposition),
178 mime_type_(info.mime_type), 179 mime_type_(info.mime_type),
179 original_mime_type_(info.original_mime_type), 180 original_mime_type_(info.original_mime_type),
180 remote_address_(info.remote_address), 181 remote_address_(info.remote_address),
181 total_bytes_(info.total_bytes), 182 total_bytes_(info.total_bytes),
182 last_modified_time_(info.last_modified),
183 etag_(info.etag),
184 last_reason_(info.result), 183 last_reason_(info.result),
185 start_tick_(base::TimeTicks::Now()), 184 start_tick_(base::TimeTicks::Now()),
186 state_(INITIAL_INTERNAL), 185 state_(INITIAL_INTERNAL),
187 start_time_(info.start_time), 186 start_time_(info.start_time),
188 delegate_(delegate), 187 delegate_(delegate),
189 is_temporary_(!info.save_info->file_path.empty()), 188 is_temporary_(!info.save_info->file_path.empty()),
189 last_modified_time_(info.last_modified),
190 etag_(info.etag),
190 bound_net_log_(bound_net_log), 191 bound_net_log_(bound_net_log),
191 weak_ptr_factory_(this) { 192 weak_ptr_factory_(this) {
192 delegate_->Attach(); 193 delegate_->Attach();
193 Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD); 194 Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD);
194 195
195 // Link the event sources. 196 // Link the event sources.
196 bound_net_log_.AddEvent( 197 bound_net_log_.AddEvent(
197 net::NetLog::TYPE_DOWNLOAD_URL_REQUEST, 198 net::NetLog::TYPE_DOWNLOAD_URL_REQUEST,
198 info.request_bound_net_log.source().ToEventParametersCallback()); 199 info.request_bound_net_log.source().ToEventParametersCallback());
199 200
200 info.request_bound_net_log.AddEvent( 201 info.request_bound_net_log.AddEvent(
201 net::NetLog::TYPE_DOWNLOAD_STARTED, 202 net::NetLog::TYPE_DOWNLOAD_STARTED,
202 bound_net_log_.source().ToEventParametersCallback()); 203 bound_net_log_.source().ToEventParametersCallback());
203 } 204 }
204 205
205 // Constructing for the "Save Page As..." feature: 206 // Constructing for the "Save Page As..." feature:
206 DownloadItemImpl::DownloadItemImpl( 207 DownloadItemImpl::DownloadItemImpl(
207 DownloadItemImplDelegate* delegate, 208 DownloadItemImplDelegate* delegate,
208 uint32_t download_id, 209 uint32_t download_id,
209 const base::FilePath& path, 210 const base::FilePath& path,
210 const GURL& url, 211 const GURL& url,
211 const std::string& mime_type, 212 const std::string& mime_type,
212 scoped_ptr<DownloadRequestHandleInterface> request_handle, 213 scoped_ptr<DownloadRequestHandleInterface> request_handle,
213 const net::BoundNetLog& bound_net_log) 214 const net::BoundNetLog& bound_net_log)
214 : is_save_package_download_(true), 215 : is_save_package_download_(true),
215 request_handle_(std::move(request_handle)), 216 request_handle_(std::move(request_handle)),
216 guid_(base::ToUpperASCII(base::GenerateGUID())), 217 guid_(base::ToUpperASCII(base::GenerateGUID())),
217 download_id_(download_id), 218 download_id_(download_id),
218 current_path_(path),
219 target_path_(path), 219 target_path_(path),
220 url_chain_(1, url), 220 url_chain_(1, url),
221 mime_type_(mime_type), 221 mime_type_(mime_type),
222 original_mime_type_(mime_type), 222 original_mime_type_(mime_type),
223 start_tick_(base::TimeTicks::Now()), 223 start_tick_(base::TimeTicks::Now()),
224 state_(IN_PROGRESS_INTERNAL), 224 state_(IN_PROGRESS_INTERNAL),
225 start_time_(base::Time::Now()), 225 start_time_(base::Time::Now()),
226 delegate_(delegate), 226 delegate_(delegate),
227 current_path_(path),
227 bound_net_log_(bound_net_log), 228 bound_net_log_(bound_net_log),
228 weak_ptr_factory_(this) { 229 weak_ptr_factory_(this) {
229 delegate_->Attach(); 230 delegate_->Attach();
230 Init(true /* actively downloading */, SRC_SAVE_PAGE_AS); 231 Init(true /* actively downloading */, SRC_SAVE_PAGE_AS);
231 } 232 }
232 233
233 DownloadItemImpl::~DownloadItemImpl() { 234 DownloadItemImpl::~DownloadItemImpl() {
234 DCHECK_CURRENTLY_ON(BrowserThread::UI); 235 DCHECK_CURRENTLY_ON(BrowserThread::UI);
235 236
236 // Should always have been nuked before now, at worst in 237 // Should always have been nuked before now, at worst in
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 372
372 case MAX_DOWNLOAD_INTERNAL_STATE: 373 case MAX_DOWNLOAD_INTERNAL_STATE:
373 case TARGET_RESOLVED_INTERNAL: 374 case TARGET_RESOLVED_INTERNAL:
374 NOTREACHED(); 375 NOTREACHED();
375 } 376 }
376 } 377 }
377 378
378 void DownloadItemImpl::Cancel(bool user_cancel) { 379 void DownloadItemImpl::Cancel(bool user_cancel) {
379 DCHECK_CURRENTLY_ON(BrowserThread::UI); 380 DCHECK_CURRENTLY_ON(BrowserThread::UI);
380 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 381 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
381 Interrupt(user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED 382 InterruptAndDiscardPartialState(
382 : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN); 383 user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
384 : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN);
383 UpdateObservers(); 385 UpdateObservers();
384 } 386 }
385 387
386 void DownloadItemImpl::Remove() { 388 void DownloadItemImpl::Remove() {
387 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 389 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
388 DCHECK_CURRENTLY_ON(BrowserThread::UI); 390 DCHECK_CURRENTLY_ON(BrowserThread::UI);
389 391
390 delegate_->AssertStateConsistent(this); 392 delegate_->AssertStateConsistent(this);
391 Interrupt(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); 393 InterruptAndDiscardPartialState(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
392 UpdateObservers(); 394 UpdateObservers();
393 delegate_->AssertStateConsistent(this); 395 delegate_->AssertStateConsistent(this);
394 396
395 NotifyRemoved(); 397 NotifyRemoved();
396 delegate_->DownloadRemoved(this); 398 delegate_->DownloadRemoved(this);
397 // We have now been deleted. 399 // We have now been deleted.
398 } 400 }
399 401
400 void DownloadItemImpl::OpenDownload() { 402 void DownloadItemImpl::OpenDownload() {
401 DCHECK_CURRENTLY_ON(BrowserThread::UI); 403 DCHECK_CURRENTLY_ON(BrowserThread::UI);
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 } 596 }
595 597
596 DownloadItem::TargetDisposition DownloadItemImpl::GetTargetDisposition() const { 598 DownloadItem::TargetDisposition DownloadItemImpl::GetTargetDisposition() const {
597 return target_disposition_; 599 return target_disposition_;
598 } 600 }
599 601
600 const std::string& DownloadItemImpl::GetHash() const { 602 const std::string& DownloadItemImpl::GetHash() const {
601 return hash_; 603 return hash_;
602 } 604 }
603 605
604 const std::string& DownloadItemImpl::GetHashState() const {
605 return hash_state_;
606 }
607
608 bool DownloadItemImpl::GetFileExternallyRemoved() const { 606 bool DownloadItemImpl::GetFileExternallyRemoved() const {
609 return file_externally_removed_; 607 return file_externally_removed_;
610 } 608 }
611 609
612 void DownloadItemImpl::DeleteFile(const base::Callback<void(bool)>& callback) { 610 void DownloadItemImpl::DeleteFile(const base::Callback<void(bool)>& callback) {
613 DCHECK_CURRENTLY_ON(BrowserThread::UI); 611 DCHECK_CURRENTLY_ON(BrowserThread::UI);
614 if (GetState() != DownloadItem::COMPLETE) { 612 if (GetState() != DownloadItem::COMPLETE) {
615 // Pass a null WeakPtr so it doesn't call OnDownloadedFileRemoved. 613 // Pass a null WeakPtr so it doesn't call OnDownloadedFileRemoved.
616 BrowserThread::PostTask( 614 BrowserThread::PostTask(
617 BrowserThread::UI, FROM_HERE, 615 BrowserThread::UI, FROM_HERE,
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 ++iter; 787 ++iter;
790 for ( ; verbose && (iter != last); ++iter) { 788 for ( ; verbose && (iter != last); ++iter) {
791 url_list += " ->\n\t"; 789 url_list += " ->\n\t";
792 const GURL& next_url = *iter; 790 const GURL& next_url = *iter;
793 url_list += next_url.is_valid() ? next_url.spec() : "<invalid>"; 791 url_list += next_url.is_valid() ? next_url.spec() : "<invalid>";
794 } 792 }
795 } 793 }
796 794
797 if (verbose) { 795 if (verbose) {
798 description += base::StringPrintf( 796 description += base::StringPrintf(
799 " total = %" PRId64 797 " total = %" PRId64 " received = %" PRId64
800 " received = %" PRId64
801 " reason = %s" 798 " reason = %s"
802 " paused = %c" 799 " paused = %c"
803 " resume_mode = %s" 800 " resume_mode = %s"
804 " auto_resume_count = %d" 801 " auto_resume_count = %d"
805 " danger = %d" 802 " danger = %d"
806 " all_data_saved = %c" 803 " all_data_saved = %c"
807 " last_modified = '%s'" 804 " last_modified = '%s'"
808 " etag = '%s'" 805 " etag = '%s'"
809 " has_download_file = %s" 806 " has_download_file = %s"
810 " url_chain = \n\t\"%s\"\n\t" 807 " url_chain = \n\t\"%s\"\n\t"
811 " full_path = \"%" PRFilePath "\"\n\t" 808 " current_path = \"%" PRFilePath
809 "\"\n\t"
812 " target_path = \"%" PRFilePath "\"", 810 " target_path = \"%" PRFilePath "\"",
813 GetTotalBytes(), 811 GetTotalBytes(),
814 GetReceivedBytes(), 812 GetReceivedBytes(),
815 DownloadInterruptReasonToString(last_reason_).c_str(), 813 DownloadInterruptReasonToString(last_reason_).c_str(),
816 IsPaused() ? 'T' : 'F', 814 IsPaused() ? 'T' : 'F',
817 DebugResumeModeString(GetResumeMode()), 815 DebugResumeModeString(GetResumeMode()),
818 auto_resume_count_, 816 auto_resume_count_,
819 GetDangerType(), 817 GetDangerType(),
820 AllDataSaved() ? 'T' : 'F', 818 AllDataSaved() ? 'T' : 'F',
821 GetLastModifiedTime().c_str(), 819 GetLastModifiedTime().c_str(),
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 (auto_resume_count_ >= kMaxAutoResumeAttempts || is_paused_); 853 (auto_resume_count_ >= kMaxAutoResumeAttempts || is_paused_);
856 854
857 switch(last_reason_) { 855 switch(last_reason_) {
858 case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR: 856 case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
859 case DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT: 857 case DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
860 break; 858 break;
861 859
862 case DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE: 860 case DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
863 // The server disagreed with the file offset that we sent. 861 // The server disagreed with the file offset that we sent.
864 862
863 case DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH:
864 // The file on disk was found to not match the expected hash. Discard and
865 // start from beginning.
866
865 case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT: 867 case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:
866 // The [possibly persisted] file offset disagreed with the file on disk. 868 // The [possibly persisted] file offset disagreed with the file on disk.
867 869
868 // The intermediate stub is not usable and the server is resonding. Hence 870 // The intermediate stub is not usable and the server is responding. Hence
869 // retrying the request from the beginning is likely to work. 871 // retrying the request from the beginning is likely to work.
870 restart_required = true; 872 restart_required = true;
871 break; 873 break;
872 874
873 case DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED: 875 case DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
874 case DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED: 876 case DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
875 case DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN: 877 case DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
876 case DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED: 878 case DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
877 case DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE: 879 case DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE:
878 case DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN: 880 case DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 // HTTP_PRECONDITION_FAILED), then the download will automatically retried as 952 // HTTP_PRECONDITION_FAILED), then the download will automatically retried as
951 // a full request rather than a partial. Full restarts clobber validators. 953 // a full request rather than a partial. Full restarts clobber validators.
952 int origin_state = 0; 954 int origin_state = 0;
953 if (chain_iter != new_create_info.url_chain.end()) 955 if (chain_iter != new_create_info.url_chain.end())
954 origin_state |= ORIGIN_STATE_ON_RESUMPTION_ADDITIONAL_REDIRECTS; 956 origin_state |= ORIGIN_STATE_ON_RESUMPTION_ADDITIONAL_REDIRECTS;
955 if (etag_ != new_create_info.etag || 957 if (etag_ != new_create_info.etag ||
956 last_modified_time_ != new_create_info.last_modified) 958 last_modified_time_ != new_create_info.last_modified)
957 origin_state |= ORIGIN_STATE_ON_RESUMPTION_VALIDATORS_CHANGED; 959 origin_state |= ORIGIN_STATE_ON_RESUMPTION_VALIDATORS_CHANGED;
958 if (content_disposition_ != new_create_info.content_disposition) 960 if (content_disposition_ != new_create_info.content_disposition)
959 origin_state |= ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED; 961 origin_state |= ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED;
960 RecordOriginStateOnResumption(new_create_info.save_info->offset != 0, 962 RecordOriginStateOnResumption(received_bytes_ != 0, origin_state);
961 origin_state);
962 963
963 url_chain_.insert( 964 url_chain_.insert(
964 url_chain_.end(), chain_iter, new_create_info.url_chain.end()); 965 url_chain_.end(), chain_iter, new_create_info.url_chain.end());
965 etag_ = new_create_info.etag; 966 etag_ = new_create_info.etag;
966 last_modified_time_ = new_create_info.last_modified; 967 last_modified_time_ = new_create_info.last_modified;
967 content_disposition_ = new_create_info.content_disposition; 968 content_disposition_ = new_create_info.content_disposition;
968 969
969 // Don't update observers. This method is expected to be called just before a 970 // Don't update observers. This method is expected to be called just before a
970 // DownloadFile is created and Start() is called. The observers will be 971 // DownloadFile is created and Start() is called. The observers will be
971 // notified when the download transitions to the IN_PROGRESS state. 972 // notified when the download transitions to the IN_PROGRESS state.
(...skipping 15 matching lines...) Expand all
987 } 988 }
988 989
989 const net::BoundNetLog& DownloadItemImpl::GetBoundNetLog() const { 990 const net::BoundNetLog& DownloadItemImpl::GetBoundNetLog() const {
990 return bound_net_log_; 991 return bound_net_log_;
991 } 992 }
992 993
993 void DownloadItemImpl::SetTotalBytes(int64_t total_bytes) { 994 void DownloadItemImpl::SetTotalBytes(int64_t total_bytes) {
994 total_bytes_ = total_bytes; 995 total_bytes_ = total_bytes;
995 } 996 }
996 997
997 void DownloadItemImpl::OnAllDataSaved(const std::string& final_hash) { 998 void DownloadItemImpl::OnAllDataSaved(
999 int64_t total_bytes,
1000 scoped_ptr<crypto::SecureHash> hash_state) {
998 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1001 DCHECK_CURRENTLY_ON(BrowserThread::UI);
999 DCHECK(!all_data_saved_); 1002 DCHECK(!all_data_saved_);
1000 all_data_saved_ = true; 1003 all_data_saved_ = true;
1004 SetTotalBytes(total_bytes);
1005 UpdateProgress(total_bytes, 0);
1006 SetHashState(std::move(hash_state));
1007 hash_state_.reset(); // No need to retain hash_state_ since we are done with
1008 // the download and don't expect to receive any more
1009 // data.
1010
1001 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 1011 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
1002
1003 // Store final hash and null out intermediate serialized hash state.
1004 hash_ = final_hash;
1005 hash_state_ = "";
1006
1007 UpdateObservers(); 1012 UpdateObservers();
1008 } 1013 }
1009 1014
1010 void DownloadItemImpl::MarkAsComplete() { 1015 void DownloadItemImpl::MarkAsComplete() {
1011 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1016 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1012 1017
1013 DCHECK(all_data_saved_); 1018 DCHECK(all_data_saved_);
1014 end_time_ = base::Time::Now(); 1019 end_time_ = base::Time::Now();
1015 TransitionTo(COMPLETE_INTERNAL); 1020 TransitionTo(COMPLETE_INTERNAL);
1016 UpdateObservers(); 1021 UpdateObservers();
1017 } 1022 }
1018 1023
1019 void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far, 1024 void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far,
1020 int64_t bytes_per_sec, 1025 int64_t bytes_per_sec) {
1021 const std::string& hash_state) {
1022 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1026 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1023 // If the download is in any other state we don't expect any 1027 // If the download is in any other state we don't expect any
1024 // DownloadDestinationObserver callbacks. An interruption or a cancellation 1028 // DownloadDestinationObserver callbacks. An interruption or a cancellation
1025 // results in a call to ReleaseDownloadFile which invalidates the weak 1029 // results in a call to ReleaseDownloadFile which invalidates the weak
1026 // reference held by the DownloadFile and hence cuts off any pending 1030 // reference held by the DownloadFile and hence cuts off any pending
1027 // callbacks. 1031 // callbacks.
1028 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL); 1032 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
1033
1034 // There must be no pending destination_error_.
1035 DCHECK_EQ(destination_error_, DOWNLOAD_INTERRUPT_REASON_NONE);
1036
1029 DVLOG(20) << __FUNCTION__ << " so_far=" << bytes_so_far 1037 DVLOG(20) << __FUNCTION__ << " so_far=" << bytes_so_far
1030 << " per_sec=" << bytes_per_sec 1038 << " per_sec=" << bytes_per_sec
1031 << " download=" << DebugString(true); 1039 << " download=" << DebugString(true);
1032 1040
1033 bytes_per_sec_ = bytes_per_sec; 1041 UpdateProgress(bytes_so_far, bytes_per_sec);
1034 hash_state_ = hash_state;
1035 received_bytes_ = bytes_so_far;
1036
1037 // If we've received more data than we were expecting (bad server info?),
1038 // revert to 'unknown size mode'.
1039 if (received_bytes_ > total_bytes_)
1040 total_bytes_ = 0;
1041
1042 if (bound_net_log_.IsCapturing()) { 1042 if (bound_net_log_.IsCapturing()) {
1043 bound_net_log_.AddEvent( 1043 bound_net_log_.AddEvent(
1044 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED, 1044 net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED,
1045 net::NetLog::Int64Callback("bytes_so_far", received_bytes_)); 1045 net::NetLog::Int64Callback("bytes_so_far", received_bytes_));
1046 } 1046 }
1047 1047
1048 UpdateObservers(); 1048 UpdateObservers();
1049 } 1049 }
1050 1050
1051 void DownloadItemImpl::DestinationError(DownloadInterruptReason reason) { 1051 void DownloadItemImpl::DestinationError(
1052 DownloadInterruptReason reason,
1053 int64_t bytes_so_far,
1054 scoped_ptr<crypto::SecureHash> secure_hash) {
1052 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1055 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1053 // If the download is in any other state we don't expect any 1056 // If the download is in any other state we don't expect any
1054 // DownloadDestinationObserver callbacks. An interruption or a cancellation 1057 // DownloadDestinationObserver callbacks. An interruption or a cancellation
1055 // results in a call to ReleaseDownloadFile which invalidates the weak 1058 // results in a call to ReleaseDownloadFile which invalidates the weak
1056 // reference held by the DownloadFile and hence cuts off any pending 1059 // reference held by the DownloadFile and hence cuts off any pending
1057 // callbacks. 1060 // callbacks.
1058 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL); 1061 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
1059 DVLOG(20) << __FUNCTION__ 1062 DVLOG(20) << __FUNCTION__
1060 << "() reason:" << DownloadInterruptReasonToString(reason); 1063 << "() reason:" << DownloadInterruptReasonToString(reason);
1061 1064
1062 // Postpone recognition of this error until after file name determination 1065 // Postpone recognition of this error until after file name determination
1063 // has completed and the intermediate file has been renamed to simplify 1066 // has completed and the intermediate file has been renamed to simplify
1064 // resumption conditions. 1067 // resumption conditions.
1065 if (state_ == TARGET_PENDING_INTERNAL) { 1068 if (state_ == TARGET_PENDING_INTERNAL) {
1069 received_bytes_ = bytes_so_far;
1070 hash_state_ = std::move(secure_hash);
1071 hash_.clear();
1066 destination_error_ = reason; 1072 destination_error_ = reason;
1067 return; 1073 return;
1068 } 1074 }
1069 Interrupt(reason); 1075 InterruptWithPartialState(bytes_so_far, std::move(secure_hash), reason);
1070 UpdateObservers(); 1076 UpdateObservers();
1071 } 1077 }
1072 1078
1073 void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) { 1079 void DownloadItemImpl::DestinationCompleted(
1080 int64_t total_bytes,
1081 scoped_ptr<crypto::SecureHash> secure_hash) {
1074 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1082 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1075 // If the download is in any other state we don't expect any 1083 // If the download is in any other state we don't expect any
1076 // DownloadDestinationObserver callbacks. An interruption or a cancellation 1084 // DownloadDestinationObserver callbacks. An interruption or a cancellation
1077 // results in a call to ReleaseDownloadFile which invalidates the weak 1085 // results in a call to ReleaseDownloadFile which invalidates the weak
1078 // reference held by the DownloadFile and hence cuts off any pending 1086 // reference held by the DownloadFile and hence cuts off any pending
1079 // callbacks. 1087 // callbacks.
1080 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL); 1088 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
1081 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 1089 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
1082 1090
1083 OnAllDataSaved(final_hash); 1091 OnAllDataSaved(total_bytes, std::move(secure_hash));
1084 MaybeCompleteDownload(); 1092 MaybeCompleteDownload();
1085 } 1093 }
1086 1094
1087 // **** Download progression cascade 1095 // **** Download progression cascade
1088 1096
1089 void DownloadItemImpl::Init(bool active, 1097 void DownloadItemImpl::Init(bool active,
1090 DownloadType download_type) { 1098 DownloadType download_type) {
1091 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1099 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1092 1100
1093 if (active) 1101 if (active)
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 DCHECK(state_ == INITIAL_INTERNAL || state_ == RESUMING_INTERNAL); 1160 DCHECK(state_ == INITIAL_INTERNAL || state_ == RESUMING_INTERNAL);
1153 1161
1154 // If the state_ is INITIAL_INTERNAL, then the target path must be empty. 1162 // If the state_ is INITIAL_INTERNAL, then the target path must be empty.
1155 DCHECK(state_ != INITIAL_INTERNAL || target_path_.empty()); 1163 DCHECK(state_ != INITIAL_INTERNAL || target_path_.empty());
1156 1164
1157 // If a resumption attempted failed, or if the download was DOA, then the 1165 // If a resumption attempted failed, or if the download was DOA, then the
1158 // download should go back to being interrupted. 1166 // download should go back to being interrupted.
1159 if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) { 1167 if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) {
1160 DCHECK(!download_file_.get()); 1168 DCHECK(!download_file_.get());
1161 1169
1170 // Download requests that are interrupted by Start() should result in a
1171 // DownloadCreateInfo with an intact DownloadSaveInfo.
1172 DCHECK(new_create_info.save_info);
1173
1174 int64_t offset = new_create_info.save_info->offset;
1175 scoped_ptr<crypto::SecureHash> hash_state =
1176 make_scoped_ptr(new_create_info.save_info->hash_state
1177 ? new_create_info.save_info->hash_state->Clone()
1178 : nullptr);
1179
1162 // Interrupted downloads also need a target path. 1180 // Interrupted downloads also need a target path.
1163 if (target_path_.empty()) { 1181 if (target_path_.empty()) {
1182 received_bytes_ = offset;
1183 hash_state_ = std::move(hash_state);
1184 hash_.clear();
1185 destination_error_ = new_create_info.result;
1164 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL); 1186 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
1165 destination_error_ = new_create_info.result;
1166 DetermineDownloadTarget(); 1187 DetermineDownloadTarget();
1167 return; 1188 return;
1168 } 1189 }
1169 1190
1170 // Otherwise, this was a resumption attempt which ended with an 1191 // Otherwise, this was a resumption attempt which ended with an
1171 // interruption. Continue with current target path. 1192 // interruption. Continue with current target path.
1172 TransitionTo(TARGET_RESOLVED_INTERNAL); 1193 TransitionTo(TARGET_RESOLVED_INTERNAL);
1173 Interrupt(new_create_info.result); 1194 InterruptWithPartialState(
1195 offset, std::move(hash_state), new_create_info.result);
1174 UpdateObservers(); 1196 UpdateObservers();
1175 return; 1197 return;
1176 } 1198 }
1177 1199
1178 // Successful download start. 1200 // Successful download start.
1179 DCHECK(download_file_.get()); 1201 DCHECK(download_file_.get());
1180 DCHECK(request_handle_.get()); 1202 DCHECK(request_handle_.get());
1181 1203
1182 if (state_ == RESUMING_INTERNAL) 1204 if (state_ == RESUMING_INTERNAL)
1183 UpdateValidatorsOnResumption(new_create_info); 1205 UpdateValidatorsOnResumption(new_create_info);
1184 1206
1185 TransitionTo(TARGET_PENDING_INTERNAL); 1207 TransitionTo(TARGET_PENDING_INTERNAL);
1186 1208
1187 BrowserThread::PostTask( 1209 BrowserThread::PostTask(
1188 BrowserThread::FILE, FROM_HERE, 1210 BrowserThread::FILE, FROM_HERE,
1189 base::Bind(&DownloadFile::Initialize, 1211 base::Bind(&DownloadFile::Initialize,
1190 // Safe because we control download file lifetime. 1212 // Safe because we control download file lifetime.
1191 base::Unretained(download_file_.get()), 1213 base::Unretained(download_file_.get()),
1192 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, 1214 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
1193 weak_ptr_factory_.GetWeakPtr()))); 1215 weak_ptr_factory_.GetWeakPtr())));
1194 } 1216 }
1195 1217
1196 void DownloadItemImpl::OnDownloadFileInitialized( 1218 void DownloadItemImpl::OnDownloadFileInitialized(
1197 DownloadInterruptReason result) { 1219 DownloadInterruptReason result) {
1198 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1220 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1199 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL); 1221 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL);
1200 DVLOG(20) << __FUNCTION__ 1222 DVLOG(20) << __FUNCTION__
1201 << "() result:" << DownloadInterruptReasonToString(result); 1223 << "() result:" << DownloadInterruptReasonToString(result);
1202 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { 1224 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
1203 // Whoops. That didn't work. Proceed as an interrupted download. 1225 // Whoops. That didn't work. Proceed as an interrupted download, but reset
1226 // the partial state. Currently, the partial stub cannot be recovered if the
1227 // download file initialization fails.
1228 received_bytes_ = 0;
1229 hash_state_.reset();
1230 hash_.clear();
1204 destination_error_ = result; 1231 destination_error_ = result;
1205 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL); 1232 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
1206 } 1233 }
1207 1234
1208 DetermineDownloadTarget(); 1235 DetermineDownloadTarget();
1209 } 1236 }
1210 1237
1211 void DownloadItemImpl::DetermineDownloadTarget() { 1238 void DownloadItemImpl::DetermineDownloadTarget() {
1212 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1239 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1213 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true); 1240 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true);
(...skipping 24 matching lines...) Expand all
1238 << " disposition:" << disposition << " danger_type:" << danger_type 1265 << " disposition:" << disposition << " danger_type:" << danger_type
1239 << " this:" << DebugString(true); 1266 << " this:" << DebugString(true);
1240 1267
1241 target_path_ = target_path; 1268 target_path_ = target_path;
1242 target_disposition_ = disposition; 1269 target_disposition_ = disposition;
1243 SetDangerType(danger_type); 1270 SetDangerType(danger_type);
1244 1271
1245 // This was an interrupted download that was looking for a filename. Now that 1272 // This was an interrupted download that was looking for a filename. Now that
1246 // it has one, transition to interrupted. 1273 // it has one, transition to interrupted.
1247 if (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL) { 1274 if (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL) {
1248 Interrupt(destination_error_); 1275 InterruptWithPartialState(
1276 received_bytes_, std::move(hash_state_), destination_error_);
1249 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE; 1277 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
1250 UpdateObservers(); 1278 UpdateObservers();
1251 return; 1279 return;
1252 } 1280 }
1253 1281
1254 // We want the intermediate and target paths to refer to the same directory so 1282 // We want the intermediate and target paths to refer to the same directory so
1255 // that they are both on the same device and subject to same 1283 // that they are both on the same device and subject to same
1256 // space/permission/availability constraints. 1284 // space/permission/availability constraints.
1257 DCHECK(intermediate_path.DirName() == target_path.DirName()); 1285 DCHECK(intermediate_path.DirName() == target_path.DirName());
1258 1286
(...skipping 27 matching lines...) Expand all
1286 base::Unretained(download_file_.get()), 1314 base::Unretained(download_file_.get()),
1287 intermediate_path, callback)); 1315 intermediate_path, callback));
1288 } 1316 }
1289 1317
1290 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( 1318 void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
1291 DownloadInterruptReason reason, 1319 DownloadInterruptReason reason,
1292 const base::FilePath& full_path) { 1320 const base::FilePath& full_path) {
1293 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1321 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1294 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL); 1322 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL);
1295 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 1323 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
1324
1296 TransitionTo(TARGET_RESOLVED_INTERNAL); 1325 TransitionTo(TARGET_RESOLVED_INTERNAL);
1297 1326
1327 // If the intermediate rename fails while there's also a destination_error_,
1328 // then the former is considered the critical error since it requires
1329 // discarding the partial state.
1330 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1331 // TODO(asanka): Even though the rename failed, it may still be possible to
1332 // recover the partial state from the 'before' name.
1333 InterruptAndDiscardPartialState(reason);
1334 UpdateObservers();
1335 return;
1336 }
1337
1298 if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) { 1338 if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) {
1299 // Process destination error. If both |reason| and |destination_error_| 1339 SetFullPath(full_path);
1300 // refer to actual errors, we want to use the |destination_error_| as the 1340 InterruptWithPartialState(
1301 // argument to the Interrupt() routine, as it happened first. 1341 received_bytes_, std::move(hash_state_), destination_error_);
1302 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE)
1303 SetFullPath(full_path);
1304 Interrupt(destination_error_);
1305 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE; 1342 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
1306 UpdateObservers(); 1343 UpdateObservers();
1307 } else if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1344 return;
1308 Interrupt(reason);
1309 // All file errors result in file deletion above; no need to cleanup. The
1310 // current_path_ should be empty. Resuming this download will force a
1311 // restart and a re-doing of filename determination.
1312 DCHECK(current_path_.empty());
1313 UpdateObservers();
1314 } else {
1315 SetFullPath(full_path);
1316 TransitionTo(IN_PROGRESS_INTERNAL);
1317 // TODO(asanka): Calling UpdateObservers() prior to MaybeCompleteDownload()
1318 // is not safe. The download could be in an underminate state after invoking
1319 // observers. http://crbug.com/586610
1320 UpdateObservers();
1321 MaybeCompleteDownload();
1322 } 1345 }
1346
1347 SetFullPath(full_path);
1348 TransitionTo(IN_PROGRESS_INTERNAL);
1349 // TODO(asanka): Calling UpdateObservers() prior to MaybeCompleteDownload() is
1350 // not safe. The download could be in an underminate state after invoking
1351 // observers. http://crbug.com/586610
1352 UpdateObservers();
1353 MaybeCompleteDownload();
1323 } 1354 }
1324 1355
1325 // When SavePackage downloads MHTML to GData (see 1356 // When SavePackage downloads MHTML to GData (see
1326 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it 1357 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it
1327 // does for non-SavePackage downloads, but SavePackage downloads never satisfy 1358 // does for non-SavePackage downloads, but SavePackage downloads never satisfy
1328 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls 1359 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls
1329 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage 1360 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage
1330 // notices that the upload has completed and runs its normal Finish() pathway. 1361 // notices that the upload has completed and runs its normal Finish() pathway.
1331 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes 1362 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes
1332 // downloads. SavePackage always uses its own Finish() to mark downloads 1363 // downloads. SavePackage always uses its own Finish() to mark downloads
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1372 return; 1403 return;
1373 } 1404 }
1374 1405
1375 DCHECK(download_file_.get()); 1406 DCHECK(download_file_.get());
1376 // Unilaterally rename; even if it already has the right name, 1407 // Unilaterally rename; even if it already has the right name,
1377 // we need theannotation. 1408 // we need theannotation.
1378 DownloadFile::RenameCompletionCallback callback = 1409 DownloadFile::RenameCompletionCallback callback =
1379 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, 1410 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
1380 weak_ptr_factory_.GetWeakPtr()); 1411 weak_ptr_factory_.GetWeakPtr());
1381 BrowserThread::PostTask( 1412 BrowserThread::PostTask(
1382 BrowserThread::FILE, FROM_HERE, 1413 BrowserThread::FILE,
1414 FROM_HERE,
1383 base::Bind(&DownloadFile::RenameAndAnnotate, 1415 base::Bind(&DownloadFile::RenameAndAnnotate,
1384 base::Unretained(download_file_.get()), 1416 base::Unretained(download_file_.get()),
1385 GetTargetFilePath(), callback)); 1417 GetTargetFilePath(),
1418 delegate_->GetApplicationClientIdForFileScanning(),
1419 GetURL(),
1420 GetReferrerUrl(),
1421 callback));
1386 } 1422 }
1387 1423
1388 void DownloadItemImpl::OnDownloadRenamedToFinalName( 1424 void DownloadItemImpl::OnDownloadRenamedToFinalName(
1389 DownloadInterruptReason reason, 1425 DownloadInterruptReason reason,
1390 const base::FilePath& full_path) { 1426 const base::FilePath& full_path) {
1391 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1427 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1392 DCHECK(!is_save_package_download_); 1428 DCHECK(!is_save_package_download_);
1393 1429
1394 // If a cancel or interrupt hit, we'll cancel the DownloadFile, which 1430 // If a cancel or interrupt hit, we'll cancel the DownloadFile, which
1395 // will result in deleting the file on the file thread. So we don't 1431 // will result in deleting the file on the file thread. So we don't
1396 // care about the name having been changed. 1432 // care about the name having been changed.
1397 if (state_ != IN_PROGRESS_INTERNAL) 1433 if (state_ != IN_PROGRESS_INTERNAL)
1398 return; 1434 return;
1399 1435
1400 DVLOG(20) << __FUNCTION__ << "()" 1436 DVLOG(20) << __FUNCTION__ << "()"
1401 << " full_path = \"" << full_path.value() << "\"" 1437 << " full_path = \"" << full_path.value() << "\""
1402 << " " << DebugString(false); 1438 << " " << DebugString(false);
1403 1439
1404 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1440 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1405 Interrupt(reason); 1441 // Failure to perform the final rename is considered fatal. TODO(asanka): It
1406 1442 // may not be, in which case we should figure out whether we can recover the
1407 // All file errors should have resulted in in file deletion above. On 1443 // state.
1408 // resumption we will need to re-do filename determination. 1444 InterruptAndDiscardPartialState(reason);
1409 DCHECK(current_path_.empty());
1410 UpdateObservers(); 1445 UpdateObservers();
1411 return; 1446 return;
1412 } 1447 }
1413 1448
1414 DCHECK(target_path_ == full_path); 1449 DCHECK(target_path_ == full_path);
1415 1450
1416 if (full_path != current_path_) { 1451 if (full_path != current_path_) {
1417 // full_path is now the current and target file path. 1452 // full_path is now the current and target file path.
1418 DCHECK(!full_path.empty()); 1453 DCHECK(!full_path.empty());
1419 SetFullPath(full_path); 1454 SetFullPath(full_path);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 if (!IsTemporary()) 1502 if (!IsTemporary())
1468 OpenDownload(); 1503 OpenDownload();
1469 1504
1470 auto_opened_ = true; 1505 auto_opened_ = true;
1471 } 1506 }
1472 UpdateObservers(); 1507 UpdateObservers();
1473 } 1508 }
1474 1509
1475 // **** End of Download progression cascade 1510 // **** End of Download progression cascade
1476 1511
1477 // An error occurred somewhere. 1512 void DownloadItemImpl::InterruptAndDiscardPartialState(
1478 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { 1513 DownloadInterruptReason reason) {
1514 InterruptWithPartialState(0, scoped_ptr<crypto::SecureHash>(), reason);
1515 }
1516
1517 void DownloadItemImpl::InterruptWithPartialState(
1518 int64_t bytes_so_far,
1519 scoped_ptr<crypto::SecureHash> hash_state,
1520 DownloadInterruptReason reason) {
1479 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1521 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1480 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason); 1522 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason);
1481 DVLOG(20) << __FUNCTION__ 1523 DVLOG(20) << __FUNCTION__
1482 << "() reason:" << DownloadInterruptReasonToString(reason) 1524 << "() reason:" << DownloadInterruptReasonToString(reason)
1525 << " bytes_so_far:" << bytes_so_far
1526 << " hash_state:" << (hash_state ? "Valid" : "Invalid")
1483 << " this=" << DebugString(true); 1527 << " this=" << DebugString(true);
1484 1528
1485 // Somewhat counter-intuitively, it is possible for us to receive an 1529 // Somewhat counter-intuitively, it is possible for us to receive an
1486 // interrupt after we've already been interrupted. The generation of 1530 // interrupt after we've already been interrupted. The generation of
1487 // interrupts from the file thread Renames and the generation of 1531 // interrupts from the file thread Renames and the generation of
1488 // interrupts from disk writes go through two different mechanisms (driven 1532 // interrupts from disk writes go through two different mechanisms (driven
1489 // by rename requests from UI thread and by write requests from IO thread, 1533 // by rename requests from UI thread and by write requests from IO thread,
1490 // respectively), and since we choose not to keep state on the File thread, 1534 // respectively), and since we choose not to keep state on the File thread,
1491 // this is the place where the races collide. It's also possible for 1535 // this is the place where the races collide. It's also possible for
1492 // interrupts to race with cancels. 1536 // interrupts to race with cancels.
(...skipping 20 matching lines...) Expand all
1513 1557
1514 if (download_file_) { 1558 if (download_file_) {
1515 ResumeMode resume_mode = GetResumeMode(); 1559 ResumeMode resume_mode = GetResumeMode();
1516 ReleaseDownloadFile(resume_mode != RESUME_MODE_IMMEDIATE_CONTINUE && 1560 ReleaseDownloadFile(resume_mode != RESUME_MODE_IMMEDIATE_CONTINUE &&
1517 resume_mode != RESUME_MODE_USER_CONTINUE); 1561 resume_mode != RESUME_MODE_USER_CONTINUE);
1518 } 1562 }
1519 break; 1563 break;
1520 1564
1521 case RESUMING_INTERNAL: 1565 case RESUMING_INTERNAL:
1522 case INTERRUPTED_INTERNAL: 1566 case INTERRUPTED_INTERNAL:
1567 DCHECK(!download_file_);
1523 // The first non-cancel interrupt reason wins in cases where multiple 1568 // The first non-cancel interrupt reason wins in cases where multiple
1524 // things go wrong. 1569 // things go wrong.
1525 if (reason != DOWNLOAD_INTERRUPT_REASON_USER_CANCELED && 1570 if (reason != DOWNLOAD_INTERRUPT_REASON_USER_CANCELED &&
1526 reason != DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) 1571 reason != DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN)
1527 return; 1572 return;
1528 1573
1529 last_reason_ = reason; 1574 last_reason_ = reason;
1530 if (!current_path_.empty()) { 1575 if (!current_path_.empty()) {
1531 // There is no download file and this is transitioning from INTERRUPTED 1576 // There is no download file and this is transitioning from INTERRUPTED
1532 // to CANCELLED. The intermediate file is no longer usable, and should 1577 // to CANCELLED. The intermediate file is no longer usable, and should
(...skipping 11 matching lines...) Expand all
1544 // through another round of downloading when we resume. There's a potential 1589 // through another round of downloading when we resume. There's a potential
1545 // problem here in the abstract, as if we did download all the data and then 1590 // problem here in the abstract, as if we did download all the data and then
1546 // run into a continuable error, on resumption we won't download any more 1591 // run into a continuable error, on resumption we won't download any more
1547 // data. However, a) there are currently no continuable errors that can occur 1592 // data. However, a) there are currently no continuable errors that can occur
1548 // after we download all the data, and b) if there were, that would probably 1593 // after we download all the data, and b) if there were, that would probably
1549 // simply result in a null range request, which would generate a 1594 // simply result in a null range request, which would generate a
1550 // DestinationCompleted() notification from the DownloadFile, which would 1595 // DestinationCompleted() notification from the DownloadFile, which would
1551 // behave properly with setting all_data_saved_ to false here. 1596 // behave properly with setting all_data_saved_ to false here.
1552 all_data_saved_ = false; 1597 all_data_saved_ = false;
1553 1598
1599 if (current_path_.empty()) {
1600 hash_state_.reset();
1601 hash_.clear();
1602 received_bytes_ = 0;
1603 } else {
1604 UpdateProgress(bytes_so_far, 0);
1605 SetHashState(std::move(hash_state));
1606 }
1607
1554 if (request_handle_) 1608 if (request_handle_)
1555 request_handle_->CancelRequest(); 1609 request_handle_->CancelRequest();
1556 1610
1557 if (reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED || 1611 if (reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED ||
1558 reason == DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) { 1612 reason == DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) {
1559 if (IsDangerous()) { 1613 if (IsDangerous()) {
1560 RecordDangerousDownloadDiscard( 1614 RecordDangerousDownloadDiscard(
1561 reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED 1615 reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
1562 ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION 1616 ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION
1563 : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN, 1617 : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN,
1564 GetDangerType(), GetTargetFilePath()); 1618 GetDangerType(), GetTargetFilePath());
1565 } 1619 }
1566 1620
1567 RecordDownloadCount(CANCELLED_COUNT); 1621 RecordDownloadCount(CANCELLED_COUNT);
1568 TransitionTo(CANCELLED_INTERNAL); 1622 TransitionTo(CANCELLED_INTERNAL);
1569 return; 1623 return;
1570 } 1624 }
1571 1625
1572 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_); 1626 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_);
1573 if (!GetWebContents()) 1627 if (!GetWebContents())
1574 RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS); 1628 RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS);
1575 1629
1576 TransitionTo(INTERRUPTED_INTERNAL); 1630 TransitionTo(INTERRUPTED_INTERNAL);
1577 AutoResumeIfValid(); 1631 AutoResumeIfValid();
1578 } 1632 }
1579 1633
1634 void DownloadItemImpl::UpdateProgress(int64_t bytes_so_far,
1635 int64_t bytes_per_sec) {
1636 received_bytes_ = bytes_so_far;
1637 bytes_per_sec_ = bytes_per_sec;
1638
1639 // If we've received more data than we were expecting (bad server info?),
1640 // revert to 'unknown size mode'.
1641 if (received_bytes_ > total_bytes_)
1642 total_bytes_ = 0;
1643 }
1644
1645 void DownloadItemImpl::SetHashState(scoped_ptr<crypto::SecureHash> hash_state) {
1646 hash_state_ = std::move(hash_state);
1647 if (!hash_state_) {
1648 hash_.clear();
1649 return;
1650 }
1651
1652 scoped_ptr<crypto::SecureHash> clone_of_hash_state(hash_state_->Clone());
1653 std::vector<char> hash_value(clone_of_hash_state->GetHashLength());
1654 clone_of_hash_state->Finish(&hash_value.front(), hash_value.size());
1655 hash_.assign(hash_value.begin(), hash_value.end());
1656 }
1657
1580 void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) { 1658 void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) {
1581 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1659 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1582 DVLOG(20) << __FUNCTION__ << "() destroy_file:" << destroy_file; 1660 DVLOG(20) << __FUNCTION__ << "() destroy_file:" << destroy_file;
1583 1661
1584 if (destroy_file) { 1662 if (destroy_file) {
1585 BrowserThread::PostTask( 1663 BrowserThread::PostTask(
1586 BrowserThread::FILE, FROM_HERE, 1664 BrowserThread::FILE, FROM_HERE,
1587 // Will be deleted at end of task execution. 1665 // Will be deleted at end of task execution.
1588 base::Bind(&DownloadFileCancel, base::Passed(&download_file_))); 1666 base::Bind(&DownloadFileCancel, base::Passed(&download_file_)));
1589 // Avoid attempting to reuse the intermediate file by clearing out 1667 // Avoid attempting to reuse the intermediate file by clearing out
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1687 1765
1688 case COMPLETE_INTERNAL: 1766 case COMPLETE_INTERNAL:
1689 bound_net_log_.AddEvent( 1767 bound_net_log_.AddEvent(
1690 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED, 1768 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED,
1691 base::Bind(&ItemFinishedNetLogCallback, auto_opened_)); 1769 base::Bind(&ItemFinishedNetLogCallback, auto_opened_));
1692 break; 1770 break;
1693 1771
1694 case INTERRUPTED_INTERNAL: 1772 case INTERRUPTED_INTERNAL:
1695 bound_net_log_.AddEvent( 1773 bound_net_log_.AddEvent(
1696 net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED, 1774 net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED,
1697 base::Bind(&ItemInterruptedNetLogCallback, last_reason_, 1775 base::Bind(
1698 received_bytes_, &hash_state_)); 1776 &ItemInterruptedNetLogCallback, last_reason_, received_bytes_));
1699 break; 1777 break;
1700 1778
1701 case RESUMING_INTERNAL: 1779 case RESUMING_INTERNAL:
1702 bound_net_log_.AddEvent( 1780 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED,
1703 net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED, 1781 base::Bind(&ItemResumingNetLogCallback,
1704 base::Bind(&ItemResumingNetLogCallback, false, last_reason_, 1782 false,
1705 received_bytes_, &hash_state_)); 1783 last_reason_,
1784 received_bytes_));
1706 break; 1785 break;
1707 1786
1708 case CANCELLED_INTERNAL: 1787 case CANCELLED_INTERNAL:
1709 bound_net_log_.AddEvent( 1788 bound_net_log_.AddEvent(
1710 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED, 1789 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED,
1711 base::Bind(&ItemCanceledNetLogCallback, received_bytes_, 1790 base::Bind(&ItemCanceledNetLogCallback, received_bytes_));
1712 &hash_state_));
1713 break; 1791 break;
1714 1792
1715 case MAX_DOWNLOAD_INTERNAL_STATE: 1793 case MAX_DOWNLOAD_INTERNAL_STATE:
1716 NOTREACHED(); 1794 NOTREACHED();
1717 break; 1795 break;
1718 } 1796 }
1719 1797
1720 DVLOG(20) << " " << __FUNCTION__ << "()" 1798 DVLOG(20) << " " << __FUNCTION__ << "()"
1721 << " from:" << DebugDownloadStateString(old_state) 1799 << " from:" << DebugDownloadStateString(old_state)
1722 << " to:" << DebugDownloadStateString(state_) 1800 << " to:" << DebugDownloadStateString(state_)
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1803 1881
1804 // We are starting a new request. Shake off all pending operations. 1882 // We are starting a new request. Shake off all pending operations.
1805 DCHECK(!download_file_); 1883 DCHECK(!download_file_);
1806 weak_ptr_factory_.InvalidateWeakPtrs(); 1884 weak_ptr_factory_.InvalidateWeakPtrs();
1807 1885
1808 // Reset the appropriate state if restarting. 1886 // Reset the appropriate state if restarting.
1809 ResumeMode mode = GetResumeMode(); 1887 ResumeMode mode = GetResumeMode();
1810 if (mode == RESUME_MODE_IMMEDIATE_RESTART || 1888 if (mode == RESUME_MODE_IMMEDIATE_RESTART ||
1811 mode == RESUME_MODE_USER_RESTART) { 1889 mode == RESUME_MODE_USER_RESTART) {
1812 received_bytes_ = 0; 1890 received_bytes_ = 0;
1813 hash_state_ = ""; 1891 last_modified_time_.clear();
1814 last_modified_time_ = ""; 1892 etag_.clear();
1815 etag_ = ""; 1893 hash_.clear();
1894 hash_state_.reset();
1816 } 1895 }
1817 1896
1818 // Avoid using the WebContents even if it's still around. Resumption requests 1897 // Avoid using the WebContents even if it's still around. Resumption requests
1819 // are consistently routed through the no-renderer code paths so that the 1898 // are consistently routed through the no-renderer code paths so that the
1820 // request will not be dropped if the WebContents (and by extension, the 1899 // request will not be dropped if the WebContents (and by extension, the
1821 // associated renderer) goes away before a response is received. 1900 // associated renderer) goes away before a response is received.
1822 scoped_ptr<DownloadUrlParameters> download_params(new DownloadUrlParameters( 1901 scoped_ptr<DownloadUrlParameters> download_params(new DownloadUrlParameters(
1823 GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext())); 1902 GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext()));
1824 download_params->set_file_path(GetFullPath()); 1903 download_params->set_file_path(GetFullPath());
1825 download_params->set_offset(GetReceivedBytes()); 1904 download_params->set_offset(GetReceivedBytes());
1826 download_params->set_hash_state(GetHashState());
1827 download_params->set_last_modified(GetLastModifiedTime()); 1905 download_params->set_last_modified(GetLastModifiedTime());
1828 download_params->set_etag(GetETag()); 1906 download_params->set_etag(GetETag());
1907 download_params->set_hash_of_partial_file(hash_);
1908 download_params->set_hash_state(std::move(hash_state_));
1829 1909
1830 TransitionTo(RESUMING_INTERNAL); 1910 TransitionTo(RESUMING_INTERNAL);
1831 delegate_->ResumeInterruptedDownload(std::move(download_params), GetId()); 1911 delegate_->ResumeInterruptedDownload(std::move(download_params), GetId());
1832 // Just in case we were interrupted while paused. 1912 // Just in case we were interrupted while paused.
1833 is_paused_ = false; 1913 is_paused_ = false;
1834 } 1914 }
1835 1915
1836 // static 1916 // static
1837 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState( 1917 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState(
1838 DownloadInternalState internal_state) { 1918 DownloadInternalState internal_state) {
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
2003 case RESUME_MODE_USER_CONTINUE: 2083 case RESUME_MODE_USER_CONTINUE:
2004 return "USER_CONTINUE"; 2084 return "USER_CONTINUE";
2005 case RESUME_MODE_USER_RESTART: 2085 case RESUME_MODE_USER_RESTART:
2006 return "USER_RESTART"; 2086 return "USER_RESTART";
2007 } 2087 }
2008 NOTREACHED() << "Unknown resume mode " << mode; 2088 NOTREACHED() << "Unknown resume mode " << mode;
2009 return "unknown"; 2089 return "unknown";
2010 } 2090 }
2011 2091
2012 } // namespace content 2092 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/download_item_impl.h ('k') | content/browser/download/download_item_impl_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698