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

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: Try to appease MSVC 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);
1055 destination_error_ = reason; 1052 destination_error_ = reason;
1056 return; 1053 return;
1057 } 1054 }
1058 Interrupt(reason); 1055 InterruptWithPartialState(bytes_so_far, std::move(secure_hash), reason);
1059 UpdateObservers(); 1056 UpdateObservers();
1060 } 1057 }
1061 1058
1062 void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) { 1059 void DownloadItemImpl::DestinationCompleted(
1060 int64_t total_bytes,
1061 scoped_ptr<crypto::SecureHash> secure_hash) {
1063 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1062 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1064 // If the download is in any other state we don't expect any 1063 // If the download is in any other state we don't expect any
1065 // DownloadDestinationObserver callbacks. An interruption or a cancellation 1064 // DownloadDestinationObserver callbacks. An interruption or a cancellation
1066 // results in a call to ReleaseDownloadFile which invalidates the weak 1065 // results in a call to ReleaseDownloadFile which invalidates the weak
1067 // reference held by the DownloadFile and hence cuts off any pending 1066 // reference held by the DownloadFile and hence cuts off any pending
1068 // callbacks. 1067 // callbacks.
1069 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL); 1068 DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
1070 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 1069 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
1071 1070
1072 OnAllDataSaved(final_hash); 1071 OnAllDataSaved(total_bytes, std::move(secure_hash));
1073 MaybeCompleteDownload(); 1072 MaybeCompleteDownload();
1074 } 1073 }
1075 1074
1076 // **** Download progression cascade 1075 // **** Download progression cascade
1077 1076
1078 void DownloadItemImpl::Init(bool active, 1077 void DownloadItemImpl::Init(bool active,
1079 DownloadType download_type) { 1078 DownloadType download_type) {
1080 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1079 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1081 1080
1082 if (active) 1081 if (active)
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 DCHECK(state_ == INITIAL_INTERNAL || state_ == RESUMING_INTERNAL); 1140 DCHECK(state_ == INITIAL_INTERNAL || state_ == RESUMING_INTERNAL);
1142 1141
1143 // If the state_ is INITIAL_INTERNAL, then the target path must be empty. 1142 // If the state_ is INITIAL_INTERNAL, then the target path must be empty.
1144 DCHECK(state_ != INITIAL_INTERNAL || target_path_.empty()); 1143 DCHECK(state_ != INITIAL_INTERNAL || target_path_.empty());
1145 1144
1146 // If a resumption attempted failed, or if the download was DOA, then the 1145 // If a resumption attempted failed, or if the download was DOA, then the
1147 // download should go back to being interrupted. 1146 // download should go back to being interrupted.
1148 if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) { 1147 if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) {
1149 DCHECK(!download_file_.get()); 1148 DCHECK(!download_file_.get());
1150 1149
1150 // Download requests that are interrupted by Start() should result in a
1151 // DownloadCreateInfo with an intact DownloadSaveInfo.
1152 DCHECK(new_create_info.save_info);
1153
1154 int64_t offset = new_create_info.save_info->offset;
1155 scoped_ptr<crypto::SecureHash> hash_state =
1156 make_scoped_ptr(new_create_info.save_info->hash_state
1157 ? new_create_info.save_info->hash_state->Clone()
1158 : nullptr);
1159
1151 // Interrupted downloads also need a target path. 1160 // Interrupted downloads also need a target path.
1152 if (target_path_.empty()) { 1161 if (target_path_.empty()) {
1162 received_bytes_ = offset;
1163 hash_state_ = std::move(hash_state);
1164 destination_error_ = new_create_info.result;
1153 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL); 1165 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
1154 destination_error_ = new_create_info.result;
1155 DetermineDownloadTarget(); 1166 DetermineDownloadTarget();
1156 return; 1167 return;
1157 } 1168 }
1158 1169
1159 // Otherwise, this was a resumption attempt which ended with an 1170 // Otherwise, this was a resumption attempt which ended with an
1160 // interruption. Continue with current target path. 1171 // interruption. Continue with current target path.
1161 TransitionTo(TARGET_RESOLVED_INTERNAL); 1172 TransitionTo(TARGET_RESOLVED_INTERNAL);
1162 Interrupt(new_create_info.result); 1173 InterruptWithPartialState(offset, std::move(hash_state),
1174 new_create_info.result);
1163 UpdateObservers(); 1175 UpdateObservers();
1164 return; 1176 return;
1165 } 1177 }
1166 1178
1167 // Successful download start. 1179 // Successful download start.
1168 DCHECK(download_file_.get()); 1180 DCHECK(download_file_.get());
1169 DCHECK(request_handle_.get()); 1181 DCHECK(request_handle_.get());
1170 1182
1171 if (state_ == RESUMING_INTERNAL) 1183 if (state_ == RESUMING_INTERNAL)
1172 UpdateValidatorsOnResumption(new_create_info); 1184 UpdateValidatorsOnResumption(new_create_info);
1173 1185
1174 TransitionTo(TARGET_PENDING_INTERNAL); 1186 TransitionTo(TARGET_PENDING_INTERNAL);
1175 1187
1176 BrowserThread::PostTask( 1188 BrowserThread::PostTask(
1177 BrowserThread::FILE, FROM_HERE, 1189 BrowserThread::FILE, FROM_HERE,
1178 base::Bind(&DownloadFile::Initialize, 1190 base::Bind(&DownloadFile::Initialize,
1179 // Safe because we control download file lifetime. 1191 // Safe because we control download file lifetime.
1180 base::Unretained(download_file_.get()), 1192 base::Unretained(download_file_.get()),
1181 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, 1193 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
1182 weak_ptr_factory_.GetWeakPtr()))); 1194 weak_ptr_factory_.GetWeakPtr())));
1183 } 1195 }
1184 1196
1185 void DownloadItemImpl::OnDownloadFileInitialized( 1197 void DownloadItemImpl::OnDownloadFileInitialized(
1186 DownloadInterruptReason result) { 1198 DownloadInterruptReason result) {
1187 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1199 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1188 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL); 1200 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL);
1189 DVLOG(20) << __FUNCTION__ 1201 DVLOG(20) << __FUNCTION__
1190 << "() result:" << DownloadInterruptReasonToString(result); 1202 << "() result:" << DownloadInterruptReasonToString(result);
1191 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { 1203 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
1192 // Whoops. That didn't work. Proceed as an interrupted download. 1204 // Whoops. That didn't work. Proceed as an interrupted download, but reset
1205 // the partial state. Currently, the partial stub cannot be recovered if the
1206 // download file initialization fails.
1207 received_bytes_ = 0;
1208 hash_state_.reset();
svaldez 2016/03/09 19:27:34 Reset hash_?
asanka 2016/03/10 16:48:08 Done.
1193 destination_error_ = result; 1209 destination_error_ = result;
1194 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL); 1210 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
1195 } 1211 }
1196 1212
1197 DetermineDownloadTarget(); 1213 DetermineDownloadTarget();
1198 } 1214 }
1199 1215
1200 void DownloadItemImpl::DetermineDownloadTarget() { 1216 void DownloadItemImpl::DetermineDownloadTarget() {
1201 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1217 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1202 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true); 1218 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true);
(...skipping 24 matching lines...) Expand all
1227 << " disposition:" << disposition << " danger_type:" << danger_type 1243 << " disposition:" << disposition << " danger_type:" << danger_type
1228 << " this:" << DebugString(true); 1244 << " this:" << DebugString(true);
1229 1245
1230 target_path_ = target_path; 1246 target_path_ = target_path;
1231 target_disposition_ = disposition; 1247 target_disposition_ = disposition;
1232 SetDangerType(danger_type); 1248 SetDangerType(danger_type);
1233 1249
1234 // This was an interrupted download that was looking for a filename. Now that 1250 // This was an interrupted download that was looking for a filename. Now that
1235 // it has one, transition to interrupted. 1251 // it has one, transition to interrupted.
1236 if (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL) { 1252 if (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL) {
1237 Interrupt(destination_error_); 1253 InterruptWithPartialState(received_bytes_, std::move(hash_state_),
1254 destination_error_);
1238 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE; 1255 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
1239 UpdateObservers(); 1256 UpdateObservers();
1240 return; 1257 return;
1241 } 1258 }
1242 1259
1243 // We want the intermediate and target paths to refer to the same directory so 1260 // 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 1261 // that they are both on the same device and subject to same
1245 // space/permission/availability constraints. 1262 // space/permission/availability constraints.
1246 DCHECK(intermediate_path.DirName() == target_path.DirName()); 1263 DCHECK(intermediate_path.DirName() == target_path.DirName());
1247 1264
(...skipping 27 matching lines...) Expand all
1275 base::Unretained(download_file_.get()), 1292 base::Unretained(download_file_.get()),
1276 intermediate_path, callback)); 1293 intermediate_path, callback));
1277 } 1294 }
1278 1295
1279 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( 1296 void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
1280 DownloadInterruptReason reason, 1297 DownloadInterruptReason reason,
1281 const base::FilePath& full_path) { 1298 const base::FilePath& full_path) {
1282 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1299 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1283 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL); 1300 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL);
1284 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 1301 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
1302
1285 TransitionTo(TARGET_RESOLVED_INTERNAL); 1303 TransitionTo(TARGET_RESOLVED_INTERNAL);
1286 1304
1305 // If the intermediate rename fails while there's also a destination_error_,
1306 // then the former is considered the critical error since it requires
1307 // discarding the partial state.
1308 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1309 // TODO(asanka): Even though the rename failed, it may still be possible to
1310 // recover the partial state from the 'before' name.
1311 InterruptAndDiscardPartialState(reason);
1312 UpdateObservers();
1313 return;
1314 }
1315
1287 if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) { 1316 if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) {
1288 // Process destination error. If both |reason| and |destination_error_| 1317 SetFullPath(full_path);
1289 // refer to actual errors, we want to use the |destination_error_| as the 1318 InterruptWithPartialState(received_bytes_, std::move(hash_state_),
1290 // argument to the Interrupt() routine, as it happened first. 1319 destination_error_);
1291 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE)
1292 SetFullPath(full_path);
1293 Interrupt(destination_error_);
1294 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE; 1320 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
1295 UpdateObservers(); 1321 UpdateObservers();
1296 } else if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1322 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 } 1323 }
1324
1325 SetFullPath(full_path);
1326 TransitionTo(IN_PROGRESS_INTERNAL);
1327 // TODO(asanka): Calling UpdateObservers() prior to MaybeCompleteDownload() is
1328 // not safe. The download could be in an underminate state after invoking
1329 // observers. http://crbug.com/586610
1330 UpdateObservers();
1331 MaybeCompleteDownload();
1312 } 1332 }
1313 1333
1314 // When SavePackage downloads MHTML to GData (see 1334 // When SavePackage downloads MHTML to GData (see
1315 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it 1335 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it
1316 // does for non-SavePackage downloads, but SavePackage downloads never satisfy 1336 // does for non-SavePackage downloads, but SavePackage downloads never satisfy
1317 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls 1337 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls
1318 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage 1338 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage
1319 // notices that the upload has completed and runs its normal Finish() pathway. 1339 // notices that the upload has completed and runs its normal Finish() pathway.
1320 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes 1340 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes
1321 // downloads. SavePackage always uses its own Finish() to mark downloads 1341 // downloads. SavePackage always uses its own Finish() to mark downloads
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1363 1383
1364 DCHECK(download_file_.get()); 1384 DCHECK(download_file_.get());
1365 // Unilaterally rename; even if it already has the right name, 1385 // Unilaterally rename; even if it already has the right name,
1366 // we need theannotation. 1386 // we need theannotation.
1367 DownloadFile::RenameCompletionCallback callback = 1387 DownloadFile::RenameCompletionCallback callback =
1368 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, 1388 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
1369 weak_ptr_factory_.GetWeakPtr()); 1389 weak_ptr_factory_.GetWeakPtr());
1370 BrowserThread::PostTask( 1390 BrowserThread::PostTask(
1371 BrowserThread::FILE, FROM_HERE, 1391 BrowserThread::FILE, FROM_HERE,
1372 base::Bind(&DownloadFile::RenameAndAnnotate, 1392 base::Bind(&DownloadFile::RenameAndAnnotate,
1373 base::Unretained(download_file_.get()), 1393 base::Unretained(download_file_.get()), GetTargetFilePath(),
1374 GetTargetFilePath(), callback)); 1394 delegate_->GetApplicationClientIdForFileScanning(), GetURL(),
1395 GetReferrerUrl(), callback));
1375 } 1396 }
1376 1397
1377 void DownloadItemImpl::OnDownloadRenamedToFinalName( 1398 void DownloadItemImpl::OnDownloadRenamedToFinalName(
1378 DownloadInterruptReason reason, 1399 DownloadInterruptReason reason,
1379 const base::FilePath& full_path) { 1400 const base::FilePath& full_path) {
1380 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1401 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1381 DCHECK(!is_save_package_download_); 1402 DCHECK(!is_save_package_download_);
1382 1403
1383 // If a cancel or interrupt hit, we'll cancel the DownloadFile, which 1404 // 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 1405 // will result in deleting the file on the file thread. So we don't
1385 // care about the name having been changed. 1406 // care about the name having been changed.
1386 if (state_ != IN_PROGRESS_INTERNAL) 1407 if (state_ != IN_PROGRESS_INTERNAL)
1387 return; 1408 return;
1388 1409
1389 DVLOG(20) << __FUNCTION__ << "()" 1410 DVLOG(20) << __FUNCTION__ << "()"
1390 << " full_path = \"" << full_path.value() << "\"" 1411 << " full_path = \"" << full_path.value() << "\""
1391 << " " << DebugString(false); 1412 << " " << DebugString(false);
1392 1413
1393 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1414 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1394 Interrupt(reason); 1415 // Failure to perform the final rename is considered fatal. TODO(asanka): It
1395 1416 // 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 1417 // state.
1397 // resumption we will need to re-do filename determination. 1418 InterruptAndDiscardPartialState(reason);
1398 DCHECK(current_path_.empty());
1399 UpdateObservers(); 1419 UpdateObservers();
1400 return; 1420 return;
1401 } 1421 }
1402 1422
1403 DCHECK(target_path_ == full_path); 1423 DCHECK(target_path_ == full_path);
1404 1424
1405 if (full_path != current_path_) { 1425 if (full_path != current_path_) {
1406 // full_path is now the current and target file path. 1426 // full_path is now the current and target file path.
1407 DCHECK(!full_path.empty()); 1427 DCHECK(!full_path.empty());
1408 SetFullPath(full_path); 1428 SetFullPath(full_path);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1456 if (!IsTemporary()) 1476 if (!IsTemporary())
1457 OpenDownload(); 1477 OpenDownload();
1458 1478
1459 auto_opened_ = true; 1479 auto_opened_ = true;
1460 } 1480 }
1461 UpdateObservers(); 1481 UpdateObservers();
1462 } 1482 }
1463 1483
1464 // **** End of Download progression cascade 1484 // **** End of Download progression cascade
1465 1485
1466 // An error occurred somewhere. 1486 void DownloadItemImpl::InterruptAndDiscardPartialState(
1467 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { 1487 DownloadInterruptReason reason) {
1488 InterruptWithPartialState(0, scoped_ptr<crypto::SecureHash>(), reason);
1489 }
1490
1491 void DownloadItemImpl::InterruptWithPartialState(
1492 int64_t bytes_so_far,
1493 scoped_ptr<crypto::SecureHash> hash_state,
1494 DownloadInterruptReason reason) {
1468 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1495 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1469 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason); 1496 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason);
1470 DVLOG(20) << __FUNCTION__ 1497 DVLOG(20) << __FUNCTION__
1471 << "() reason:" << DownloadInterruptReasonToString(reason) 1498 << "() reason:" << DownloadInterruptReasonToString(reason)
1499 << " bytes_so_far:" << bytes_so_far
1500 << " hash_state:" << (hash_state ? "Valid" : "Invalid")
1472 << " this=" << DebugString(true); 1501 << " this=" << DebugString(true);
1473 1502
1474 // Somewhat counter-intuitively, it is possible for us to receive an 1503 // Somewhat counter-intuitively, it is possible for us to receive an
1475 // interrupt after we've already been interrupted. The generation of 1504 // interrupt after we've already been interrupted. The generation of
1476 // interrupts from the file thread Renames and the generation of 1505 // interrupts from the file thread Renames and the generation of
1477 // interrupts from disk writes go through two different mechanisms (driven 1506 // interrupts from disk writes go through two different mechanisms (driven
1478 // by rename requests from UI thread and by write requests from IO thread, 1507 // 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, 1508 // 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 1509 // this is the place where the races collide. It's also possible for
1481 // interrupts to race with cancels. 1510 // interrupts to race with cancels.
(...skipping 20 matching lines...) Expand all
1502 1531
1503 if (download_file_) { 1532 if (download_file_) {
1504 ResumeMode resume_mode = GetResumeMode(); 1533 ResumeMode resume_mode = GetResumeMode();
1505 ReleaseDownloadFile(resume_mode != RESUME_MODE_IMMEDIATE_CONTINUE && 1534 ReleaseDownloadFile(resume_mode != RESUME_MODE_IMMEDIATE_CONTINUE &&
1506 resume_mode != RESUME_MODE_USER_CONTINUE); 1535 resume_mode != RESUME_MODE_USER_CONTINUE);
1507 } 1536 }
1508 break; 1537 break;
1509 1538
1510 case RESUMING_INTERNAL: 1539 case RESUMING_INTERNAL:
1511 case INTERRUPTED_INTERNAL: 1540 case INTERRUPTED_INTERNAL:
1541 DCHECK(!download_file_);
1512 // The first non-cancel interrupt reason wins in cases where multiple 1542 // The first non-cancel interrupt reason wins in cases where multiple
1513 // things go wrong. 1543 // things go wrong.
1514 if (reason != DOWNLOAD_INTERRUPT_REASON_USER_CANCELED && 1544 if (reason != DOWNLOAD_INTERRUPT_REASON_USER_CANCELED &&
1515 reason != DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) 1545 reason != DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN)
1516 return; 1546 return;
1517 1547
1518 last_reason_ = reason; 1548 last_reason_ = reason;
1519 if (!current_path_.empty()) { 1549 if (!current_path_.empty()) {
1520 // There is no download file and this is transitioning from INTERRUPTED 1550 // There is no download file and this is transitioning from INTERRUPTED
1521 // to CANCELLED. The intermediate file is no longer usable, and should 1551 // 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 1563 // 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 1564 // 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 1565 // 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 1566 // 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 1567 // 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 1568 // simply result in a null range request, which would generate a
1539 // DestinationCompleted() notification from the DownloadFile, which would 1569 // DestinationCompleted() notification from the DownloadFile, which would
1540 // behave properly with setting all_data_saved_ to false here. 1570 // behave properly with setting all_data_saved_ to false here.
1541 all_data_saved_ = false; 1571 all_data_saved_ = false;
1542 1572
1573 if (current_path_.empty()) {
1574 hash_state_.reset();
1575 hash_.clear();
1576 received_bytes_ = 0;
1577 } else {
1578 UpdateProgress(bytes_so_far, 0);
1579 hash_state_ = std::move(hash_state);
1580 UpdatePrefixHash();
1581 }
1582
1543 if (request_handle_) 1583 if (request_handle_)
1544 request_handle_->CancelRequest(); 1584 request_handle_->CancelRequest();
1545 1585
1546 if (reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED || 1586 if (reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED ||
1547 reason == DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) { 1587 reason == DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) {
1548 if (IsDangerous()) { 1588 if (IsDangerous()) {
1549 RecordDangerousDownloadDiscard( 1589 RecordDangerousDownloadDiscard(
1550 reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED 1590 reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
1551 ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION 1591 ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION
1552 : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN, 1592 : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN,
1553 GetDangerType(), GetTargetFilePath()); 1593 GetDangerType(), GetTargetFilePath());
1554 } 1594 }
1555 1595
1556 RecordDownloadCount(CANCELLED_COUNT); 1596 RecordDownloadCount(CANCELLED_COUNT);
1557 TransitionTo(CANCELLED_INTERNAL); 1597 TransitionTo(CANCELLED_INTERNAL);
1558 return; 1598 return;
1559 } 1599 }
1560 1600
1561 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_); 1601 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_);
1562 if (!GetWebContents()) 1602 if (!GetWebContents())
1563 RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS); 1603 RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS);
1564 1604
1565 TransitionTo(INTERRUPTED_INTERNAL); 1605 TransitionTo(INTERRUPTED_INTERNAL);
1566 AutoResumeIfValid(); 1606 AutoResumeIfValid();
1567 } 1607 }
1568 1608
1609 void DownloadItemImpl::UpdateProgress(int64_t bytes_so_far,
1610 int64_t bytes_per_sec) {
1611 received_bytes_ = bytes_so_far;
1612 bytes_per_sec_ = bytes_per_sec;
1613
1614 // If we've received more data than we were expecting (bad server info?),
1615 // revert to 'unknown size mode'.
1616 if (received_bytes_ > total_bytes_)
1617 total_bytes_ = 0;
1618 }
1619
1620 void DownloadItemImpl::UpdatePrefixHash() {
1621 if (!hash_state_) {
1622 hash_.clear();
1623 return;
1624 }
1625
1626 scoped_ptr<crypto::SecureHash> clone(hash_state_->Clone());
1627 std::vector<char> hash_value(clone->GetHashLength());
1628 clone->Finish(&hash_value.front(), hash_value.size());
1629 hash_.assign(hash_value.begin(), hash_value.end());
1630 }
1631
1569 void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) { 1632 void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) {
1570 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1633 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1571 DVLOG(20) << __FUNCTION__ << "() destroy_file:" << destroy_file; 1634 DVLOG(20) << __FUNCTION__ << "() destroy_file:" << destroy_file;
1572 1635
1573 if (destroy_file) { 1636 if (destroy_file) {
1574 BrowserThread::PostTask( 1637 BrowserThread::PostTask(
1575 BrowserThread::FILE, FROM_HERE, 1638 BrowserThread::FILE, FROM_HERE,
1576 // Will be deleted at end of task execution. 1639 // Will be deleted at end of task execution.
1577 base::Bind(&DownloadFileCancel, base::Passed(&download_file_))); 1640 base::Bind(&DownloadFileCancel, base::Passed(&download_file_)));
1578 // Avoid attempting to reuse the intermediate file by clearing out 1641 // 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_)); 1737 base::Bind(&ItemCompletingNetLogCallback, received_bytes_, &hash_));
1675 break; 1738 break;
1676 1739
1677 case COMPLETE_INTERNAL: 1740 case COMPLETE_INTERNAL:
1678 bound_net_log_.AddEvent( 1741 bound_net_log_.AddEvent(
1679 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED, 1742 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED,
1680 base::Bind(&ItemFinishedNetLogCallback, auto_opened_)); 1743 base::Bind(&ItemFinishedNetLogCallback, auto_opened_));
1681 break; 1744 break;
1682 1745
1683 case INTERRUPTED_INTERNAL: 1746 case INTERRUPTED_INTERNAL:
1684 bound_net_log_.AddEvent( 1747 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED,
1685 net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED, 1748 base::Bind(&ItemInterruptedNetLogCallback,
1686 base::Bind(&ItemInterruptedNetLogCallback, last_reason_, 1749 last_reason_, received_bytes_));
1687 received_bytes_, &hash_state_));
1688 break; 1750 break;
1689 1751
1690 case RESUMING_INTERNAL: 1752 case RESUMING_INTERNAL:
1691 bound_net_log_.AddEvent( 1753 bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED,
1692 net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED, 1754 base::Bind(&ItemResumingNetLogCallback, false,
1693 base::Bind(&ItemResumingNetLogCallback, false, last_reason_, 1755 last_reason_, received_bytes_));
1694 received_bytes_, &hash_state_));
1695 break; 1756 break;
1696 1757
1697 case CANCELLED_INTERNAL: 1758 case CANCELLED_INTERNAL:
1698 bound_net_log_.AddEvent( 1759 bound_net_log_.AddEvent(
1699 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED, 1760 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED,
1700 base::Bind(&ItemCanceledNetLogCallback, received_bytes_, 1761 base::Bind(&ItemCanceledNetLogCallback, received_bytes_));
1701 &hash_state_));
1702 break; 1762 break;
1703 1763
1704 case MAX_DOWNLOAD_INTERNAL_STATE: 1764 case MAX_DOWNLOAD_INTERNAL_STATE:
1705 NOTREACHED(); 1765 NOTREACHED();
1706 break; 1766 break;
1707 } 1767 }
1708 1768
1709 DVLOG(20) << " " << __FUNCTION__ << "()" 1769 DVLOG(20) << " " << __FUNCTION__ << "()"
1710 << " from:" << DebugDownloadStateString(old_state) 1770 << " from:" << DebugDownloadStateString(old_state)
1711 << " to:" << DebugDownloadStateString(state_) 1771 << " to:" << DebugDownloadStateString(state_)
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1792 1852
1793 // We are starting a new request. Shake off all pending operations. 1853 // We are starting a new request. Shake off all pending operations.
1794 DCHECK(!download_file_); 1854 DCHECK(!download_file_);
1795 weak_ptr_factory_.InvalidateWeakPtrs(); 1855 weak_ptr_factory_.InvalidateWeakPtrs();
1796 1856
1797 // Reset the appropriate state if restarting. 1857 // Reset the appropriate state if restarting.
1798 ResumeMode mode = GetResumeMode(); 1858 ResumeMode mode = GetResumeMode();
1799 if (mode == RESUME_MODE_IMMEDIATE_RESTART || 1859 if (mode == RESUME_MODE_IMMEDIATE_RESTART ||
1800 mode == RESUME_MODE_USER_RESTART) { 1860 mode == RESUME_MODE_USER_RESTART) {
1801 received_bytes_ = 0; 1861 received_bytes_ = 0;
1802 hash_state_ = ""; 1862 last_modified_time_.clear();
1803 last_modified_time_ = ""; 1863 etag_.clear();
1804 etag_ = ""; 1864 hash_.clear();
1865 hash_state_.reset();
1805 } 1866 }
1806 1867
1807 // Avoid using the WebContents even if it's still around. Resumption requests 1868 // 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 1869 // 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 1870 // request will not be dropped if the WebContents (and by extension, the
1810 // associated renderer) goes away before a response is received. 1871 // associated renderer) goes away before a response is received.
1811 scoped_ptr<DownloadUrlParameters> download_params(new DownloadUrlParameters( 1872 scoped_ptr<DownloadUrlParameters> download_params(new DownloadUrlParameters(
1812 GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext())); 1873 GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext()));
1813 download_params->set_file_path(GetFullPath()); 1874 download_params->set_file_path(GetFullPath());
1814 download_params->set_offset(GetReceivedBytes()); 1875 download_params->set_offset(GetReceivedBytes());
1815 download_params->set_hash_state(GetHashState());
1816 download_params->set_last_modified(GetLastModifiedTime()); 1876 download_params->set_last_modified(GetLastModifiedTime());
1817 download_params->set_etag(GetETag()); 1877 download_params->set_etag(GetETag());
1878 download_params->set_prefix_hash(hash_);
1879 download_params->set_hash_state(std::move(hash_state_));
1818 1880
1819 TransitionTo(RESUMING_INTERNAL); 1881 TransitionTo(RESUMING_INTERNAL);
1820 delegate_->ResumeInterruptedDownload(std::move(download_params), GetId()); 1882 delegate_->ResumeInterruptedDownload(std::move(download_params), GetId());
1821 // Just in case we were interrupted while paused. 1883 // Just in case we were interrupted while paused.
1822 is_paused_ = false; 1884 is_paused_ = false;
1823 } 1885 }
1824 1886
1825 // static 1887 // static
1826 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState( 1888 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState(
1827 DownloadInternalState internal_state) { 1889 DownloadInternalState internal_state) {
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1992 case RESUME_MODE_USER_CONTINUE: 2054 case RESUME_MODE_USER_CONTINUE:
1993 return "USER_CONTINUE"; 2055 return "USER_CONTINUE";
1994 case RESUME_MODE_USER_RESTART: 2056 case RESUME_MODE_USER_RESTART:
1995 return "USER_RESTART"; 2057 return "USER_RESTART";
1996 } 2058 }
1997 NOTREACHED() << "Unknown resume mode " << mode; 2059 NOTREACHED() << "Unknown resume mode " << mode;
1998 return "unknown"; 2060 return "unknown";
1999 } 2061 }
2000 2062
2001 } // namespace content 2063 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698