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

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: Deal with downloads that are blocked by throttles. Created 4 years, 10 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 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 has_user_gesture_(info.has_user_gesture), 185 has_user_gesture_(info.has_user_gesture),
186 content_disposition_(info.content_disposition), 186 content_disposition_(info.content_disposition),
187 mime_type_(info.mime_type), 187 mime_type_(info.mime_type),
188 original_mime_type_(info.original_mime_type), 188 original_mime_type_(info.original_mime_type),
189 remote_address_(info.remote_address), 189 remote_address_(info.remote_address),
190 total_bytes_(info.total_bytes), 190 total_bytes_(info.total_bytes),
191 received_bytes_(0), 191 received_bytes_(0),
192 bytes_per_sec_(0), 192 bytes_per_sec_(0),
193 last_modified_time_(info.last_modified), 193 last_modified_time_(info.last_modified),
194 etag_(info.etag), 194 etag_(info.etag),
195 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), 195 last_reason_(info.result),
196 start_tick_(base::TimeTicks::Now()), 196 start_tick_(base::TimeTicks::Now()),
197 state_(INITIAL_INTERNAL), 197 state_(INITIAL_INTERNAL),
198 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), 198 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
199 start_time_(info.start_time), 199 start_time_(info.start_time),
200 delegate_(delegate), 200 delegate_(delegate),
201 is_paused_(false), 201 is_paused_(false),
202 auto_resume_count_(0), 202 auto_resume_count_(0),
203 open_when_complete_(false), 203 open_when_complete_(false),
204 file_externally_removed_(false), 204 file_externally_removed_(false),
205 auto_opened_(false), 205 auto_opened_(false),
206 is_temporary_(!info.save_info->file_path.empty()), 206 is_temporary_(!info.save_info->file_path.empty()),
207 all_data_saved_(false), 207 all_data_saved_(false),
208 destination_error_(content::DOWNLOAD_INTERRUPT_REASON_NONE), 208 destination_error_(DOWNLOAD_INTERRUPT_REASON_NONE),
209 opened_(false), 209 opened_(false),
210 delegate_delayed_complete_(false), 210 delegate_delayed_complete_(false),
211 bound_net_log_(bound_net_log), 211 bound_net_log_(bound_net_log),
212 weak_ptr_factory_(this) { 212 weak_ptr_factory_(this) {
213 delegate_->Attach(); 213 delegate_->Attach();
214 Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD); 214 Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD);
215 215
216 // Link the event sources. 216 // Link the event sources.
217 bound_net_log_.AddEvent( 217 bound_net_log_.AddEvent(
218 net::NetLog::TYPE_DOWNLOAD_URL_REQUEST, 218 net::NetLog::TYPE_DOWNLOAD_URL_REQUEST,
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 case INITIAL_INTERNAL: 354 case INITIAL_INTERNAL:
355 case COMPLETING_INTERNAL: 355 case COMPLETING_INTERNAL:
356 case COMPLETE_INTERNAL: 356 case COMPLETE_INTERNAL:
357 case INTERRUPTED_INTERNAL: 357 case INTERRUPTED_INTERNAL:
358 case CANCELLED_INTERNAL: 358 case CANCELLED_INTERNAL:
359 case RESUMING_INTERNAL: 359 case RESUMING_INTERNAL:
360 // No active request. 360 // No active request.
361 return; 361 return;
362 362
363 case TARGET_PENDING_INTERNAL: 363 case TARGET_PENDING_INTERNAL:
364 case INTERRUPTED_TARGET_PENDING_INTERNAL:
364 case TARGET_RESOLVED_INTERNAL: 365 case TARGET_RESOLVED_INTERNAL:
365 case IN_PROGRESS_INTERNAL: 366 case IN_PROGRESS_INTERNAL:
366 request_handle_->PauseRequest(); 367 request_handle_->PauseRequest();
367 is_paused_ = true; 368 is_paused_ = true;
368 UpdateObservers(); 369 UpdateObservers();
369 return; 370 return;
370 371
371 case MAX_DOWNLOAD_INTERNAL_STATE: 372 case MAX_DOWNLOAD_INTERNAL_STATE:
372 NOTREACHED(); 373 NOTREACHED();
373 } 374 }
374 } 375 }
375 376
376 void DownloadItemImpl::Resume() { 377 void DownloadItemImpl::Resume() {
377 DCHECK_CURRENTLY_ON(BrowserThread::UI); 378 DCHECK_CURRENTLY_ON(BrowserThread::UI);
379 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
378 switch (state_) { 380 switch (state_) {
379 case INITIAL_INTERNAL: 381 case INITIAL_INTERNAL:
380 case COMPLETING_INTERNAL: 382 case COMPLETING_INTERNAL:
381 case COMPLETE_INTERNAL: 383 case COMPLETE_INTERNAL:
382 case CANCELLED_INTERNAL: 384 case CANCELLED_INTERNAL:
383 // Nothing to resume. 385 // Nothing to resume.
384 case RESUMING_INTERNAL: 386 case RESUMING_INTERNAL:
385 // Resumption in progress. 387 // Resumption in progress.
386 return; 388 return;
387 389
388 case TARGET_PENDING_INTERNAL: 390 case TARGET_PENDING_INTERNAL:
391 case INTERRUPTED_TARGET_PENDING_INTERNAL:
389 case TARGET_RESOLVED_INTERNAL: 392 case TARGET_RESOLVED_INTERNAL:
390 case IN_PROGRESS_INTERNAL: 393 case IN_PROGRESS_INTERNAL:
391 if (!is_paused_) 394 if (!is_paused_)
392 return; 395 return;
393 request_handle_->ResumeRequest(); 396 request_handle_->ResumeRequest();
394 is_paused_ = false; 397 is_paused_ = false;
395 UpdateObservers(); 398 UpdateObservers();
396 return; 399 return;
397 400
398 case INTERRUPTED_INTERNAL: 401 case INTERRUPTED_INTERNAL:
399 auto_resume_count_ = 0; // User input resets the counter. 402 auto_resume_count_ = 0; // User input resets the counter.
400 ResumeInterruptedDownload(); 403 ResumeInterruptedDownload();
404 UpdateObservers();
401 return; 405 return;
402 406
403 case MAX_DOWNLOAD_INTERNAL_STATE: 407 case MAX_DOWNLOAD_INTERNAL_STATE:
404 NOTREACHED(); 408 NOTREACHED();
405 } 409 }
406 } 410 }
407 411
408 void DownloadItemImpl::Cancel(bool user_cancel) { 412 void DownloadItemImpl::Cancel(bool user_cancel) {
409 DCHECK_CURRENTLY_ON(BrowserThread::UI); 413 DCHECK_CURRENTLY_ON(BrowserThread::UI);
410 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 414 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
411 Interrupt(user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED 415 Interrupt(user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
412 : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN); 416 : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN);
417 UpdateObservers();
413 } 418 }
414 419
415 void DownloadItemImpl::Remove() { 420 void DownloadItemImpl::Remove() {
416 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 421 DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
417 DCHECK_CURRENTLY_ON(BrowserThread::UI); 422 DCHECK_CURRENTLY_ON(BrowserThread::UI);
418 423
419 delegate_->AssertStateConsistent(this); 424 delegate_->AssertStateConsistent(this);
420 Interrupt(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED); 425 Interrupt(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
421 delegate_->AssertStateConsistent(this); 426 delegate_->AssertStateConsistent(this);
422 427
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 DCHECK_CURRENTLY_ON(BrowserThread::UI); 485 DCHECK_CURRENTLY_ON(BrowserThread::UI);
481 switch (state_) { 486 switch (state_) {
482 case INITIAL_INTERNAL: 487 case INITIAL_INTERNAL:
483 case COMPLETING_INTERNAL: 488 case COMPLETING_INTERNAL:
484 case COMPLETE_INTERNAL: 489 case COMPLETE_INTERNAL:
485 case CANCELLED_INTERNAL: 490 case CANCELLED_INTERNAL:
486 case RESUMING_INTERNAL: 491 case RESUMING_INTERNAL:
487 return false; 492 return false;
488 493
489 case TARGET_PENDING_INTERNAL: 494 case TARGET_PENDING_INTERNAL:
495 case INTERRUPTED_TARGET_PENDING_INTERNAL:
490 case TARGET_RESOLVED_INTERNAL: 496 case TARGET_RESOLVED_INTERNAL:
491 case IN_PROGRESS_INTERNAL: 497 case IN_PROGRESS_INTERNAL:
492 return is_paused_; 498 return is_paused_;
493 499
494 case INTERRUPTED_INTERNAL: { 500 case INTERRUPTED_INTERNAL: {
495 ResumeMode resume_mode = GetResumeMode(); 501 ResumeMode resume_mode = GetResumeMode();
496 // Only allow Resume() calls if the resumption mode requires a user 502 // Only allow Resume() calls if the resumption mode requires a user
497 // action. 503 // action.
498 return IsDownloadResumptionEnabled() && 504 return IsDownloadResumptionEnabled() &&
499 (resume_mode == RESUME_MODE_USER_RESTART || 505 (resume_mode == RESUME_MODE_USER_RESTART ||
500 resume_mode == RESUME_MODE_USER_CONTINUE); 506 resume_mode == RESUME_MODE_USER_CONTINUE);
501 } 507 }
502 508
503 case MAX_DOWNLOAD_INTERNAL_STATE: 509 case MAX_DOWNLOAD_INTERNAL_STATE:
504 NOTREACHED(); 510 NOTREACHED();
505 } 511 }
506 return false; 512 return false;
507 } 513 }
508 514
509 bool DownloadItemImpl::IsDone() const { 515 bool DownloadItemImpl::IsDone() const {
510 switch (state_) { 516 switch (state_) {
511 case INITIAL_INTERNAL: 517 case INITIAL_INTERNAL:
512 case COMPLETING_INTERNAL: 518 case COMPLETING_INTERNAL:
513 case RESUMING_INTERNAL: 519 case RESUMING_INTERNAL:
514 case TARGET_PENDING_INTERNAL: 520 case TARGET_PENDING_INTERNAL:
521 case INTERRUPTED_TARGET_PENDING_INTERNAL:
515 case TARGET_RESOLVED_INTERNAL: 522 case TARGET_RESOLVED_INTERNAL:
516 case IN_PROGRESS_INTERNAL: 523 case IN_PROGRESS_INTERNAL:
517 return false; 524 return false;
518 525
519 case COMPLETE_INTERNAL: 526 case COMPLETE_INTERNAL:
520 case CANCELLED_INTERNAL: 527 case CANCELLED_INTERNAL:
521 return true; 528 return true;
522 529
523 case INTERRUPTED_INTERNAL: 530 case INTERRUPTED_INTERNAL:
524 return !CanResume(); 531 return !CanResume();
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 case DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED: 936 case DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
930 case DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM: 937 case DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM:
931 case DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN: 938 case DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN:
932 mode = RESUME_MODE_INVALID; 939 mode = RESUME_MODE_INVALID;
933 break; 940 break;
934 } 941 }
935 942
936 return mode; 943 return mode;
937 } 944 }
938 945
939 void DownloadItemImpl::MergeOriginInfoOnResume( 946 void DownloadItemImpl::UpdateValidatorsOnResumption(
940 const DownloadCreateInfo& new_create_info) { 947 const DownloadCreateInfo& new_create_info) {
941 DCHECK_CURRENTLY_ON(BrowserThread::UI); 948 DCHECK_CURRENTLY_ON(BrowserThread::UI);
942 DCHECK_EQ(RESUMING_INTERNAL, state_); 949 DCHECK_EQ(RESUMING_INTERNAL, state_);
943 DCHECK(!new_create_info.url_chain.empty()); 950 DCHECK(!new_create_info.url_chain.empty());
944 951
945 // We are going to tack on any new redirects to our list of redirects. 952 // We are going to tack on any new redirects to our list of redirects.
946 // When a download is resumed, the URL used for the resumption request is the 953 // When a download is resumed, the URL used for the resumption request is the
947 // one at the end of the previous redirect chain. Tacking additional redirects 954 // one at the end of the previous redirect chain. Tacking additional redirects
948 // to the end of this chain ensures that: 955 // to the end of this chain ensures that:
949 // - If the download needs to be resumed again, the ETag/Last-Modified headers 956 // - If the download needs to be resumed again, the ETag/Last-Modified headers
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 hash_state_ = ""; 1023 hash_state_ = "";
1017 1024
1018 UpdateObservers(); 1025 UpdateObservers();
1019 } 1026 }
1020 1027
1021 void DownloadItemImpl::MarkAsComplete() { 1028 void DownloadItemImpl::MarkAsComplete() {
1022 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1029 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1023 1030
1024 DCHECK(all_data_saved_); 1031 DCHECK(all_data_saved_);
1025 end_time_ = base::Time::Now(); 1032 end_time_ = base::Time::Now();
1026 TransitionTo(COMPLETE_INTERNAL, UPDATE_OBSERVERS); 1033 TransitionTo(COMPLETE_INTERNAL);
1034 UpdateObservers();
1027 } 1035 }
1028 1036
1029 void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far, 1037 void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far,
1030 int64_t bytes_per_sec, 1038 int64_t bytes_per_sec,
1031 const std::string& hash_state) { 1039 const std::string& hash_state) {
1032 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1040 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1033 DVLOG(20) << __FUNCTION__ << " so_far=" << bytes_so_far 1041 DVLOG(20) << __FUNCTION__ << " so_far=" << bytes_so_far
1034 << " per_sec=" << bytes_per_sec << " download=" 1042 << " per_sec=" << bytes_per_sec << " download="
1035 << DebugString(true); 1043 << DebugString(true);
1036 1044
(...skipping 28 matching lines...) Expand all
1065 1073
1066 void DownloadItemImpl::DestinationError(DownloadInterruptReason reason) { 1074 void DownloadItemImpl::DestinationError(DownloadInterruptReason reason) {
1067 DCHECK(state_ == TARGET_PENDING_INTERNAL || 1075 DCHECK(state_ == TARGET_PENDING_INTERNAL ||
1068 state_ == TARGET_RESOLVED_INTERNAL || state_ == IN_PROGRESS_INTERNAL); 1076 state_ == TARGET_RESOLVED_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
1069 DVLOG(20) << __FUNCTION__ 1077 DVLOG(20) << __FUNCTION__
1070 << "() reason:" << DownloadInterruptReasonToString(reason); 1078 << "() reason:" << DownloadInterruptReasonToString(reason);
1071 1079
1072 // Postpone recognition of this error until after file name determination 1080 // Postpone recognition of this error until after file name determination
1073 // has completed and the intermediate file has been renamed to simplify 1081 // has completed and the intermediate file has been renamed to simplify
1074 // resumption conditions. 1082 // resumption conditions.
1075 if (state_ != IN_PROGRESS_INTERNAL) 1083 if (state_ != IN_PROGRESS_INTERNAL) {
1076 destination_error_ = reason; 1084 destination_error_ = reason;
1077 else 1085 return;
1078 Interrupt(reason); 1086 }
1087 Interrupt(reason);
1088 UpdateObservers();
1079 } 1089 }
1080 1090
1081 void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) { 1091 void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) {
1082 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 1092 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
1083 OnAllDataSaved(final_hash); 1093 OnAllDataSaved(final_hash);
1084 MaybeCompleteDownload(); 1094 MaybeCompleteDownload();
1085 } 1095 }
1086 1096
1087 // **** Download progression cascade 1097 // **** Download progression cascade
1088 1098
(...skipping 28 matching lines...) Expand all
1117 bound_net_log_.AddEvent( 1127 bound_net_log_.AddEvent(
1118 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data); 1128 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data);
1119 } 1129 }
1120 1130
1121 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true); 1131 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true);
1122 } 1132 }
1123 1133
1124 // We're starting the download. 1134 // We're starting the download.
1125 void DownloadItemImpl::Start( 1135 void DownloadItemImpl::Start(
1126 scoped_ptr<DownloadFile> file, 1136 scoped_ptr<DownloadFile> file,
1127 scoped_ptr<DownloadRequestHandleInterface> req_handle) { 1137 scoped_ptr<DownloadRequestHandleInterface> req_handle,
1138 const DownloadCreateInfo& new_create_info) {
1128 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1139 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1129 DCHECK(!download_file_.get()); 1140 DCHECK(!download_file_.get());
1130 DCHECK(file.get());
1131 DCHECK(req_handle.get());
1132 DVLOG(20) << __FUNCTION__ << "() this=" << DebugString(true); 1141 DVLOG(20) << __FUNCTION__ << "() this=" << DebugString(true);
1133 1142
1134 download_file_ = std::move(file); 1143 download_file_ = std::move(file);
1135 request_handle_ = std::move(req_handle); 1144 request_handle_ = std::move(req_handle);
1136 1145
1137 if (state_ == CANCELLED_INTERNAL) { 1146 if (state_ == CANCELLED_INTERNAL) {
1138 // The download was in the process of resuming when it was cancelled. Don't 1147 // The download was in the process of resuming when it was cancelled. Don't
1139 // proceed. 1148 // proceed.
1140 ReleaseDownloadFile(true); 1149 ReleaseDownloadFile(true);
1141 request_handle_->CancelRequest(); 1150 if (request_handle_)
1151 request_handle_->CancelRequest();
1142 return; 1152 return;
1143 } 1153 }
1144 1154
1145 TransitionTo(TARGET_PENDING_INTERNAL, UPDATE_OBSERVERS); 1155 // The state could be one of the following:
1156 //
1157 // INITIAL_INTERNAL: A normal download attempt.
1158 //
1159 // RESUMING_INTERNAL: A resumption attempt. May or may not have been
1160 // successful.
1161 DCHECK(state_ == INITIAL_INTERNAL || state_ == RESUMING_INTERNAL);
1162
1163 // If a resumption attempted failed, or if the download was DOA, then the
1164 // download should go back to being interrupted.
1165 if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) {
1166 DCHECK(!download_file_.get());
1167
1168 // For downloads that are interrupted on initiation, invoke target
1169 // determination so that we'll end up with a usable filename.
1170 if (state_ == INITIAL_INTERNAL) {
1171 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
1172 destination_error_ = new_create_info.result;
1173 DetermineDownloadTarget();
1174 return;
1175 }
1176
1177 // Otherwise, this was a resumption attempt which ended with an
1178 // interruption.
1179 Interrupt(new_create_info.result);
1180 UpdateObservers();
1181 return;
1182 }
1183
1184 // Successful download start.
1185 DCHECK(download_file_.get());
1186 DCHECK(request_handle_.get());
1187
1188 if (state_ == RESUMING_INTERNAL)
1189 UpdateValidatorsOnResumption(new_create_info);
1190
1191 TransitionTo(TARGET_PENDING_INTERNAL);
1192 UpdateObservers();
1146 1193
1147 BrowserThread::PostTask( 1194 BrowserThread::PostTask(
1148 BrowserThread::FILE, FROM_HERE, 1195 BrowserThread::FILE, FROM_HERE,
1149 base::Bind(&DownloadFile::Initialize, 1196 base::Bind(&DownloadFile::Initialize,
1150 // Safe because we control download file lifetime. 1197 // Safe because we control download file lifetime.
1151 base::Unretained(download_file_.get()), 1198 base::Unretained(download_file_.get()),
1152 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, 1199 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
1153 weak_ptr_factory_.GetWeakPtr()))); 1200 weak_ptr_factory_.GetWeakPtr())));
1154 } 1201 }
1155 1202
1156 void DownloadItemImpl::OnDownloadFileInitialized( 1203 void DownloadItemImpl::OnDownloadFileInitialized(
1157 DownloadInterruptReason result) { 1204 DownloadInterruptReason result) {
1158 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1205 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1159 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL); 1206 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL);
1160 DVLOG(20) << __FUNCTION__ 1207 DVLOG(20) << __FUNCTION__
1161 << "() result:" << DownloadInterruptReasonToString(result); 1208 << "() result:" << DownloadInterruptReasonToString(result);
1162 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { 1209 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
1163 // Transition out to IN_PROGRESS since this DownloadItem is skipping the 1210 // Whoops. That didn't work. Proceed as an interrupted download. Update the
1164 // download target determination process. 1211 // observers since this is an externally visible transition.
1165 TransitionTo(TARGET_RESOLVED_INTERNAL, DONT_UPDATE_OBSERVERS); 1212 destination_error_ = result;
1166 Interrupt(result); 1213 TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
1167 // TODO(rdsmith/asanka): Arguably we should show this in the UI, but 1214 UpdateObservers();
1168 // it's not at all clear what to show--we haven't done filename
1169 // determination, so we don't know what name to display. OTOH,
1170 // the failure mode of not showing the DI if the file initialization
1171 // fails isn't a good one. Can we hack up a name based on the
1172 // URLRequest? We'll need to make sure that initialization happens
1173 // properly. Possibly the right thing is to have the UI handle
1174 // this case specially.
1175 return;
1176 } 1215 }
1177 1216
1217 DetermineDownloadTarget();
1218 }
1219
1220 void DownloadItemImpl::DetermineDownloadTarget() {
1221 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1222 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true);
1223
1178 delegate_->DetermineDownloadTarget( 1224 delegate_->DetermineDownloadTarget(
1179 this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined, 1225 this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined,
1180 weak_ptr_factory_.GetWeakPtr())); 1226 weak_ptr_factory_.GetWeakPtr()));
1181 } 1227 }
1182 1228
1183 // Called by delegate_ when the download target path has been 1229 // Called by delegate_ when the download target path has been determined.
1184 // determined.
1185 void DownloadItemImpl::OnDownloadTargetDetermined( 1230 void DownloadItemImpl::OnDownloadTargetDetermined(
1186 const base::FilePath& target_path, 1231 const base::FilePath& target_path,
1187 TargetDisposition disposition, 1232 TargetDisposition disposition,
1188 DownloadDangerType danger_type, 1233 DownloadDangerType danger_type,
1189 const base::FilePath& intermediate_path) { 1234 const base::FilePath& intermediate_path) {
1190 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1235 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1191 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL); 1236 DCHECK(state_ == TARGET_PENDING_INTERNAL ||
1237 state_ == INTERRUPTED_TARGET_PENDING_INTERNAL);
1192 1238
1193 // If the |target_path| is empty, then we consider this download to be 1239 // If the |target_path| is empty, then we consider this download to be
1194 // canceled. 1240 // canceled.
1195 if (target_path.empty()) { 1241 if (target_path.empty()) {
1196 Cancel(true); 1242 Cancel(true);
1197 return; 1243 return;
1198 } 1244 }
1199 1245
1200 // TODO(rdsmith,asanka): We are ignoring the possibility that the download
1201 // has been interrupted at this point until we finish the intermediate
1202 // rename and set the full path. That's dangerous, because we might race
1203 // with resumption, either manual (because the interrupt is visible to the
1204 // UI) or automatic. If we keep the "ignore an error on download until file
1205 // name determination complete" semantics, we need to make sure that the
1206 // error is kept completely invisible until that point.
1207
1208 DVLOG(20) << __FUNCTION__ << " " << target_path.value() << " " << disposition 1246 DVLOG(20) << __FUNCTION__ << " " << target_path.value() << " " << disposition
1209 << " " << danger_type << " " << DebugString(true); 1247 << " " << danger_type << " " << DebugString(true);
1210 1248
1211 target_path_ = target_path; 1249 target_path_ = target_path;
1212 target_disposition_ = disposition; 1250 target_disposition_ = disposition;
1213 SetDangerType(danger_type); 1251 SetDangerType(danger_type);
1214 1252
1253 // This was an interrupted download that was looking for a filename. Now that
1254 // it has one, transition to interrupted.
1255 if (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL) {
1256 Interrupt(destination_error_);
1257 UpdateObservers();
1258 return;
1259 }
1260
1215 // We want the intermediate and target paths to refer to the same directory so 1261 // We want the intermediate and target paths to refer to the same directory so
1216 // that they are both on the same device and subject to same 1262 // that they are both on the same device and subject to same
1217 // space/permission/availability constraints. 1263 // space/permission/availability constraints.
1218 DCHECK(intermediate_path.DirName() == target_path.DirName()); 1264 DCHECK(intermediate_path.DirName() == target_path.DirName());
1219 1265
1220 // During resumption, we may choose to proceed with the same intermediate 1266 // During resumption, we may choose to proceed with the same intermediate
1221 // file. No rename is necessary if our intermediate file already has the 1267 // file. No rename is necessary if our intermediate file already has the
1222 // correct name. 1268 // correct name.
1223 // 1269 //
1224 // The intermediate name may change from its original value during filename 1270 // The intermediate name may change from its original value during filename
(...skipping 22 matching lines...) Expand all
1247 base::Unretained(download_file_.get()), 1293 base::Unretained(download_file_.get()),
1248 intermediate_path, callback)); 1294 intermediate_path, callback));
1249 } 1295 }
1250 1296
1251 void DownloadItemImpl::OnDownloadRenamedToIntermediateName( 1297 void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
1252 DownloadInterruptReason reason, 1298 DownloadInterruptReason reason,
1253 const base::FilePath& full_path) { 1299 const base::FilePath& full_path) {
1254 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1300 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1255 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL); 1301 DCHECK_EQ(state_, TARGET_PENDING_INTERNAL);
1256 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 1302 DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
1257 TransitionTo(TARGET_RESOLVED_INTERNAL, DONT_UPDATE_OBSERVERS); 1303 TransitionTo(TARGET_RESOLVED_INTERNAL);
1258 1304
1259 if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) { 1305 if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) {
1260 // Process destination error. If both |reason| and |destination_error_| 1306 // Process destination error. If both |reason| and |destination_error_|
1261 // refer to actual errors, we want to use the |destination_error_| as the 1307 // refer to actual errors, we want to use the |destination_error_| as the
1262 // argument to the Interrupt() routine, as it happened first. 1308 // argument to the Interrupt() routine, as it happened first.
1263 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE) 1309 if (reason == DOWNLOAD_INTERRUPT_REASON_NONE)
1264 SetFullPath(full_path); 1310 SetFullPath(full_path);
1265 Interrupt(destination_error_); 1311 Interrupt(destination_error_);
1266 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE; 1312 destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
1267 } else if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1313 } else if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1268 Interrupt(reason); 1314 Interrupt(reason);
1269 // All file errors result in file deletion above; no need to cleanup. The 1315 // All file errors result in file deletion above; no need to cleanup. The
1270 // current_path_ should be empty. Resuming this download will force a 1316 // current_path_ should be empty. Resuming this download will force a
1271 // restart and a re-doing of filename determination. 1317 // restart and a re-doing of filename determination.
1272 DCHECK(current_path_.empty()); 1318 DCHECK(current_path_.empty());
1273 } else { 1319 } else {
1274 SetFullPath(full_path); 1320 SetFullPath(full_path);
1275 TransitionTo(IN_PROGRESS_INTERNAL, UPDATE_OBSERVERS); 1321 TransitionTo(IN_PROGRESS_INTERNAL);
1276 MaybeCompleteDownload(); 1322 MaybeCompleteDownload();
1277 } 1323 }
1324 UpdateObservers();
1278 } 1325 }
1279 1326
1280 // When SavePackage downloads MHTML to GData (see 1327 // When SavePackage downloads MHTML to GData (see
1281 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it 1328 // SavePackageFilePickerChromeOS), GData calls MaybeCompleteDownload() like it
1282 // does for non-SavePackage downloads, but SavePackage downloads never satisfy 1329 // does for non-SavePackage downloads, but SavePackage downloads never satisfy
1283 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls 1330 // IsDownloadReadyForCompletion(). GDataDownloadObserver manually calls
1284 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage 1331 // DownloadItem::UpdateObservers() when the upload completes so that SavePackage
1285 // notices that the upload has completed and runs its normal Finish() pathway. 1332 // notices that the upload has completed and runs its normal Finish() pathway.
1286 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes 1333 // MaybeCompleteDownload() is never the mechanism by which SavePackage completes
1287 // downloads. SavePackage always uses its own Finish() to mark downloads 1334 // downloads. SavePackage always uses its own Finish() to mark downloads
(...skipping 25 matching lines...) Expand all
1313 return; 1360 return;
1314 1361
1315 DVLOG(20) << __FUNCTION__ << "()" 1362 DVLOG(20) << __FUNCTION__ << "()"
1316 << " " << DebugString(true); 1363 << " " << DebugString(true);
1317 DCHECK(!GetTargetFilePath().empty()); 1364 DCHECK(!GetTargetFilePath().empty());
1318 DCHECK(!IsDangerous()); 1365 DCHECK(!IsDangerous());
1319 1366
1320 // TODO(rdsmith/benjhayden): Remove as part of SavePackage integration. 1367 // TODO(rdsmith/benjhayden): Remove as part of SavePackage integration.
1321 if (is_save_package_download_) { 1368 if (is_save_package_download_) {
1322 // Avoid doing anything on the file thread; there's nothing we control 1369 // Avoid doing anything on the file thread; there's nothing we control
1323 // there. 1370 // there. Strictly speaking, this skips giving the embedder a chance to
1324 // Strictly speaking, this skips giving the embedder a chance to open 1371 // open the download. But on a save package download, there's no real
1325 // the download. But on a save package download, there's no real
1326 // concept of opening. 1372 // concept of opening.
1327 Completed(); 1373 Completed();
1328 return; 1374 return;
1329 } 1375 }
1330 1376
1331 DCHECK(download_file_.get()); 1377 DCHECK(download_file_.get());
1332 // Unilaterally rename; even if it already has the right name, 1378 // Unilaterally rename; even if it already has the right name,
1333 // we need theannotation. 1379 // we need theannotation.
1334 DownloadFile::RenameCompletionCallback callback = 1380 DownloadFile::RenameCompletionCallback callback =
1335 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, 1381 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
(...skipping 20 matching lines...) Expand all
1356 DVLOG(20) << __FUNCTION__ << "()" 1402 DVLOG(20) << __FUNCTION__ << "()"
1357 << " full_path = \"" << full_path.value() << "\"" 1403 << " full_path = \"" << full_path.value() << "\""
1358 << " " << DebugString(false); 1404 << " " << DebugString(false);
1359 1405
1360 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1406 if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1361 Interrupt(reason); 1407 Interrupt(reason);
1362 1408
1363 // All file errors should have resulted in in file deletion above. On 1409 // All file errors should have resulted in in file deletion above. On
1364 // resumption we will need to re-do filename determination. 1410 // resumption we will need to re-do filename determination.
1365 DCHECK(current_path_.empty()); 1411 DCHECK(current_path_.empty());
1412 UpdateObservers();
1366 return; 1413 return;
1367 } 1414 }
1368 1415
1369 DCHECK(target_path_ == full_path); 1416 DCHECK(target_path_ == full_path);
1370 1417
1371 if (full_path != current_path_) { 1418 if (full_path != current_path_) {
1372 // full_path is now the current and target file path. 1419 // full_path is now the current and target file path.
1373 DCHECK(!full_path.empty()); 1420 DCHECK(!full_path.empty());
1374 SetFullPath(full_path); 1421 SetFullPath(full_path);
1375 } 1422 }
1376 1423
1377 // Complete the download and release the DownloadFile. 1424 // Complete the download and release the DownloadFile.
1378 DCHECK(download_file_); 1425 DCHECK(download_file_);
1379 ReleaseDownloadFile(false); 1426 ReleaseDownloadFile(false);
1380 1427
1381 // We're not completely done with the download item yet, but at this 1428 // We're not completely done with the download item yet, but at this
1382 // point we're committed to complete the download. Cancels (or Interrupts, 1429 // point we're committed to complete the download. Cancels (or Interrupts,
1383 // though it's not clear how they could happen) after this point will be 1430 // though it's not clear how they could happen) after this point will be
1384 // ignored. 1431 // ignored.
1385 TransitionTo(COMPLETING_INTERNAL, DONT_UPDATE_OBSERVERS); 1432 TransitionTo(COMPLETING_INTERNAL);
1386 1433
1387 if (delegate_->ShouldOpenDownload( 1434 if (delegate_->ShouldOpenDownload(
1388 this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened, 1435 this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened,
1389 weak_ptr_factory_.GetWeakPtr()))) { 1436 weak_ptr_factory_.GetWeakPtr()))) {
1390 Completed(); 1437 Completed();
1391 } else { 1438 } else {
1392 delegate_delayed_complete_ = true; 1439 delegate_delayed_complete_ = true;
1393 UpdateObservers(); 1440 UpdateObservers();
1394 } 1441 }
1395 } 1442 }
1396 1443
1397 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { 1444 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) {
1398 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1445 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1399 1446
1400 auto_opened_ = auto_opened; 1447 auto_opened_ = auto_opened;
1401 Completed(); 1448 Completed();
1402 } 1449 }
1403 1450
1404 void DownloadItemImpl::Completed() { 1451 void DownloadItemImpl::Completed() {
1405 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1452 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1406 1453
1407 DVLOG(20) << __FUNCTION__ << "() " << DebugString(false); 1454 DVLOG(20) << __FUNCTION__ << "() " << DebugString(false);
1408 1455
1409 DCHECK(all_data_saved_); 1456 DCHECK(all_data_saved_);
1410 end_time_ = base::Time::Now(); 1457 end_time_ = base::Time::Now();
1411 TransitionTo(COMPLETE_INTERNAL, UPDATE_OBSERVERS); 1458 TransitionTo(COMPLETE_INTERNAL);
1459 UpdateObservers();
1412 RecordDownloadCompleted(start_tick_, received_bytes_); 1460 RecordDownloadCompleted(start_tick_, received_bytes_);
1413 1461
1414 if (auto_opened_) { 1462 if (auto_opened_) {
1415 // If it was already handled by the delegate, do nothing. 1463 // If it was already handled by the delegate, do nothing.
1416 } else if (GetOpenWhenComplete() || 1464 } else if (GetOpenWhenComplete() ||
1417 ShouldOpenFileBasedOnExtension() || 1465 ShouldOpenFileBasedOnExtension() ||
1418 IsTemporary()) { 1466 IsTemporary()) {
1419 // If the download is temporary, like in drag-and-drop, do not open it but 1467 // If the download is temporary, like in drag-and-drop, do not open it but
1420 // we still need to set it auto-opened so that it can be removed from the 1468 // we still need to set it auto-opened so that it can be removed from the
1421 // download shelf. 1469 // download shelf.
1422 if (!IsTemporary()) 1470 if (!IsTemporary())
1423 OpenDownload(); 1471 OpenDownload();
1424 1472
1425 auto_opened_ = true; 1473 auto_opened_ = true;
1426 UpdateObservers(); 1474 UpdateObservers();
1427 } 1475 }
1428 } 1476 }
1429 1477
1430 void DownloadItemImpl::OnResumeRequestStarted(
1431 DownloadItem* item,
1432 DownloadInterruptReason interrupt_reason) {
1433 // If |item| is not NULL, then Start() has been called already, and nothing
1434 // more needs to be done here.
1435 if (item) {
1436 DCHECK_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
1437 DCHECK_EQ(static_cast<DownloadItem*>(this), item);
1438 return;
1439 }
1440 // Otherwise, the request failed without passing through
1441 // DownloadResourceHandler::OnResponseStarted.
1442 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
1443 Interrupt(interrupt_reason);
1444 }
1445
1446 // **** End of Download progression cascade 1478 // **** End of Download progression cascade
1447 1479
1448 // An error occurred somewhere. 1480 // An error occurred somewhere.
1449 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { 1481 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) {
1450 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1482 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1451 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason); 1483 DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason);
1452 DVLOG(20) << __FUNCTION__ 1484 DVLOG(20) << __FUNCTION__
1453 << "() reason:" << DownloadInterruptReasonToString(reason) 1485 << "() reason:" << DownloadInterruptReasonToString(reason)
1454 << " this=" << DebugString(true); 1486 << " this=" << DebugString(true);
1455 1487
(...skipping 13 matching lines...) Expand all
1469 case COMPLETE_INTERNAL: 1501 case COMPLETE_INTERNAL:
1470 // Already complete. 1502 // Already complete.
1471 return; 1503 return;
1472 1504
1473 case TARGET_PENDING_INTERNAL: 1505 case TARGET_PENDING_INTERNAL:
1474 case TARGET_RESOLVED_INTERNAL: 1506 case TARGET_RESOLVED_INTERNAL:
1475 case IN_PROGRESS_INTERNAL: 1507 case IN_PROGRESS_INTERNAL:
1476 break; 1508 break;
1477 1509
1478 case RESUMING_INTERNAL: 1510 case RESUMING_INTERNAL:
1511 case INTERRUPTED_TARGET_PENDING_INTERNAL:
1479 case INTERRUPTED_INTERNAL: 1512 case INTERRUPTED_INTERNAL:
1480 // The first non-cancel interrupt reason wins in cases where multiple 1513 // The first non-cancel interrupt reason wins in cases where multiple
1481 // things go wrong. 1514 // things go wrong.
1482 if (reason != DOWNLOAD_INTERRUPT_REASON_USER_CANCELED && 1515 if (reason != DOWNLOAD_INTERRUPT_REASON_USER_CANCELED &&
1483 reason != DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) 1516 reason != DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN)
1484 return; 1517 return;
1485 1518
1486 if (!current_path_.empty()) { 1519 if (!current_path_.empty()) {
1487 BrowserThread::PostTask( 1520 BrowserThread::PostTask(
1488 BrowserThread::FILE, FROM_HERE, 1521 BrowserThread::FILE, FROM_HERE,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1523 reason == DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) { 1556 reason == DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) {
1524 if (IsDangerous()) { 1557 if (IsDangerous()) {
1525 RecordDangerousDownloadDiscard( 1558 RecordDangerousDownloadDiscard(
1526 reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED 1559 reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
1527 ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION 1560 ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION
1528 : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN, 1561 : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN,
1529 GetDangerType(), GetTargetFilePath()); 1562 GetDangerType(), GetTargetFilePath());
1530 } 1563 }
1531 1564
1532 RecordDownloadCount(CANCELLED_COUNT); 1565 RecordDownloadCount(CANCELLED_COUNT);
1533 TransitionTo(CANCELLED_INTERNAL, DONT_UPDATE_OBSERVERS); 1566 TransitionTo(CANCELLED_INTERNAL);
asanka 2016/02/11 23:57:25 Needs an UpdateObservers() call.
Randy Smith (Not in Mondays) 2016/02/12 18:58:10 This looks like a note you made to yourself that y
asanka 2016/02/12 20:52:28 Stale. We've relieved Interrupt() of the responsib
1534 } else { 1567 return;
1535 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_);
1536 if (!GetWebContents())
1537 RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS);
1538 TransitionTo(INTERRUPTED_INTERNAL, DONT_UPDATE_OBSERVERS);
1539 AutoResumeIfValid();
1540 } 1568 }
1541 1569
1542 UpdateObservers(); 1570 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_);
1571 if (!GetWebContents())
1572 RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS);
1573
1574 TransitionTo(INTERRUPTED_INTERNAL);
1575 AutoResumeIfValid();
1543 } 1576 }
1544 1577
1545 void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) { 1578 void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) {
1546 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1579 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1547 DVLOG(20) << __FUNCTION__ << "() destroy_file:" << destroy_file; 1580 DVLOG(20) << __FUNCTION__ << "() destroy_file:" << destroy_file;
1548 1581
1549 if (destroy_file) { 1582 if (destroy_file) {
1550 BrowserThread::PostTask( 1583 BrowserThread::PostTask(
1551 BrowserThread::FILE, FROM_HERE, 1584 BrowserThread::FILE, FROM_HERE,
1552 // Will be deleted at end of task execution. 1585 // Will be deleted at end of task execution.
(...skipping 25 matching lines...) Expand all
1578 // If we don't have all the data, the download is not ready for 1611 // If we don't have all the data, the download is not ready for
1579 // completion. 1612 // completion.
1580 if (!AllDataSaved()) 1613 if (!AllDataSaved())
1581 return false; 1614 return false;
1582 1615
1583 // If the download is dangerous, but not yet validated, it's not ready for 1616 // If the download is dangerous, but not yet validated, it's not ready for
1584 // completion. 1617 // completion.
1585 if (IsDangerous()) 1618 if (IsDangerous())
1586 return false; 1619 return false;
1587 1620
1588 // Invariants for the IN_PROGRESS state. DCHECKs here verify that the 1621 // Check for consistency before invoking delegate. Since there are no pending
1589 // invariants are still true. 1622 // target determination calls and the download is in progress, both the target
1623 // and current paths should be non-empty and they should point to the same
1624 // directory.
1590 DCHECK(!target_path_.empty()); 1625 DCHECK(!target_path_.empty());
1591 DCHECK(!current_path_.empty()); 1626 DCHECK(!current_path_.empty());
1592 DCHECK(target_path_.DirName() == current_path_.DirName()); 1627 DCHECK(target_path_.DirName() == current_path_.DirName());
1593 1628
1594 // Give the delegate a chance to hold up a stop sign. It'll call 1629 // Give the delegate a chance to hold up a stop sign. It'll call
1595 // use back through the passed callback if it does and that state changes. 1630 // use back through the passed callback if it does and that state changes.
1596 if (!delegate_->ShouldCompleteDownload(this, state_change_notification)) 1631 if (!delegate_->ShouldCompleteDownload(this, state_change_notification))
1597 return false; 1632 return false;
1598 1633
1599 return true; 1634 return true;
1600 } 1635 }
1601 1636
1602 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state, 1637 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {
1603 ShouldUpdateObservers notify_action) {
1604 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1638 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1605 1639
1606 if (state_ == new_state) 1640 if (state_ == new_state)
1607 return; 1641 return;
1608 1642
1609 DownloadInternalState old_state = state_; 1643 DownloadInternalState old_state = state_;
1610 state_ = new_state; 1644 state_ = new_state;
1611 1645
1612 DCHECK(is_save_package_download_ 1646 DCHECK(is_save_package_download_
1613 ? IsValidSavePackageStateTransition(old_state, new_state) 1647 ? IsValidSavePackageStateTransition(old_state, new_state)
1614 : IsValidStateTransition(old_state, new_state)) 1648 : IsValidStateTransition(old_state, new_state))
1615 << "Invalid state transition from:" << DebugDownloadStateString(old_state) 1649 << "Invalid state transition from:" << DebugDownloadStateString(old_state)
1616 << " to:" << DebugDownloadStateString(new_state); 1650 << " to:" << DebugDownloadStateString(new_state);
1617 1651
1618 switch (state_) { 1652 switch (state_) {
1619 case INITIAL_INTERNAL: 1653 case INITIAL_INTERNAL:
1620 NOTREACHED(); 1654 NOTREACHED();
1621 break; 1655 break;
1622 1656
1623 case TARGET_PENDING_INTERNAL: 1657 case TARGET_PENDING_INTERNAL:
1624 case TARGET_RESOLVED_INTERNAL: 1658 case TARGET_RESOLVED_INTERNAL:
1659 case INTERRUPTED_TARGET_PENDING_INTERNAL:
1625 break; 1660 break;
1626 1661
1627 case IN_PROGRESS_INTERNAL: 1662 case IN_PROGRESS_INTERNAL:
1628 DCHECK(!current_path_.empty()) << "Current output path must be known."; 1663 DCHECK(!current_path_.empty()) << "Current output path must be known.";
1629 DCHECK(!target_path_.empty()) << "Target path must be known."; 1664 DCHECK(!target_path_.empty()) << "Target path must be known.";
1630 DCHECK(current_path_.DirName() == target_path_.DirName()) 1665 DCHECK(current_path_.DirName() == target_path_.DirName())
1631 << "Current output directory must match target directory."; 1666 << "Current output directory must match target directory.";
1632 DCHECK(download_file_) << "Output file must be owned by download item."; 1667 DCHECK(download_file_) << "Output file must be owned by download item.";
1633 DCHECK(request_handle_) << "Download source must be active."; 1668 DCHECK(request_handle_) << "Download source must be active.";
1634 DCHECK(!is_paused_) << "At the time a download enters IN_PROGRESS state, " 1669 DCHECK(!is_paused_) << "At the time a download enters IN_PROGRESS state, "
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1697 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE); 1732 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE);
1698 1733
1699 // Resumption 1734 // Resumption
1700 if (was_done && !is_done) { 1735 if (was_done && !is_done) {
1701 std::string file_name(target_path_.BaseName().AsUTF8Unsafe()); 1736 std::string file_name(target_path_.BaseName().AsUTF8Unsafe());
1702 bound_net_log_.BeginEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, 1737 bound_net_log_.BeginEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE,
1703 base::Bind(&ItemActivatedNetLogCallback, 1738 base::Bind(&ItemActivatedNetLogCallback,
1704 this, SRC_ACTIVE_DOWNLOAD, 1739 this, SRC_ACTIVE_DOWNLOAD,
1705 &file_name)); 1740 &file_name));
1706 } 1741 }
1707
1708 if (notify_action == UPDATE_OBSERVERS)
1709 UpdateObservers();
1710 } 1742 }
1711 1743
1712 void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) { 1744 void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) {
1713 if (danger_type != danger_type_) { 1745 if (danger_type != danger_type_) {
1714 bound_net_log_.AddEvent( 1746 bound_net_log_.AddEvent(
1715 net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED, 1747 net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED,
1716 base::Bind(&ItemCheckedNetLogCallback, danger_type)); 1748 base::Bind(&ItemCheckedNetLogCallback, danger_type));
1717 } 1749 }
1718 // Only record the Malicious UMA stat if it's going from {not malicious} -> 1750 // Only record the Malicious UMA stat if it's going from {not malicious} ->
1719 // {malicious}. 1751 // {malicious}.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1761 1793
1762 void DownloadItemImpl::ResumeInterruptedDownload() { 1794 void DownloadItemImpl::ResumeInterruptedDownload() {
1763 DCHECK_CURRENTLY_ON(BrowserThread::UI); 1795 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1764 if (!IsDownloadResumptionEnabled()) 1796 if (!IsDownloadResumptionEnabled())
1765 return; 1797 return;
1766 1798
1767 // If we're not interrupted, ignore the request; our caller is drunk. 1799 // If we're not interrupted, ignore the request; our caller is drunk.
1768 if (state_ != INTERRUPTED_INTERNAL) 1800 if (state_ != INTERRUPTED_INTERNAL)
1769 return; 1801 return;
1770 1802
1803 // We are starting a new request. Shake off all pending operations.
1804 DCHECK(!download_file_);
1805 weak_ptr_factory_.InvalidateWeakPtrs();
asanka 2016/02/11 23:57:25 Perhaps we should do this when the previous reques
Randy Smith (Not in Mondays) 2016/02/12 18:58:10 I think we do (given that Interrupt() does a Relea
asanka 2016/02/12 20:52:28 This was a note to self to check. It is possible t
1806
1771 // Reset the appropriate state if restarting. 1807 // Reset the appropriate state if restarting.
1772 ResumeMode mode = GetResumeMode(); 1808 ResumeMode mode = GetResumeMode();
1773 if (mode == RESUME_MODE_IMMEDIATE_RESTART || 1809 if (mode == RESUME_MODE_IMMEDIATE_RESTART ||
1774 mode == RESUME_MODE_USER_RESTART) { 1810 mode == RESUME_MODE_USER_RESTART) {
1775 received_bytes_ = 0; 1811 received_bytes_ = 0;
1776 hash_state_ = ""; 1812 hash_state_ = "";
1777 last_modified_time_ = ""; 1813 last_modified_time_ = "";
1778 etag_ = ""; 1814 etag_ = "";
1779 } 1815 }
1780 1816
1781 scoped_ptr<DownloadUrlParameters> download_params; 1817 scoped_ptr<DownloadUrlParameters> download_params;
1782 if (GetWebContents()) { 1818 if (GetWebContents()) {
1783 download_params = 1819 download_params =
1784 DownloadUrlParameters::FromWebContents(GetWebContents(), GetURL()); 1820 DownloadUrlParameters::FromWebContents(GetWebContents(), GetURL());
1785 } else { 1821 } else {
1786 download_params = make_scoped_ptr(new DownloadUrlParameters( 1822 download_params = make_scoped_ptr(new DownloadUrlParameters(
1787 GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext())); 1823 GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext()));
1788 } 1824 }
1789 1825
1790 download_params->set_file_path(GetFullPath()); 1826 download_params->set_file_path(GetFullPath());
1791 download_params->set_offset(GetReceivedBytes()); 1827 download_params->set_offset(GetReceivedBytes());
1792 download_params->set_hash_state(GetHashState()); 1828 download_params->set_hash_state(GetHashState());
1793 download_params->set_last_modified(GetLastModifiedTime()); 1829 download_params->set_last_modified(GetLastModifiedTime());
1794 download_params->set_etag(GetETag()); 1830 download_params->set_etag(GetETag());
1795 download_params->set_callback(
1796 base::Bind(&DownloadItemImpl::OnResumeRequestStarted,
1797 weak_ptr_factory_.GetWeakPtr()));
1798 1831
1799 TransitionTo(RESUMING_INTERNAL, DONT_UPDATE_OBSERVERS); 1832 TransitionTo(RESUMING_INTERNAL);
1800 delegate_->ResumeInterruptedDownload(std::move(download_params), GetId()); 1833 delegate_->ResumeInterruptedDownload(std::move(download_params), GetId());
1801 // Just in case we were interrupted while paused. 1834 // Just in case we were interrupted while paused.
1802 is_paused_ = false; 1835 is_paused_ = false;
1803 } 1836 }
1804 1837
1805 // static 1838 // static
1806 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState( 1839 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState(
1807 DownloadInternalState internal_state) { 1840 DownloadInternalState internal_state) {
1808 switch (internal_state) { 1841 switch (internal_state) {
1809 case INITIAL_INTERNAL: 1842 case INITIAL_INTERNAL:
1810 case TARGET_PENDING_INTERNAL: 1843 case TARGET_PENDING_INTERNAL:
1811 case TARGET_RESOLVED_INTERNAL: 1844 case TARGET_RESOLVED_INTERNAL:
1812 // TODO(asanka): Introduce an externally visible state to distinguish 1845 // TODO(asanka): Introduce an externally visible state to distinguish
1813 // between the above states and IN_PROGRESS_INTERNAL. The latter (the 1846 // between the above states and IN_PROGRESS_INTERNAL. The latter (the
1814 // state where the download is active and has a known target) is the state 1847 // state where the download is active and has a known target) is the state
1815 // that most external users are interested in. 1848 // that most external users are interested in.
1816 case IN_PROGRESS_INTERNAL: 1849 case IN_PROGRESS_INTERNAL:
1817 return IN_PROGRESS; 1850 return IN_PROGRESS;
1818 case COMPLETING_INTERNAL: 1851 case COMPLETING_INTERNAL:
1819 return IN_PROGRESS; 1852 return IN_PROGRESS;
1820 case COMPLETE_INTERNAL: 1853 case COMPLETE_INTERNAL:
1821 return COMPLETE; 1854 return COMPLETE;
1822 case CANCELLED_INTERNAL: 1855 case CANCELLED_INTERNAL:
1823 return CANCELLED; 1856 return CANCELLED;
1857 case INTERRUPTED_TARGET_PENDING_INTERNAL:
1824 case INTERRUPTED_INTERNAL: 1858 case INTERRUPTED_INTERNAL:
1825 return INTERRUPTED; 1859 return INTERRUPTED;
1826 case RESUMING_INTERNAL: 1860 case RESUMING_INTERNAL:
1827 return IN_PROGRESS; 1861 return IN_PROGRESS;
1828 case MAX_DOWNLOAD_INTERNAL_STATE: 1862 case MAX_DOWNLOAD_INTERNAL_STATE:
1829 break; 1863 break;
1830 } 1864 }
1831 NOTREACHED(); 1865 NOTREACHED();
1832 return MAX_DOWNLOAD_STATE; 1866 return MAX_DOWNLOAD_STATE;
1833 } 1867 }
(...skipping 18 matching lines...) Expand all
1852 } 1886 }
1853 1887
1854 #if DCHECK_IS_ON() 1888 #if DCHECK_IS_ON()
1855 // static 1889 // static
1856 bool DownloadItemImpl::IsValidSavePackageStateTransition( 1890 bool DownloadItemImpl::IsValidSavePackageStateTransition(
1857 DownloadInternalState from, 1891 DownloadInternalState from,
1858 DownloadInternalState to) { 1892 DownloadInternalState to) {
1859 switch (from) { 1893 switch (from) {
1860 case INITIAL_INTERNAL: 1894 case INITIAL_INTERNAL:
1861 case TARGET_PENDING_INTERNAL: 1895 case TARGET_PENDING_INTERNAL:
1896 case INTERRUPTED_TARGET_PENDING_INTERNAL:
1862 case TARGET_RESOLVED_INTERNAL: 1897 case TARGET_RESOLVED_INTERNAL:
1863 case COMPLETING_INTERNAL: 1898 case COMPLETING_INTERNAL:
1864 case COMPLETE_INTERNAL: 1899 case COMPLETE_INTERNAL:
1865 case INTERRUPTED_INTERNAL: 1900 case INTERRUPTED_INTERNAL:
1866 case RESUMING_INTERNAL: 1901 case RESUMING_INTERNAL:
1867 case CANCELLED_INTERNAL: 1902 case CANCELLED_INTERNAL:
1868 return false; 1903 return false;
1869 1904
1870 case IN_PROGRESS_INTERNAL: 1905 case IN_PROGRESS_INTERNAL:
1871 return to == CANCELLED_INTERNAL || COMPLETE_INTERNAL; 1906 return to == CANCELLED_INTERNAL || COMPLETE_INTERNAL;
1872 1907
1873 case MAX_DOWNLOAD_INTERNAL_STATE: 1908 case MAX_DOWNLOAD_INTERNAL_STATE:
1874 NOTREACHED(); 1909 NOTREACHED();
1875 } 1910 }
1876 return false; 1911 return false;
1877 } 1912 }
1878 1913
1879 // static 1914 // static
1880 bool DownloadItemImpl::IsValidStateTransition(DownloadInternalState from, 1915 bool DownloadItemImpl::IsValidStateTransition(DownloadInternalState from,
1881 DownloadInternalState to) { 1916 DownloadInternalState to) {
1882 switch (from) { 1917 switch (from) {
1883 case INITIAL_INTERNAL: 1918 case INITIAL_INTERNAL:
1884 return to == TARGET_PENDING_INTERNAL || to == INTERRUPTED_INTERNAL; 1919 return to == TARGET_PENDING_INTERNAL ||
1920 to == INTERRUPTED_TARGET_PENDING_INTERNAL;
1885 1921
1886 case TARGET_PENDING_INTERNAL: 1922 case TARGET_PENDING_INTERNAL:
1887 return to == TARGET_RESOLVED_INTERNAL || to == CANCELLED_INTERNAL; 1923 return to == INTERRUPTED_TARGET_PENDING_INTERNAL ||
1924 to == TARGET_RESOLVED_INTERNAL || to == CANCELLED_INTERNAL;
1925
1926 case INTERRUPTED_TARGET_PENDING_INTERNAL:
1927 return to == INTERRUPTED_INTERNAL || to == CANCELLED_INTERNAL;
1888 1928
1889 case TARGET_RESOLVED_INTERNAL: 1929 case TARGET_RESOLVED_INTERNAL:
1890 return to == IN_PROGRESS_INTERNAL || to == INTERRUPTED_INTERNAL || 1930 return to == IN_PROGRESS_INTERNAL || to == INTERRUPTED_INTERNAL ||
1891 to == CANCELLED_INTERNAL; 1931 to == CANCELLED_INTERNAL;
1892 1932
1893 case IN_PROGRESS_INTERNAL: 1933 case IN_PROGRESS_INTERNAL:
1894 return to == COMPLETING_INTERNAL || to == CANCELLED_INTERNAL || 1934 return to == COMPLETING_INTERNAL || to == CANCELLED_INTERNAL ||
1895 to == INTERRUPTED_INTERNAL; 1935 to == INTERRUPTED_INTERNAL;
1896 1936
1897 case COMPLETING_INTERNAL: 1937 case COMPLETING_INTERNAL:
1898 return to == COMPLETE_INTERNAL; 1938 return to == COMPLETE_INTERNAL;
1899 1939
1900 case COMPLETE_INTERNAL: 1940 case COMPLETE_INTERNAL:
1901 return false; 1941 return false;
1902 1942
1903 case INTERRUPTED_INTERNAL: 1943 case INTERRUPTED_INTERNAL:
1904 return to == RESUMING_INTERNAL || to == CANCELLED_INTERNAL; 1944 return to == RESUMING_INTERNAL || to == CANCELLED_INTERNAL;
1905 1945
1906 case RESUMING_INTERNAL: 1946 case RESUMING_INTERNAL:
1907 return to == TARGET_PENDING_INTERNAL || to == CANCELLED_INTERNAL; 1947 return to == TARGET_PENDING_INTERNAL ||
1948 to == INTERRUPTED_TARGET_PENDING_INTERNAL ||
1949 to == CANCELLED_INTERNAL;
1908 1950
1909 case CANCELLED_INTERNAL: 1951 case CANCELLED_INTERNAL:
1910 return false; 1952 return false;
1911 1953
1912 case MAX_DOWNLOAD_INTERNAL_STATE: 1954 case MAX_DOWNLOAD_INTERNAL_STATE:
1913 NOTREACHED(); 1955 NOTREACHED();
1914 } 1956 }
1915 return false; 1957 return false;
1916 } 1958 }
1917 #endif // DCHECK_IS_ON() 1959 #endif // DCHECK_IS_ON()
1918 1960
1919 const char* DownloadItemImpl::DebugDownloadStateString( 1961 const char* DownloadItemImpl::DebugDownloadStateString(
1920 DownloadInternalState state) { 1962 DownloadInternalState state) {
1921 switch (state) { 1963 switch (state) {
1922 case INITIAL_INTERNAL: 1964 case INITIAL_INTERNAL:
1923 return "INITIAL"; 1965 return "INITIAL";
1924 case TARGET_PENDING_INTERNAL: 1966 case TARGET_PENDING_INTERNAL:
1925 return "TARGET_PENDING"; 1967 return "TARGET_PENDING";
1968 case INTERRUPTED_TARGET_PENDING_INTERNAL:
1969 return "INTERRUPTED_TARGET_PENDING";
1926 case TARGET_RESOLVED_INTERNAL: 1970 case TARGET_RESOLVED_INTERNAL:
1927 return "TARGET_RESOLVED"; 1971 return "TARGET_RESOLVED";
1928 case IN_PROGRESS_INTERNAL: 1972 case IN_PROGRESS_INTERNAL:
1929 return "IN_PROGRESS"; 1973 return "IN_PROGRESS";
1930 case COMPLETING_INTERNAL: 1974 case COMPLETING_INTERNAL:
1931 return "COMPLETING"; 1975 return "COMPLETING";
1932 case COMPLETE_INTERNAL: 1976 case COMPLETE_INTERNAL:
1933 return "COMPLETE"; 1977 return "COMPLETE";
1934 case CANCELLED_INTERNAL: 1978 case CANCELLED_INTERNAL:
1935 return "CANCELLED"; 1979 return "CANCELLED";
(...skipping 19 matching lines...) Expand all
1955 case RESUME_MODE_USER_CONTINUE: 1999 case RESUME_MODE_USER_CONTINUE:
1956 return "USER_CONTINUE"; 2000 return "USER_CONTINUE";
1957 case RESUME_MODE_USER_RESTART: 2001 case RESUME_MODE_USER_RESTART:
1958 return "USER_RESTART"; 2002 return "USER_RESTART";
1959 } 2003 }
1960 NOTREACHED() << "Unknown resume mode " << mode; 2004 NOTREACHED() << "Unknown resume mode " << mode;
1961 return "unknown"; 2005 return "unknown";
1962 } 2006 }
1963 2007
1964 } // namespace content 2008 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698