OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
163 } | 163 } |
164 | 164 |
165 // Constructing for a regular download: | 165 // Constructing for a regular download: |
166 DownloadItemImpl::DownloadItemImpl( | 166 DownloadItemImpl::DownloadItemImpl( |
167 DownloadItemImplDelegate* delegate, | 167 DownloadItemImplDelegate* delegate, |
168 uint32 download_id, | 168 uint32 download_id, |
169 const DownloadCreateInfo& info, | 169 const DownloadCreateInfo& info, |
170 const net::BoundNetLog& bound_net_log) | 170 const net::BoundNetLog& bound_net_log) |
171 : is_save_package_download_(false), | 171 : is_save_package_download_(false), |
172 download_id_(download_id), | 172 download_id_(download_id), |
173 target_disposition_( | 173 target_disposition_((info.save_info->prompt_for_save_location) |
174 (info.save_info->prompt_for_save_location) ? | 174 ? TARGET_DISPOSITION_PROMPT |
175 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE), | 175 : TARGET_DISPOSITION_OVERWRITE), |
176 url_chain_(info.url_chain), | 176 url_chain_(info.url_chain), |
177 referrer_url_(info.referrer_url), | 177 referrer_url_(info.referrer_url), |
178 suggested_filename_(base::UTF16ToUTF8(info.save_info->suggested_name)), | 178 suggested_filename_(base::UTF16ToUTF8(info.save_info->suggested_name)), |
179 forced_file_path_(info.save_info->file_path), | 179 forced_file_path_(info.save_info->file_path), |
180 transition_type_(info.transition_type), | 180 transition_type_(info.transition_type), |
181 has_user_gesture_(info.has_user_gesture), | 181 has_user_gesture_(info.has_user_gesture), |
182 content_disposition_(info.content_disposition), | 182 content_disposition_(info.content_disposition), |
183 mime_type_(info.mime_type), | 183 mime_type_(info.mime_type), |
184 original_mime_type_(info.original_mime_type), | 184 original_mime_type_(info.original_mime_type), |
185 remote_address_(info.remote_address), | 185 remote_address_(info.remote_address), |
186 total_bytes_(info.total_bytes), | 186 total_bytes_(info.total_bytes), |
187 received_bytes_(0), | 187 received_bytes_(0), |
188 bytes_per_sec_(0), | 188 bytes_per_sec_(0), |
189 last_modified_time_(info.last_modified), | 189 last_modified_time_(info.last_modified), |
190 etag_(info.etag), | 190 etag_(info.etag), |
191 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), | 191 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), |
192 start_tick_(base::TimeTicks::Now()), | 192 start_tick_(base::TimeTicks::Now()), |
193 state_(IN_PROGRESS_INTERNAL), | 193 state_(IN_PROGRESS_INTERNAL), |
194 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), | 194 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), |
195 start_time_(info.start_time), | 195 start_time_(info.start_time), |
196 delegate_(delegate), | 196 delegate_(delegate), |
197 is_paused_(false), | 197 is_paused_(false), |
198 auto_resume_count_(0), | 198 auto_resume_count_(0), |
199 open_when_complete_(false), | 199 open_when_complete_(false), |
200 file_externally_removed_(false), | 200 file_externally_removed_(false), |
201 auto_opened_(false), | 201 auto_opened_(false), |
202 is_temporary_(!info.save_info->file_path.empty()), | 202 is_temporary_(!info.save_info->file_path.empty()), |
203 all_data_saved_(false), | 203 all_data_saved_(false), |
204 destination_error_(content::DOWNLOAD_INTERRUPT_REASON_NONE), | 204 destination_error_(DOWNLOAD_INTERRUPT_REASON_NONE), |
205 opened_(false), | 205 opened_(false), |
206 delegate_delayed_complete_(false), | 206 delegate_delayed_complete_(false), |
207 bound_net_log_(bound_net_log), | 207 bound_net_log_(bound_net_log), |
208 weak_ptr_factory_(this) { | 208 weak_ptr_factory_(this) { |
209 delegate_->Attach(); | 209 delegate_->Attach(); |
210 Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD); | 210 Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD); |
211 | 211 |
212 // Link the event sources. | 212 // Link the event sources. |
213 bound_net_log_.AddEvent( | 213 bound_net_log_.AddEvent( |
214 net::NetLog::TYPE_DOWNLOAD_URL_REQUEST, | 214 net::NetLog::TYPE_DOWNLOAD_URL_REQUEST, |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 callback.Run(current_path_); | 334 callback.Run(current_path_); |
335 } | 335 } |
336 current_path_.clear(); | 336 current_path_.clear(); |
337 Remove(); | 337 Remove(); |
338 // We have now been deleted. | 338 // We have now been deleted. |
339 } | 339 } |
340 | 340 |
341 void DownloadItemImpl::Pause() { | 341 void DownloadItemImpl::Pause() { |
342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
343 | 343 |
344 // Ignore irrelevant states. | 344 // Ignore irrelevant states. Also ignore the call if there's no request |
345 if (state_ != IN_PROGRESS_INTERNAL || is_paused_) | 345 // handle. |
Randy Smith (Not in Mondays)
2014/03/18 21:07:28
This sounds like it's trying to handle Pause() req
asanka
2014/03/19 20:37:06
Hmm. Good point. We could set is_paused_ and respe
Randy Smith (Not in Mondays)
2014/03/20 15:24:54
That's effectively accepting that we have a race a
asanka
2016/02/11 23:57:24
But that's not correct. We are no longer in a plac
Randy Smith (Not in Mondays)
2016/02/12 18:58:10
Ok. I'm good with your race handling suggestion e
asanka
2016/02/12 20:52:28
Time Of Check vs. Time Of Use. :-) Basically, the
| |
346 if (state_ != IN_PROGRESS_INTERNAL || is_paused_ || !request_handle_) | |
346 return; | 347 return; |
347 | 348 |
348 request_handle_->PauseRequest(); | 349 request_handle_->PauseRequest(); |
349 is_paused_ = true; | 350 is_paused_ = true; |
350 UpdateObservers(); | 351 UpdateObservers(); |
351 } | 352 } |
352 | 353 |
353 void DownloadItemImpl::Resume() { | 354 void DownloadItemImpl::Resume() { |
354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
355 switch (state_) { | 356 switch (state_) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
401 | 402 |
402 RecordDownloadCount(CANCELLED_COUNT); | 403 RecordDownloadCount(CANCELLED_COUNT); |
403 | 404 |
404 // TODO(rdsmith/benjhayden): Remove condition as part of | 405 // TODO(rdsmith/benjhayden): Remove condition as part of |
405 // |SavePackage| integration. | 406 // |SavePackage| integration. |
406 // |download_file_| can be NULL if Interrupt() is called after the | 407 // |download_file_| can be NULL if Interrupt() is called after the |
407 // download file has been released. | 408 // download file has been released. |
408 if (!is_save_package_download_ && download_file_) | 409 if (!is_save_package_download_ && download_file_) |
409 ReleaseDownloadFile(true); | 410 ReleaseDownloadFile(true); |
410 | 411 |
411 if (state_ == IN_PROGRESS_INTERNAL) { | 412 if (state_ == IN_PROGRESS_INTERNAL && request_handle_) { |
412 // Cancel the originating URL request unless it's already been cancelled | 413 // Cancel the originating URL request unless it's already been cancelled |
413 // by interrupt. | 414 // by interrupt. |
414 request_handle_->CancelRequest(); | 415 request_handle_->CancelRequest(); |
415 } | 416 } |
416 | 417 |
417 // Remove the intermediate file if we are cancelling an interrupted download. | 418 // Remove the intermediate file if we are cancelling an interrupted download. |
418 // Continuable interruptions leave the intermediate file around. | 419 // Continuable interruptions leave the intermediate file around. |
419 if ((state_ == INTERRUPTED_INTERNAL || state_ == RESUMING_INTERNAL) && | 420 if ((state_ == INTERRUPTED_INTERNAL || state_ == RESUMING_INTERNAL) && |
420 !current_path_.empty()) { | 421 !current_path_.empty()) { |
421 BrowserThread::PostTask( | 422 BrowserThread::PostTask( |
(...skipping 497 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
919 } | 920 } |
920 | 921 |
921 return mode; | 922 return mode; |
922 } | 923 } |
923 | 924 |
924 void DownloadItemImpl::MergeOriginInfoOnResume( | 925 void DownloadItemImpl::MergeOriginInfoOnResume( |
925 const DownloadCreateInfo& new_create_info) { | 926 const DownloadCreateInfo& new_create_info) { |
926 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 927 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
927 DCHECK_EQ(RESUMING_INTERNAL, state_); | 928 DCHECK_EQ(RESUMING_INTERNAL, state_); |
928 DCHECK(!new_create_info.url_chain.empty()); | 929 DCHECK(!new_create_info.url_chain.empty()); |
930 DCHECK_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, new_create_info.interrupt_reason); | |
929 | 931 |
930 // We are going to tack on any new redirects to our list of redirects. | 932 // We are going to tack on any new redirects to our list of redirects. |
931 // When a download is resumed, the URL used for the resumption request is the | 933 // When a download is resumed, the URL used for the resumption request is the |
932 // one at the end of the previous redirect chain. Tacking additional redirects | 934 // one at the end of the previous redirect chain. Tacking additional redirects |
933 // to the end of this chain ensures that: | 935 // to the end of this chain ensures that: |
934 // - If the download needs to be resumed again, the ETag/Last-Modified headers | 936 // - If the download needs to be resumed again, the ETag/Last-Modified headers |
935 // will be used with the last server that sent them to us. | 937 // will be used with the last server that sent them to us. |
936 // - The redirect chain contains all the servers that were involved in this | 938 // - The redirect chain contains all the servers that were involved in this |
937 // download since the initial request, in order. | 939 // download since the initial request, in order. |
938 std::vector<GURL>::const_iterator chain_iter = | 940 std::vector<GURL>::const_iterator chain_iter = |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1099 bound_net_log_.AddEvent( | 1101 bound_net_log_.AddEvent( |
1100 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data); | 1102 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data); |
1101 } | 1103 } |
1102 | 1104 |
1103 VLOG(20) << __FUNCTION__ << "() " << DebugString(true); | 1105 VLOG(20) << __FUNCTION__ << "() " << DebugString(true); |
1104 } | 1106 } |
1105 | 1107 |
1106 // We're starting the download. | 1108 // We're starting the download. |
1107 void DownloadItemImpl::Start( | 1109 void DownloadItemImpl::Start( |
1108 scoped_ptr<DownloadFile> file, | 1110 scoped_ptr<DownloadFile> file, |
1109 scoped_ptr<DownloadRequestHandleInterface> req_handle) { | 1111 scoped_ptr<DownloadRequestHandleInterface> req_handle, |
1112 const DownloadCreateInfo& new_create_info) { | |
1110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1111 DCHECK(!download_file_.get()); | 1114 DCHECK(!download_file_.get()); |
1112 DCHECK(file.get()); | |
1113 DCHECK(req_handle.get()); | |
1114 | 1115 |
1115 download_file_ = file.Pass(); | 1116 download_file_ = file.Pass(); |
1116 request_handle_ = req_handle.Pass(); | 1117 request_handle_ = req_handle.Pass(); |
1117 | 1118 |
1118 if (GetState() == CANCELLED) { | 1119 if (GetState() == CANCELLED) { |
1119 // The download was in the process of resuming when it was cancelled. Don't | 1120 // The download was in the process of resuming when it was cancelled. Don't |
1120 // proceed. | 1121 // proceed. |
1121 ReleaseDownloadFile(true); | 1122 ReleaseDownloadFile(true); |
1122 request_handle_->CancelRequest(); | 1123 request_handle_->CancelRequest(); |
1123 return; | 1124 return; |
1124 } | 1125 } |
1125 | 1126 |
1127 DCHECK(state_ == IN_PROGRESS_INTERNAL || state_ == RESUMING_INTERNAL); | |
1128 if (new_create_info.interrupt_reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | |
1129 DCHECK(!download_file_.get()); | |
1130 // If the download failed, then skip the download_file_ initialization. It | |
1131 // isn't going to be used anyway. OnDownloadFileInitialized() handles all | |
1132 // interrupts that happen up until after download file initialization. Allow | |
1133 // it to handle the new interrupt as well. | |
1134 OnDownloadFileInitialized(new_create_info.interrupt_reason); | |
Randy Smith (Not in Mondays)
2014/03/18 21:07:28
nit: Might want to change the name if we're expand
Randy Smith (Not in Mondays)
2014/03/20 15:24:54
Just noting you didn't respond to this nit (I don'
asanka
2016/02/11 23:57:24
Whoops. Missed. I'm doing a pass through the previ
| |
1135 return; | |
1136 } | |
1137 | |
1138 // Successful download start. | |
1139 DCHECK(download_file_.get()); | |
1140 DCHECK(request_handle_.get()); | |
1141 | |
1142 if (state_ == RESUMING_INTERNAL) | |
1143 MergeOriginInfoOnResume(new_create_info); | |
1144 | |
1126 TransitionTo(IN_PROGRESS_INTERNAL, UPDATE_OBSERVERS); | 1145 TransitionTo(IN_PROGRESS_INTERNAL, UPDATE_OBSERVERS); |
1127 | 1146 |
1128 BrowserThread::PostTask( | 1147 BrowserThread::PostTask( |
1129 BrowserThread::FILE, FROM_HERE, | 1148 BrowserThread::FILE, FROM_HERE, |
1130 base::Bind(&DownloadFile::Initialize, | 1149 base::Bind(&DownloadFile::Initialize, |
1131 // Safe because we control download file lifetime. | 1150 // Safe because we control download file lifetime. |
1132 base::Unretained(download_file_.get()), | 1151 base::Unretained(download_file_.get()), |
1133 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, | 1152 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, |
1134 weak_ptr_factory_.GetWeakPtr()))); | 1153 weak_ptr_factory_.GetWeakPtr()))); |
1135 } | 1154 } |
1136 | 1155 |
1137 void DownloadItemImpl::OnDownloadFileInitialized( | 1156 void DownloadItemImpl::OnDownloadFileInitialized( |
1138 DownloadInterruptReason result) { | 1157 DownloadInterruptReason result) { |
1139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1140 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { | 1159 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { |
1160 // Either the download was interrupted at Start() or the download file | |
1161 // failed to initialize. Either way, the download will not transition to an | |
1162 // interrupted state. | |
1141 Interrupt(result); | 1163 Interrupt(result); |
1142 // TODO(rdsmith/asanka): Arguably we should show this in the UI, but | 1164 |
1143 // it's not at all clear what to show--we haven't done filename | 1165 // The download may transition to RESUMING_INTERNAL as a result of the |
1144 // determination, so we don't know what name to display. OTOH, | 1166 // Interrupt() call above if it was resumed automatically. If so, then |
1145 // the failure mode of not showing the DI if the file initialization | 1167 // Start() is expected to be called again and the download progression |
1146 // fails isn't a good one. Can we hack up a name based on the | 1168 // cascade will be redone. Therefore we are done for now. |
1147 // URLRequest? We'll need to make sure that initialization happens | 1169 // |
1148 // properly. Possibly the right thing is to have the UI handle | 1170 // NOTE: The check below assumes that resumption doesn't call Start() |
1149 // this case specially. | 1171 // synchronously. If it did, then state_ may not be RESUMING_INTERNAL when |
1150 return; | 1172 // we get here. This constraint is currently enforced via a DCHECK in |
1173 // Start() which requires that the download be in RESUMING_INTERNAL or | |
1174 // IN_PROGRESS_INTERNAL state when Start() is called. If Start() was called | |
1175 // synchronously, then the state of the DownloadItem would be | |
1176 // INTERRUPTED_INTERNAL. | |
1177 if (state_ == RESUMING_INTERNAL) | |
1178 return; | |
1151 } | 1179 } |
1152 | 1180 |
1153 delegate_->DetermineDownloadTarget( | 1181 delegate_->DetermineDownloadTarget( |
1154 this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined, | 1182 this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined, |
1155 weak_ptr_factory_.GetWeakPtr())); | 1183 weak_ptr_factory_.GetWeakPtr())); |
1156 } | 1184 } |
1157 | 1185 |
1158 // Called by delegate_ when the download target path has been | 1186 // Called by delegate_ when the download target path has been |
1159 // determined. | 1187 // determined. |
1160 void DownloadItemImpl::OnDownloadTargetDetermined( | 1188 void DownloadItemImpl::OnDownloadTargetDetermined( |
1161 const base::FilePath& target_path, | 1189 const base::FilePath& target_path, |
1162 TargetDisposition disposition, | 1190 TargetDisposition disposition, |
1163 DownloadDangerType danger_type, | 1191 DownloadDangerType danger_type, |
1164 const base::FilePath& intermediate_path) { | 1192 const base::FilePath& intermediate_path) { |
1165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1166 | 1194 |
1167 // If the |target_path| is empty, then we consider this download to be | 1195 // If the |target_path| is empty, then we consider this download to be |
1168 // canceled. | 1196 // canceled. |
1169 if (target_path.empty()) { | 1197 if (target_path.empty()) { |
1170 Cancel(true); | 1198 Cancel(true); |
1171 return; | 1199 return; |
1172 } | 1200 } |
1173 | 1201 |
1174 // TODO(rdsmith,asanka): We are ignoring the possibility that the download | |
1175 // has been interrupted at this point until we finish the intermediate | |
1176 // rename and set the full path. That's dangerous, because we might race | |
1177 // with resumption, either manual (because the interrupt is visible to the | |
1178 // UI) or automatic. If we keep the "ignore an error on download until file | |
1179 // name determination complete" semantics, we need to make sure that the | |
1180 // error is kept completely invisible until that point. | |
1181 | |
1182 VLOG(20) << __FUNCTION__ << " " << target_path.value() << " " << disposition | 1202 VLOG(20) << __FUNCTION__ << " " << target_path.value() << " " << disposition |
1183 << " " << danger_type << " " << DebugString(true); | 1203 << " " << danger_type << " " << DebugString(true); |
1184 | 1204 |
1185 target_path_ = target_path; | 1205 target_path_ = target_path; |
1186 target_disposition_ = disposition; | 1206 target_disposition_ = disposition; |
1187 SetDangerType(danger_type); | 1207 SetDangerType(danger_type); |
1208 if (state_ != IN_PROGRESS_INTERNAL) { | |
1209 // The download could be already interrupted, in which case there's nothing | |
1210 // more we can do. Notify observers and quit the download progression | |
1211 // cascade. | |
1212 UpdateObservers(); | |
1213 return; | |
1214 } | |
1188 | 1215 |
1189 // We want the intermediate and target paths to refer to the same directory so | 1216 // We want the intermediate and target paths to refer to the same directory so |
1190 // that they are both on the same device and subject to same | 1217 // that they are both on the same device and subject to same |
1191 // space/permission/availability constraints. | 1218 // space/permission/availability constraints. |
1192 DCHECK(intermediate_path.DirName() == target_path.DirName()); | 1219 DCHECK(intermediate_path.DirName() == target_path.DirName()); |
1193 | 1220 |
1194 // During resumption, we may choose to proceed with the same intermediate | 1221 // During resumption, we may choose to proceed with the same intermediate |
1195 // file. No rename is necessary if our intermediate file already has the | 1222 // file. No rename is necessary if our intermediate file already has the |
1196 // correct name. | 1223 // correct name. |
1197 // | 1224 // |
1198 // The intermediate name may change from its original value during filename | 1225 // The intermediate name may change from its original value during filename |
1199 // determination on resumption, for example if the reason for the interruption | 1226 // determination on resumption, for example if the reason for the interruption |
1200 // was the download target running out space, resulting in a user prompt. | 1227 // was the download target running out space, resulting in a user prompt. |
1201 if (intermediate_path == current_path_) { | 1228 if (intermediate_path == current_path_) { |
1202 OnDownloadRenamedToIntermediateName(DOWNLOAD_INTERRUPT_REASON_NONE, | 1229 OnDownloadRenamedToIntermediateName(DOWNLOAD_INTERRUPT_REASON_NONE, |
1203 intermediate_path); | 1230 intermediate_path); |
1204 return; | 1231 return; |
1205 } | 1232 } |
1206 | 1233 |
1207 // Rename to intermediate name. | 1234 // Rename to intermediate name. |
1208 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a | 1235 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a |
1209 // spurious rename when we can just rename to the final | 1236 // spurious rename when we can just rename to the final |
1210 // filename. Unnecessary renames may cause bugs like | 1237 // filename. Unnecessary renames may cause bugs like |
1211 // http://crbug.com/74187. | 1238 // http://crbug.com/74187. |
1212 DCHECK(!is_save_package_download_); | 1239 DCHECK(!is_save_package_download_); |
1213 DCHECK(download_file_.get()); | |
Randy Smith (Not in Mondays)
2014/03/18 21:07:28
Ok, I'm confused. It seems to me that if we're no
asanka
2014/03/19 20:37:06
Ah. The DCHECK removal was due to an interim chang
| |
1214 DownloadFile::RenameCompletionCallback callback = | 1240 DownloadFile::RenameCompletionCallback callback = |
1215 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, | 1241 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, |
1216 weak_ptr_factory_.GetWeakPtr()); | 1242 weak_ptr_factory_.GetWeakPtr()); |
1217 BrowserThread::PostTask( | 1243 BrowserThread::PostTask( |
1218 BrowserThread::FILE, FROM_HERE, | 1244 BrowserThread::FILE, FROM_HERE, |
1219 base::Bind(&DownloadFile::RenameAndUniquify, | 1245 base::Bind(&DownloadFile::RenameAndUniquify, |
1220 // Safe because we control download file lifetime. | 1246 // Safe because we control download file lifetime. |
1221 base::Unretained(download_file_.get()), | 1247 base::Unretained(download_file_.get()), |
1222 intermediate_path, callback)); | 1248 intermediate_path, callback)); |
1223 } | 1249 } |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1396 // we still need to set it auto-opened so that it can be removed from the | 1422 // we still need to set it auto-opened so that it can be removed from the |
1397 // download shelf. | 1423 // download shelf. |
1398 if (!IsTemporary()) | 1424 if (!IsTemporary()) |
1399 OpenDownload(); | 1425 OpenDownload(); |
1400 | 1426 |
1401 auto_opened_ = true; | 1427 auto_opened_ = true; |
1402 UpdateObservers(); | 1428 UpdateObservers(); |
1403 } | 1429 } |
1404 } | 1430 } |
1405 | 1431 |
1406 void DownloadItemImpl::OnResumeRequestStarted( | |
1407 DownloadItem* item, | |
1408 DownloadInterruptReason interrupt_reason) { | |
1409 // If |item| is not NULL, then Start() has been called already, and nothing | |
1410 // more needs to be done here. | |
1411 if (item) { | |
1412 DCHECK_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason); | |
1413 DCHECK_EQ(static_cast<DownloadItem*>(this), item); | |
1414 return; | |
1415 } | |
1416 // Otherwise, the request failed without passing through | |
1417 // DownloadResourceHandler::OnResponseStarted. | |
1418 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason); | |
1419 Interrupt(interrupt_reason); | |
1420 } | |
1421 | |
1422 // **** End of Download progression cascade | 1432 // **** End of Download progression cascade |
1423 | 1433 |
1424 // An error occurred somewhere. | 1434 // An error occurred somewhere. |
1425 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { | 1435 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { |
1426 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1427 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason); | 1437 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason); |
1428 | 1438 |
1429 // Somewhat counter-intuitively, it is possible for us to receive an | 1439 // Somewhat counter-intuitively, it is possible for us to receive an |
1430 // interrupt after we've already been interrupted. The generation of | 1440 // interrupt after we've already been interrupted. The generation of |
1431 // interrupts from the file thread Renames and the generation of | 1441 // interrupts from the file thread Renames and the generation of |
1432 // interrupts from disk writes go through two different mechanisms (driven | 1442 // interrupts from disk writes go through two different mechanisms (driven |
1433 // by rename requests from UI thread and by write requests from IO thread, | 1443 // by rename requests from UI thread and by write requests from IO thread, |
1434 // respectively), and since we choose not to keep state on the File thread, | 1444 // respectively), and since we choose not to keep state on the File thread, |
1435 // this is the place where the races collide. It's also possible for | 1445 // this is the place where the races collide. It's also possible for |
1436 // interrupts to race with cancels. | 1446 // interrupts to race with cancels. |
1437 | 1447 |
1438 // Whatever happens, the first one to hit the UI thread wins. | 1448 // Whatever happens, the first one to hit the UI thread wins. |
1439 if (state_ != IN_PROGRESS_INTERNAL && state_ != RESUMING_INTERNAL) | 1449 if (state_ != IN_PROGRESS_INTERNAL && state_ != RESUMING_INTERNAL) |
1440 return; | 1450 return; |
1441 | 1451 |
1442 last_reason_ = reason; | 1452 last_reason_ = reason; |
1443 | 1453 |
1444 ResumeMode resume_mode = GetResumeMode(); | 1454 ResumeMode resume_mode = GetResumeMode(); |
1445 | 1455 |
1446 if (state_ == IN_PROGRESS_INTERNAL) { | 1456 // Cancel (delete file) if: |
Randy Smith (Not in Mondays)
2014/03/18 21:07:28
So this change is removing a bit of redundancy fro
asanka
2014/03/19 20:37:06
The problem was the handling of downloads that wer
Randy Smith (Not in Mondays)
2014/03/20 15:24:54
We could do this, but my instinct is that we shoul
asanka
2016/02/11 23:57:24
New downloads that start in a failed state need to
Randy Smith (Not in Mondays)
2016/02/12 18:58:10
I feel absolutely no need to resolve this old phil
asanka
2016/02/12 20:52:28
Acknowledged.
| |
1447 // Cancel (delete file) if: | 1457 // 1) we're going to restart. |
1448 // 1) we're going to restart. | 1458 // 2) Resumption isn't possible (download was cancelled or blocked due to |
1449 // 2) Resumption isn't possible (download was cancelled or blocked due to | 1459 // security restrictions). |
1450 // security restrictions). | 1460 // 3) Resumption isn't enabled. |
1451 // 3) Resumption isn't enabled. | 1461 // No point in leaving data around we aren't going to use. |
1452 // No point in leaving data around we aren't going to use. | 1462 if (download_file_.get()) |
1453 ReleaseDownloadFile(resume_mode == RESUME_MODE_IMMEDIATE_RESTART || | 1463 ReleaseDownloadFile(resume_mode == RESUME_MODE_IMMEDIATE_RESTART || |
1454 resume_mode == RESUME_MODE_USER_RESTART || | 1464 resume_mode == RESUME_MODE_USER_RESTART || |
1455 resume_mode == RESUME_MODE_INVALID || | 1465 resume_mode == RESUME_MODE_INVALID || |
1456 !IsDownloadResumptionEnabled()); | 1466 !IsDownloadResumptionEnabled()); |
1457 | 1467 |
1458 // Cancel the originating URL request. | 1468 // Cancel the originating URL request. |
1469 if (request_handle_.get()) | |
1459 request_handle_->CancelRequest(); | 1470 request_handle_->CancelRequest(); |
1460 } else { | |
1461 DCHECK(!download_file_.get()); | |
1462 } | |
1463 | 1471 |
1464 // Reset all data saved, as even if we did save all the data we're going | 1472 // Reset all data saved, as even if we did save all the data we're going to go |
1465 // to go through another round of downloading when we resume. | 1473 // through another round of downloading when we resume. There's a potential |
1466 // There's a potential problem here in the abstract, as if we did download | 1474 // problem here in the abstract, as if we did download all the data and then |
1467 // all the data and then run into a continuable error, on resumption we | 1475 // run into a continuable error, on resumption we won't download any more |
1468 // won't download any more data. However, a) there are currently no | 1476 // data. However, a) there are currently no continuable errors that can occur |
1469 // continuable errors that can occur after we download all the data, and | 1477 // after we download all the data, and b) if there were, that would probably |
1470 // b) if there were, that would probably simply result in a null range | 1478 // simply result in a null range request, which would generate a |
1471 // request, which would generate a DestinationCompleted() notification | 1479 // DestinationCompleted() notification from the DownloadFile, which would |
1472 // from the DownloadFile, which would behave properly with setting | 1480 // behave properly with setting all_data_saved_ to false here. |
1473 // all_data_saved_ to false here. | |
1474 all_data_saved_ = false; | 1481 all_data_saved_ = false; |
1475 | 1482 |
1476 TransitionTo(INTERRUPTED_INTERNAL, DONT_UPDATE_OBSERVERS); | 1483 TransitionTo(INTERRUPTED_INTERNAL, DONT_UPDATE_OBSERVERS); |
1477 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_); | 1484 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_); |
1478 if (!GetWebContents()) | 1485 if (!GetWebContents()) |
1479 RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS); | 1486 RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS); |
1480 | 1487 |
1481 AutoResumeIfValid(); | 1488 AutoResumeIfValid(); |
1482 UpdateObservers(); | 1489 UpdateObservers(); |
1483 } | 1490 } |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1694 | 1701 |
1695 scoped_ptr<DownloadUrlParameters> download_params( | 1702 scoped_ptr<DownloadUrlParameters> download_params( |
1696 DownloadUrlParameters::FromWebContents(GetWebContents(), | 1703 DownloadUrlParameters::FromWebContents(GetWebContents(), |
1697 GetOriginalUrl())); | 1704 GetOriginalUrl())); |
1698 | 1705 |
1699 download_params->set_file_path(GetFullPath()); | 1706 download_params->set_file_path(GetFullPath()); |
1700 download_params->set_offset(GetReceivedBytes()); | 1707 download_params->set_offset(GetReceivedBytes()); |
1701 download_params->set_hash_state(GetHashState()); | 1708 download_params->set_hash_state(GetHashState()); |
1702 download_params->set_last_modified(GetLastModifiedTime()); | 1709 download_params->set_last_modified(GetLastModifiedTime()); |
1703 download_params->set_etag(GetETag()); | 1710 download_params->set_etag(GetETag()); |
1704 download_params->set_callback( | |
1705 base::Bind(&DownloadItemImpl::OnResumeRequestStarted, | |
1706 weak_ptr_factory_.GetWeakPtr())); | |
Randy Smith (Not in Mondays)
2014/03/18 21:07:28
Isn't this assuming that neither of the fall-throu
asanka
2014/03/19 20:37:06
I verified that ResourceHandler::OnResponseComplet
Randy Smith (Not in Mondays)
2014/03/20 18:04:46
What about the places outside DownloadResourceHand
asanka
2016/02/11 23:57:24
RDH::BeginDownload doesn't call the started callba
| |
1707 | 1711 |
1708 delegate_->ResumeInterruptedDownload(download_params.Pass(), GetId()); | 1712 delegate_->ResumeInterruptedDownload(download_params.Pass(), GetId()); |
1709 // Just in case we were interrupted while paused. | 1713 // Just in case we were interrupted while paused. |
1710 is_paused_ = false; | 1714 is_paused_ = false; |
1711 | 1715 |
1712 TransitionTo(RESUMING_INTERNAL, DONT_UPDATE_OBSERVERS); | 1716 TransitionTo(RESUMING_INTERNAL, DONT_UPDATE_OBSERVERS); |
1713 } | 1717 } |
1714 | 1718 |
1715 // static | 1719 // static |
1716 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState( | 1720 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState( |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1787 case RESUME_MODE_USER_CONTINUE: | 1791 case RESUME_MODE_USER_CONTINUE: |
1788 return "USER_CONTINUE"; | 1792 return "USER_CONTINUE"; |
1789 case RESUME_MODE_USER_RESTART: | 1793 case RESUME_MODE_USER_RESTART: |
1790 return "USER_RESTART"; | 1794 return "USER_RESTART"; |
1791 } | 1795 } |
1792 NOTREACHED() << "Unknown resume mode " << mode; | 1796 NOTREACHED() << "Unknown resume mode " << mode; |
1793 return "unknown"; | 1797 return "unknown"; |
1794 } | 1798 } |
1795 | 1799 |
1796 } // namespace content | 1800 } // namespace content |
OLD | NEW |