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

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

Issue 148133007: [Downloads] Always call DM::StartDownload() for explicit downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 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 | Annotate | Revision Log
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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698