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

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

Issue 10950015: Shift "commit point" for when a download will no longer accept cancels. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync'd to LKGR. Created 8 years, 2 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 5 // File method ordering: Methods in this file are in the same order
6 // as in download_item_impl.h, with the following exception: The public 6 // as in download_item_impl.h, with the following exception: The public
7 // interfaces DelayedDownloadOpened, OnDownloadTargetDetermined, and 7 // interfaces DelayedDownloadOpened, OnDownloadTargetDetermined, and
8 // OnDownloadCompleting are placed in chronological order with the other 8 // OnDownloadCompleting are placed in chronological order with the other
9 // (private) routines that together define a DownloadItem's state transitions 9 // (private) routines that together define a DownloadItem's state transitions
10 // as the download progresses. See "Download progression cascade" later in 10 // as the download progresses. See "Download progression cascade" later in
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 case DownloadItem::DANGEROUS: 73 case DownloadItem::DANGEROUS:
74 return "DANGEROUS"; 74 return "DANGEROUS";
75 case DownloadItem::DANGEROUS_BUT_VALIDATED: 75 case DownloadItem::DANGEROUS_BUT_VALIDATED:
76 return "DANGEROUS_BUT_VALIDATED"; 76 return "DANGEROUS_BUT_VALIDATED";
77 default: 77 default:
78 NOTREACHED() << "Unknown safety state " << state; 78 NOTREACHED() << "Unknown safety state " << state;
79 return "unknown"; 79 return "unknown";
80 }; 80 };
81 } 81 }
82 82
83 const char* DebugDownloadStateString(DownloadItem::DownloadState state) {
84 switch (state) {
85 case DownloadItem::IN_PROGRESS:
86 return "IN_PROGRESS";
87 case DownloadItem::COMPLETE:
88 return "COMPLETE";
89 case DownloadItem::CANCELLED:
90 return "CANCELLED";
91 case DownloadItem::INTERRUPTED:
92 return "INTERRUPTED";
93 default:
94 NOTREACHED() << "Unknown download state " << state;
95 return "unknown";
96 };
97 }
98
99 // Classes to null out request handle calls (for SavePage DownloadItems, which 83 // Classes to null out request handle calls (for SavePage DownloadItems, which
100 // may have, e.g., Cancel() called on them without it doing anything) 84 // may have, e.g., Cancel() called on them without it doing anything)
101 // and to DCHECK on them (for history DownloadItems, which should never have 85 // and to DCHECK on them (for history DownloadItems, which should never have
102 // any operation that implies an off-thread component, since they don't 86 // any operation that implies an off-thread component, since they don't
103 // have any). 87 // have any).
104 class NullDownloadRequestHandle : public DownloadRequestHandleInterface { 88 class NullDownloadRequestHandle : public DownloadRequestHandleInterface {
105 public: 89 public:
106 NullDownloadRequestHandle() {} 90 NullDownloadRequestHandle() {}
107 91
108 // DownloadRequestHandleInterface calls 92 // DownloadRequestHandleInterface calls
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 target_disposition_(TARGET_DISPOSITION_OVERWRITE), 135 target_disposition_(TARGET_DISPOSITION_OVERWRITE),
152 url_chain_(1, info.url), 136 url_chain_(1, info.url),
153 referrer_url_(info.referrer_url), 137 referrer_url_(info.referrer_url),
154 transition_type_(content::PAGE_TRANSITION_LINK), 138 transition_type_(content::PAGE_TRANSITION_LINK),
155 has_user_gesture_(false), 139 has_user_gesture_(false),
156 total_bytes_(info.total_bytes), 140 total_bytes_(info.total_bytes),
157 received_bytes_(info.received_bytes), 141 received_bytes_(info.received_bytes),
158 bytes_per_sec_(0), 142 bytes_per_sec_(0),
159 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE), 143 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE),
160 start_tick_(base::TimeTicks()), 144 start_tick_(base::TimeTicks()),
161 state_(info.state), 145 state_(ExternalToInternalState(info.state)),
162 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), 146 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
163 start_time_(info.start_time), 147 start_time_(info.start_time),
164 end_time_(info.end_time), 148 end_time_(info.end_time),
165 db_handle_(info.db_handle), 149 db_handle_(info.db_handle),
166 delegate_(delegate), 150 delegate_(delegate),
167 is_paused_(false), 151 is_paused_(false),
168 open_when_complete_(false), 152 open_when_complete_(false),
169 file_externally_removed_(false), 153 file_externally_removed_(false),
170 safety_state_(SAFE), 154 safety_state_(SAFE),
171 auto_opened_(false), 155 auto_opened_(false),
172 is_persisted_(true), 156 is_persisted_(true),
173 is_temporary_(false), 157 is_temporary_(false),
174 all_data_saved_(false), 158 all_data_saved_(false),
175 opened_(info.opened), 159 opened_(info.opened),
176 open_enabled_(true), 160 open_enabled_(true),
177 delegate_delayed_complete_(false), 161 delegate_delayed_complete_(false),
178 bound_net_log_(bound_net_log), 162 bound_net_log_(bound_net_log),
179 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { 163 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
180 delegate_->Attach(); 164 delegate_->Attach();
181 if (IsInProgress()) 165 if (state_ == IN_PROGRESS_INTERNAL)
182 state_ = CANCELLED; 166 state_ = CANCELLED_INTERNAL;
183 if (IsComplete()) 167 if (state_ == COMPLETE_INTERNAL)
184 all_data_saved_ = true; 168 all_data_saved_ = true;
185 Init(false /* not actively downloading */, 169 Init(false /* not actively downloading */,
186 download_net_logs::SRC_HISTORY_IMPORT); 170 download_net_logs::SRC_HISTORY_IMPORT);
187 } 171 }
188 172
189 // Constructing for a regular download: 173 // Constructing for a regular download:
190 DownloadItemImpl::DownloadItemImpl( 174 DownloadItemImpl::DownloadItemImpl(
191 DownloadItemImplDelegate* delegate, 175 DownloadItemImplDelegate* delegate,
192 const DownloadCreateInfo& info, 176 const DownloadCreateInfo& info,
193 scoped_ptr<DownloadRequestHandleInterface> request_handle, 177 scoped_ptr<DownloadRequestHandleInterface> request_handle,
(...skipping 12 matching lines...) Expand all
206 content_disposition_(info.content_disposition), 190 content_disposition_(info.content_disposition),
207 mime_type_(info.mime_type), 191 mime_type_(info.mime_type),
208 original_mime_type_(info.original_mime_type), 192 original_mime_type_(info.original_mime_type),
209 referrer_charset_(info.referrer_charset), 193 referrer_charset_(info.referrer_charset),
210 remote_address_(info.remote_address), 194 remote_address_(info.remote_address),
211 total_bytes_(info.total_bytes), 195 total_bytes_(info.total_bytes),
212 received_bytes_(0), 196 received_bytes_(0),
213 bytes_per_sec_(0), 197 bytes_per_sec_(0),
214 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE), 198 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE),
215 start_tick_(base::TimeTicks::Now()), 199 start_tick_(base::TimeTicks::Now()),
216 state_(IN_PROGRESS), 200 state_(IN_PROGRESS_INTERNAL),
217 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), 201 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
218 start_time_(info.start_time), 202 start_time_(info.start_time),
219 db_handle_(DownloadItem::kUninitializedHandle), 203 db_handle_(DownloadItem::kUninitializedHandle),
220 delegate_(delegate), 204 delegate_(delegate),
221 is_paused_(false), 205 is_paused_(false),
222 open_when_complete_(false), 206 open_when_complete_(false),
223 file_externally_removed_(false), 207 file_externally_removed_(false),
224 safety_state_(SAFE), 208 safety_state_(SAFE),
225 auto_opened_(false), 209 auto_opened_(false),
226 is_persisted_(false), 210 is_persisted_(false),
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 referrer_url_(GURL()), 245 referrer_url_(GURL()),
262 transition_type_(content::PAGE_TRANSITION_LINK), 246 transition_type_(content::PAGE_TRANSITION_LINK),
263 has_user_gesture_(false), 247 has_user_gesture_(false),
264 mime_type_(mime_type), 248 mime_type_(mime_type),
265 original_mime_type_(mime_type), 249 original_mime_type_(mime_type),
266 total_bytes_(0), 250 total_bytes_(0),
267 received_bytes_(0), 251 received_bytes_(0),
268 bytes_per_sec_(0), 252 bytes_per_sec_(0),
269 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE), 253 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE),
270 start_tick_(base::TimeTicks::Now()), 254 start_tick_(base::TimeTicks::Now()),
271 state_(IN_PROGRESS), 255 state_(IN_PROGRESS_INTERNAL),
272 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), 256 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
273 start_time_(base::Time::Now()), 257 start_time_(base::Time::Now()),
274 db_handle_(DownloadItem::kUninitializedHandle), 258 db_handle_(DownloadItem::kUninitializedHandle),
275 delegate_(delegate), 259 delegate_(delegate),
276 is_paused_(false), 260 is_paused_(false),
277 open_when_complete_(false), 261 open_when_complete_(false),
278 file_externally_removed_(false), 262 file_externally_removed_(false),
279 safety_state_(SAFE), 263 safety_state_(SAFE),
280 auto_opened_(false), 264 auto_opened_(false),
281 is_persisted_(false), 265 is_persisted_(false),
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 GetDangerType(), GetSafetyState())); 316 GetDangerType(), GetSafetyState()));
333 317
334 UpdateObservers(); 318 UpdateObservers();
335 319
336 delegate_->MaybeCompleteDownload(this); 320 delegate_->MaybeCompleteDownload(this);
337 } 321 }
338 322
339 void DownloadItemImpl::TogglePause() { 323 void DownloadItemImpl::TogglePause() {
340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
341 325
342 DCHECK(IsInProgress()); 326 DCHECK(state_ == IN_PROGRESS_INTERNAL || state_ == COMPLETING_INTERNAL);
343 if (is_paused_) 327 if (is_paused_)
344 request_handle_->ResumeRequest(); 328 request_handle_->ResumeRequest();
345 else 329 else
346 request_handle_->PauseRequest(); 330 request_handle_->PauseRequest();
347 is_paused_ = !is_paused_; 331 is_paused_ = !is_paused_;
348 UpdateObservers(); 332 UpdateObservers();
349 } 333 }
350 334
351 void DownloadItemImpl::Cancel(bool user_cancel) { 335 void DownloadItemImpl::Cancel(bool user_cancel) {
352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
353 337
354 last_reason_ = user_cancel ? 338 last_reason_ = user_cancel ?
355 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED : 339 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED :
356 content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN; 340 content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
357 341
358 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 342 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
359 if (!IsPartialDownload()) { 343 if (state_ != IN_PROGRESS_INTERNAL) {
360 // Small downloads might be complete before this method has 344 // Small downloads might be complete before this method has
361 // a chance to run. 345 // a chance to run.
362 return; 346 return;
363 } 347 }
364 348
365 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT); 349 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT);
366 350
367 TransitionTo(CANCELLED); 351 TransitionTo(CANCELLED_INTERNAL);
368 if (user_cancel) 352 if (user_cancel)
369 delegate_->DownloadStopped(this); 353 delegate_->DownloadStopped(this);
370 } 354 }
371 355
372 void DownloadItemImpl::Delete(DeleteReason reason) { 356 void DownloadItemImpl::Delete(DeleteReason reason) {
373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
374 358
375 switch (reason) { 359 switch (reason) {
376 case DELETE_DUE_TO_USER_DISCARD: 360 case DELETE_DUE_TO_USER_DISCARD:
377 UMA_HISTOGRAM_ENUMERATION( 361 UMA_HISTOGRAM_ENUMERATION(
(...skipping 25 matching lines...) Expand all
403 delegate_->AssertStateConsistent(this); 387 delegate_->AssertStateConsistent(this);
404 388
405 NotifyRemoved(); 389 NotifyRemoved();
406 delegate_->DownloadRemoved(this); 390 delegate_->DownloadRemoved(this);
407 // We have now been deleted. 391 // We have now been deleted.
408 } 392 }
409 393
410 void DownloadItemImpl::OpenDownload() { 394 void DownloadItemImpl::OpenDownload() {
411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
412 396
413 if (IsPartialDownload()) { 397 if (state_ == IN_PROGRESS_INTERNAL) {
414 // We don't honor the open_when_complete_ flag for temporary 398 // We don't honor the open_when_complete_ flag for temporary
415 // downloads. Don't set it because it shows up in the UI. 399 // downloads. Don't set it because it shows up in the UI.
416 if (!IsTemporary()) 400 if (!IsTemporary())
417 open_when_complete_ = !open_when_complete_; 401 open_when_complete_ = !open_when_complete_;
418 return; 402 return;
419 } 403 }
420 404
421 if (!IsComplete() || file_externally_removed_) 405 if (state_ != COMPLETE_INTERNAL || file_externally_removed_)
422 return; 406 return;
423 407
424 // Ideally, we want to detect errors in opening and report them, but we 408 // Ideally, we want to detect errors in opening and report them, but we
425 // don't generally have the proper interface for that to the external 409 // don't generally have the proper interface for that to the external
426 // program that opens the file. So instead we spawn a check to update 410 // program that opens the file. So instead we spawn a check to update
427 // the UI if the file has been deleted in parallel with the open. 411 // the UI if the file has been deleted in parallel with the open.
428 delegate_->CheckForFileRemoval(this); 412 delegate_->CheckForFileRemoval(this);
429 download_stats::RecordOpen(GetEndTime(), !GetOpened()); 413 download_stats::RecordOpen(GetEndTime(), !GetOpened());
430 opened_ = true; 414 opened_ = true;
431 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this)); 415 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadOpened(this));
(...skipping 19 matching lines...) Expand all
451 435
452 DownloadId DownloadItemImpl::GetGlobalId() const { 436 DownloadId DownloadItemImpl::GetGlobalId() const {
453 return download_id_; 437 return download_id_;
454 } 438 }
455 439
456 int64 DownloadItemImpl::GetDbHandle() const { 440 int64 DownloadItemImpl::GetDbHandle() const {
457 return db_handle_; 441 return db_handle_;
458 } 442 }
459 443
460 DownloadItem::DownloadState DownloadItemImpl::GetState() const { 444 DownloadItem::DownloadState DownloadItemImpl::GetState() const {
461 return state_; 445 return InternalToExternalState(state_);
462 } 446 }
463 447
464 content::DownloadInterruptReason DownloadItemImpl::GetLastReason() const { 448 content::DownloadInterruptReason DownloadItemImpl::GetLastReason() const {
465 return last_reason_; 449 return last_reason_;
466 } 450 }
467 451
468 bool DownloadItemImpl::IsPaused() const { 452 bool DownloadItemImpl::IsPaused() const {
469 return is_paused_; 453 return is_paused_;
470 } 454 }
471 455
472 bool DownloadItemImpl::IsTemporary() const { 456 bool DownloadItemImpl::IsTemporary() const {
473 return is_temporary_; 457 return is_temporary_;
474 } 458 }
475 459
476 bool DownloadItemImpl::IsPersisted() const { 460 bool DownloadItemImpl::IsPersisted() const {
477 return is_persisted_; 461 return is_persisted_;
478 } 462 }
479 463
480 // TODO(ahendrickson) -- Move |INTERRUPTED| from |IsCancelled()| to 464 // TODO(ahendrickson) -- Move |INTERRUPTED| from |IsCancelled()| to
481 // |IsPartialDownload()|, when resuming interrupted downloads is implemented. 465 // |IsPartialDownload()|, when resuming interrupted downloads is implemented.
482 bool DownloadItemImpl::IsPartialDownload() const { 466 bool DownloadItemImpl::IsPartialDownload() const {
483 return (state_ == IN_PROGRESS); 467 return InternalToExternalState(state_) == IN_PROGRESS;
484 } 468 }
485 469
486 bool DownloadItemImpl::IsInProgress() const { 470 bool DownloadItemImpl::IsInProgress() const {
487 return (state_ == IN_PROGRESS); 471 return InternalToExternalState(state_) == IN_PROGRESS;
488 } 472 }
489 473
490 bool DownloadItemImpl::IsCancelled() const { 474 bool DownloadItemImpl::IsCancelled() const {
491 return (state_ == CANCELLED) || 475 DownloadState external_state = InternalToExternalState(state_);
492 (state_ == INTERRUPTED); 476 return external_state == CANCELLED || external_state == INTERRUPTED;
493 } 477 }
494 478
495 bool DownloadItemImpl::IsInterrupted() const { 479 bool DownloadItemImpl::IsInterrupted() const {
496 return (state_ == INTERRUPTED); 480 return InternalToExternalState(state_) == INTERRUPTED;
497 } 481 }
498 482
499 bool DownloadItemImpl::IsComplete() const { 483 bool DownloadItemImpl::IsComplete() const {
500 return (state_ == COMPLETE); 484 return InternalToExternalState(state_) == COMPLETE;
501 } 485 }
502 486
503 const GURL& DownloadItemImpl::GetURL() const { 487 const GURL& DownloadItemImpl::GetURL() const {
504 return url_chain_.empty() ? 488 return url_chain_.empty() ?
505 GURL::EmptyGURL() : url_chain_.back(); 489 GURL::EmptyGURL() : url_chain_.back();
506 } 490 }
507 491
508 const std::vector<GURL>& DownloadItemImpl::GetUrlChain() const { 492 const std::vector<GURL>& DownloadItemImpl::GetUrlChain() const {
509 return url_chain_; 493 return url_chain_;
510 } 494 }
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 647
664 base::Time DownloadItemImpl::GetStartTime() const { 648 base::Time DownloadItemImpl::GetStartTime() const {
665 return start_time_; 649 return start_time_;
666 } 650 }
667 651
668 base::Time DownloadItemImpl::GetEndTime() const { 652 base::Time DownloadItemImpl::GetEndTime() const {
669 return end_time_; 653 return end_time_;
670 } 654 }
671 655
672 bool DownloadItemImpl::CanShowInFolder() { 656 bool DownloadItemImpl::CanShowInFolder() {
673 return !IsCancelled() && !file_externally_removed_; 657 return state_ != CANCELLED_INTERNAL && !file_externally_removed_;
674 } 658 }
675 659
676 bool DownloadItemImpl::CanOpenDownload() { 660 bool DownloadItemImpl::CanOpenDownload() {
677 return !file_externally_removed_; 661 return !file_externally_removed_;
678 } 662 }
679 663
680 bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() { 664 bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() {
681 return delegate_->ShouldOpenFileBasedOnExtension(GetUserVerifiedFilePath()); 665 return delegate_->ShouldOpenFileBasedOnExtension(GetUserVerifiedFilePath());
682 } 666 }
683 667
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 727
744 void DownloadItemImpl::SetDisplayName(const FilePath& name) { 728 void DownloadItemImpl::SetDisplayName(const FilePath& name) {
745 display_name_ = name; 729 display_name_ = name;
746 } 730 }
747 731
748 std::string DownloadItemImpl::DebugString(bool verbose) const { 732 std::string DownloadItemImpl::DebugString(bool verbose) const {
749 std::string description = 733 std::string description =
750 base::StringPrintf("{ id = %d" 734 base::StringPrintf("{ id = %d"
751 " state = %s", 735 " state = %s",
752 download_id_.local(), 736 download_id_.local(),
753 DebugDownloadStateString(GetState())); 737 DebugDownloadStateString(state_));
754 738
755 // Construct a string of the URL chain. 739 // Construct a string of the URL chain.
756 std::string url_list("<none>"); 740 std::string url_list("<none>");
757 if (!url_chain_.empty()) { 741 if (!url_chain_.empty()) {
758 std::vector<GURL>::const_iterator iter = url_chain_.begin(); 742 std::vector<GURL>::const_iterator iter = url_chain_.begin();
759 std::vector<GURL>::const_iterator last = url_chain_.end(); 743 std::vector<GURL>::const_iterator last = url_chain_.end();
760 url_list = (*iter).spec(); 744 url_list = (*iter).spec();
761 ++iter; 745 ++iter;
762 for ( ; verbose && (iter != last); ++iter) { 746 for ( ; verbose && (iter != last); ++iter) {
763 url_list += " ->\n\t"; 747 url_list += " ->\n\t";
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
827 // Somewhat counter-intuitively, it is possible for us to receive an 811 // Somewhat counter-intuitively, it is possible for us to receive an
828 // interrupt after we've already been interrupted. The generation of 812 // interrupt after we've already been interrupted. The generation of
829 // interrupts from the file thread Renames and the generation of 813 // interrupts from the file thread Renames and the generation of
830 // interrupts from disk writes go through two different mechanisms (driven 814 // interrupts from disk writes go through two different mechanisms (driven
831 // by rename requests from UI thread and by write requests from IO thread, 815 // by rename requests from UI thread and by write requests from IO thread,
832 // respectively), and since we choose not to keep state on the File thread, 816 // respectively), and since we choose not to keep state on the File thread,
833 // this is the place where the races collide. It's also possible for 817 // this is the place where the races collide. It's also possible for
834 // interrupts to race with cancels. 818 // interrupts to race with cancels.
835 819
836 // Whatever happens, the first one to hit the UI thread wins. 820 // Whatever happens, the first one to hit the UI thread wins.
837 if (!IsInProgress()) 821 if (state_ != IN_PROGRESS_INTERNAL)
838 return; 822 return;
839 823
840 last_reason_ = reason; 824 last_reason_ = reason;
841 TransitionTo(INTERRUPTED); 825 TransitionTo(INTERRUPTED_INTERNAL);
842 download_stats::RecordDownloadInterrupted( 826 download_stats::RecordDownloadInterrupted(
843 reason, received_bytes_, total_bytes_); 827 reason, received_bytes_, total_bytes_);
844 delegate_->DownloadStopped(this); 828 delegate_->DownloadStopped(this);
845 } 829 }
846 830
847 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) { 831 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) {
848 total_bytes_ = total_bytes; 832 total_bytes_ = total_bytes;
849 } 833 }
850 834
851 // Updates from the download thread may have been posted while this download 835 // Updates from the download thread may have been posted while this download
852 // was being cancelled in the UI thread, so we'll accept them unless we're 836 // was being cancelled in the UI thread, so we'll accept them unless we're
853 // complete. 837 // complete.
854 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, 838 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far,
855 int64 bytes_per_sec, 839 int64 bytes_per_sec,
856 const std::string& hash_state) { 840 const std::string& hash_state) {
857 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 841 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
858 842
859 if (!IsInProgress()) { 843 if (state_ != IN_PROGRESS_INTERNAL) {
860 // Ignore if we're no longer in-progress. This can happen if we race a 844 // Ignore if we're no longer in-progress. This can happen if we race a
861 // Cancel on the UI thread with an update on the FILE thread. 845 // Cancel on the UI thread with an update on the FILE thread.
862 // 846 //
863 // TODO(rdsmith): Arguably we should let this go through, as this means 847 // TODO(rdsmith): Arguably we should let this go through, as this means
864 // the download really did get further than we know before it was 848 // the download really did get further than we know before it was
865 // cancelled. But the gain isn't very large, and the code is more 849 // cancelled. But the gain isn't very large, and the code is more
866 // fragile if it has to support in progress updates in a non-in-progress 850 // fragile if it has to support in progress updates in a non-in-progress
867 // state. This issue should be readdressed when we revamp performance 851 // state. This issue should be readdressed when we revamp performance
868 // reporting. 852 // reporting.
869 return; 853 return;
(...skipping 24 matching lines...) Expand all
894 all_data_saved_ = true; 878 all_data_saved_ = true;
895 ProgressComplete(size, final_hash); 879 ProgressComplete(size, final_hash);
896 UpdateObservers(); 880 UpdateObservers();
897 } 881 }
898 882
899 void DownloadItemImpl::MarkAsComplete() { 883 void DownloadItemImpl::MarkAsComplete() {
900 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 884 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
901 885
902 DCHECK(all_data_saved_); 886 DCHECK(all_data_saved_);
903 end_time_ = base::Time::Now(); 887 end_time_ = base::Time::Now();
904 TransitionTo(COMPLETE); 888 TransitionTo(COMPLETE_INTERNAL);
905 } 889 }
906 890
907 void DownloadItemImpl::SetIsPersisted() { 891 void DownloadItemImpl::SetIsPersisted() {
908 is_persisted_ = true; 892 is_persisted_ = true;
909 UpdateObservers(); 893 UpdateObservers();
910 } 894 }
911 895
912 void DownloadItemImpl::SetDbHandle(int64 handle) { 896 void DownloadItemImpl::SetDbHandle(int64 handle) {
913 db_handle_ = handle; 897 db_handle_ = handle;
914 898
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 target_path_ = target_path; 963 target_path_ = target_path;
980 target_disposition_ = disposition; 964 target_disposition_ = disposition;
981 SetDangerType(danger_type); 965 SetDangerType(danger_type);
982 // TODO(asanka): SetDangerType() doesn't need to send a notification here. 966 // TODO(asanka): SetDangerType() doesn't need to send a notification here.
983 967
984 // We want the intermediate and target paths to refer to the same directory so 968 // We want the intermediate and target paths to refer to the same directory so
985 // that they are both on the same device and subject to same 969 // that they are both on the same device and subject to same
986 // space/permission/availability constraints. 970 // space/permission/availability constraints.
987 DCHECK(intermediate_path.DirName() == target_path.DirName()); 971 DCHECK(intermediate_path.DirName() == target_path.DirName());
988 972
973 if (state_ != IN_PROGRESS_INTERNAL) {
974 // If we've been cancelled or interrupted while the target was being
975 // determined, continue the cascade with a null name.
976 // The error doesn't matter as the cause of download stoppage
977 // will already have been recorded and will be retained, but we use
978 // whatever was recorded for consistency.
979 OnDownloadRenamedToIntermediateName(last_reason_, FilePath());
980 return;
981 }
982
989 // Rename to intermediate name. 983 // Rename to intermediate name.
990 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a 984 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a
991 // spurious rename when we can just rename to the final 985 // spurious rename when we can just rename to the final
992 // filename. Unnecessary renames may cause bugs like 986 // filename. Unnecessary renames may cause bugs like
993 // http://crbug.com/74187. 987 // http://crbug.com/74187.
994 DownloadFileManager::RenameCompletionCallback callback = 988 DownloadFileManager::RenameCompletionCallback callback =
995 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, 989 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName,
996 weak_ptr_factory_.GetWeakPtr()); 990 weak_ptr_factory_.GetWeakPtr());
997 BrowserThread::PostTask( 991 BrowserThread::PostTask(
998 BrowserThread::FILE, FROM_HERE, 992 BrowserThread::FILE, FROM_HERE,
(...skipping 19 matching lines...) Expand all
1018 void DownloadItemImpl::MaybeCompleteDownload() { 1012 void DownloadItemImpl::MaybeCompleteDownload() {
1019 // TODO(rdsmith): Move logic for this function here. 1013 // TODO(rdsmith): Move logic for this function here.
1020 delegate_->MaybeCompleteDownload(this); 1014 delegate_->MaybeCompleteDownload(this);
1021 } 1015 }
1022 1016
1023 // Called by DownloadManagerImpl::MaybeCompleteDownload() when it has 1017 // Called by DownloadManagerImpl::MaybeCompleteDownload() when it has
1024 // determined that the download is ready for completion. 1018 // determined that the download is ready for completion.
1025 void DownloadItemImpl::OnDownloadCompleting() { 1019 void DownloadItemImpl::OnDownloadCompleting() {
1026 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1020 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1027 1021
1022 if (state_ != IN_PROGRESS_INTERNAL)
1023 return;
1024
1028 VLOG(20) << __FUNCTION__ << "()" 1025 VLOG(20) << __FUNCTION__ << "()"
1029 << " needs rename = " << NeedsRename() 1026 << " needs rename = " << NeedsRename()
1030 << " " << DebugString(true); 1027 << " " << DebugString(true);
1031 DCHECK(!GetTargetFilePath().empty()); 1028 DCHECK(!GetTargetFilePath().empty());
1032 DCHECK_NE(DANGEROUS, GetSafetyState()); 1029 DCHECK_NE(DANGEROUS, GetSafetyState());
1033 1030
1034 if (NeedsRename()) { 1031 if (NeedsRename()) {
1035 DownloadFileManager::RenameCompletionCallback callback = 1032 DownloadFileManager::RenameCompletionCallback callback =
1036 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName, 1033 base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
1037 weak_ptr_factory_.GetWeakPtr()); 1034 weak_ptr_factory_.GetWeakPtr());
1038 BrowserThread::PostTask( 1035 BrowserThread::PostTask(
1039 BrowserThread::FILE, FROM_HERE, 1036 BrowserThread::FILE, FROM_HERE,
1040 base::Bind(&DownloadFileManager::RenameDownloadFile, 1037 base::Bind(&DownloadFileManager::RenameDownloadFile,
1041 delegate_->GetDownloadFileManager(), GetGlobalId(), 1038 delegate_->GetDownloadFileManager(), GetGlobalId(),
1042 GetTargetFilePath(), true, callback)); 1039 GetTargetFilePath(), true, callback));
1043 } else { 1040 } else {
1044 // Complete the download and release the DownloadFile. 1041 // Complete the download and release the DownloadFile.
1045 BrowserThread::PostTask( 1042 BrowserThread::PostTask(
1046 BrowserThread::FILE, FROM_HERE, 1043 BrowserThread::FILE, FROM_HERE,
1047 base::Bind(&DownloadFileManager::CompleteDownload, 1044 base::Bind(&DownloadFileManager::CompleteDownload,
1048 delegate_->GetDownloadFileManager(), GetGlobalId(), 1045 delegate_->GetDownloadFileManager(), GetGlobalId(),
1049 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, 1046 base::Bind(&DownloadItemImpl::OnDownloadFileReleased,
1050 weak_ptr_factory_.GetWeakPtr()))); 1047 weak_ptr_factory_.GetWeakPtr())));
1048 TransitionTo(COMPLETING_INTERNAL);
1051 } 1049 }
1052 } 1050 }
1053 1051
1054 void DownloadItemImpl::OnDownloadRenamedToFinalName( 1052 void DownloadItemImpl::OnDownloadRenamedToFinalName(
1055 content::DownloadInterruptReason reason, 1053 content::DownloadInterruptReason reason,
1056 const FilePath& full_path) { 1054 const FilePath& full_path) {
1057 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1055 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1058 1056
1057 // If a cancel or interrupt hit, we'll cancel the DownloadFile, which
1058 // will result in deleting the file on the file thread. So we don't
1059 // care about the name having been changed.
1060 if (state_ != IN_PROGRESS_INTERNAL)
1061 return;
1062
1059 VLOG(20) << __FUNCTION__ << "()" 1063 VLOG(20) << __FUNCTION__ << "()"
1060 << " full_path = \"" << full_path.value() << "\"" 1064 << " full_path = \"" << full_path.value() << "\""
1061 << " needed rename = " << NeedsRename() 1065 << " needed rename = " << NeedsRename()
1062 << " " << DebugString(false); 1066 << " " << DebugString(false);
1063 DCHECK(NeedsRename()); 1067 DCHECK(NeedsRename());
1064 1068
1065 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) { 1069 if (content::DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
1066 Interrupt(reason); 1070 Interrupt(reason);
1067 return; 1071 return;
1068 } 1072 }
1069 1073
1070 // full_path is now the current and target file path. 1074 // full_path is now the current and target file path.
1071 DCHECK(!full_path.empty()); 1075 DCHECK(!full_path.empty());
1072 target_path_ = full_path; 1076 target_path_ = full_path;
1073 SetFullPath(full_path); 1077 SetFullPath(full_path);
1074 delegate_->DownloadRenamedToFinalName(this); 1078 delegate_->DownloadRenamedToFinalName(this);
1075 1079
1076 // Complete the download and release the DownloadFile. 1080 // Complete the download and release the DownloadFile.
1077 BrowserThread::PostTask( 1081 BrowserThread::PostTask(
1078 BrowserThread::FILE, FROM_HERE, 1082 BrowserThread::FILE, FROM_HERE,
1079 base::Bind(&DownloadFileManager::CompleteDownload, 1083 base::Bind(&DownloadFileManager::CompleteDownload,
1080 delegate_->GetDownloadFileManager(), GetGlobalId(), 1084 delegate_->GetDownloadFileManager(), GetGlobalId(),
1081 base::Bind(&DownloadItemImpl::OnDownloadFileReleased, 1085 base::Bind(&DownloadItemImpl::OnDownloadFileReleased,
1082 weak_ptr_factory_.GetWeakPtr()))); 1086 weak_ptr_factory_.GetWeakPtr())));
1087 TransitionTo(COMPLETING_INTERNAL);
1083 } 1088 }
1084 1089
1085 void DownloadItemImpl::OnDownloadFileReleased() { 1090 void DownloadItemImpl::OnDownloadFileReleased() {
1086 if (delegate_->ShouldOpenDownload(this)) 1091 if (delegate_->ShouldOpenDownload(this))
1087 Completed(); 1092 Completed();
1088 else 1093 else
1089 delegate_delayed_complete_ = true; 1094 delegate_delayed_complete_ = true;
1090 } 1095 }
1091 1096
1092 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { 1097 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) {
1093 auto_opened_ = auto_opened; 1098 auto_opened_ = auto_opened;
1094 Completed(); 1099 Completed();
1095 } 1100 }
1096 1101
1097 void DownloadItemImpl::Completed() { 1102 void DownloadItemImpl::Completed() {
1098 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1099 1104
1100 VLOG(20) << __FUNCTION__ << "() " << DebugString(false); 1105 VLOG(20) << __FUNCTION__ << "() " << DebugString(false);
1101 1106
1102 DCHECK(all_data_saved_); 1107 DCHECK(all_data_saved_);
1103 end_time_ = base::Time::Now(); 1108 end_time_ = base::Time::Now();
1104 TransitionTo(COMPLETE); 1109 TransitionTo(COMPLETE_INTERNAL);
1105 delegate_->DownloadCompleted(this); 1110 delegate_->DownloadCompleted(this);
1106 download_stats::RecordDownloadCompleted(start_tick_, received_bytes_); 1111 download_stats::RecordDownloadCompleted(start_tick_, received_bytes_);
1107 1112
1108 if (auto_opened_) { 1113 if (auto_opened_) {
1109 // If it was already handled by the delegate, do nothing. 1114 // If it was already handled by the delegate, do nothing.
1110 } else if (GetOpenWhenComplete() || 1115 } else if (GetOpenWhenComplete() ||
1111 ShouldOpenFileBasedOnExtension() || 1116 ShouldOpenFileBasedOnExtension() ||
1112 IsTemporary()) { 1117 IsTemporary()) {
1113 // If the download is temporary, like in drag-and-drop, do not open it but 1118 // If the download is temporary, like in drag-and-drop, do not open it but
1114 // we still need to set it auto-opened so that it can be removed from the 1119 // we still need to set it auto-opened so that it can be removed from the
(...skipping 21 matching lines...) Expand all
1136 hash_state_ = ""; 1141 hash_state_ = "";
1137 1142
1138 received_bytes_ = bytes_so_far; 1143 received_bytes_ = bytes_so_far;
1139 1144
1140 // If we've received more data than we were expecting (bad server info?), 1145 // If we've received more data than we were expecting (bad server info?),
1141 // revert to 'unknown size mode'. 1146 // revert to 'unknown size mode'.
1142 if (received_bytes_ > total_bytes_) 1147 if (received_bytes_ > total_bytes_)
1143 total_bytes_ = 0; 1148 total_bytes_ = 0;
1144 } 1149 }
1145 1150
1146 void DownloadItemImpl::TransitionTo(DownloadState new_state) { 1151 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {
1147 if (state_ == new_state) 1152 if (state_ == new_state)
1148 return; 1153 return;
1149 1154
1150 DownloadState old_state = state_; 1155 DownloadInternalState old_state = state_;
1151 state_ = new_state; 1156 state_ = new_state;
1152 1157
1153 switch (state_) { 1158 switch (state_) {
1154 case COMPLETE: 1159 case COMPLETING_INTERNAL:
1160 bound_net_log_.AddEvent(
1161 net::NetLog::TYPE_DOWNLOAD_ITEM_COMPLETING,
1162 base::Bind(&download_net_logs::ItemCompletingCallback,
1163 received_bytes_, &hash_));
1164 break;
1165 case COMPLETE_INTERNAL:
1155 bound_net_log_.AddEvent( 1166 bound_net_log_.AddEvent(
1156 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED, 1167 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED,
1157 base::Bind(&download_net_logs::ItemFinishedCallback, 1168 base::Bind(&download_net_logs::ItemFinishedCallback,
1158 received_bytes_, &hash_)); 1169 auto_opened_));
1159 break; 1170 break;
1160 case INTERRUPTED: 1171 case INTERRUPTED_INTERNAL:
1161 bound_net_log_.AddEvent( 1172 bound_net_log_.AddEvent(
1162 net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED, 1173 net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED,
1163 base::Bind(&download_net_logs::ItemInterruptedCallback, 1174 base::Bind(&download_net_logs::ItemInterruptedCallback,
1164 last_reason_, received_bytes_, &hash_state_)); 1175 last_reason_, received_bytes_, &hash_state_));
1165 break; 1176 break;
1166 case CANCELLED: 1177 case CANCELLED_INTERNAL:
1167 bound_net_log_.AddEvent( 1178 bound_net_log_.AddEvent(
1168 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED, 1179 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED,
1169 base::Bind(&download_net_logs::ItemCanceledCallback, 1180 base::Bind(&download_net_logs::ItemCanceledCallback,
1170 received_bytes_, &hash_state_)); 1181 received_bytes_, &hash_state_));
1171 break; 1182 break;
1172 default: 1183 default:
1173 break; 1184 break;
1174 } 1185 }
1175 1186
1176 VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true); 1187 VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true);
1177 1188
1178 UpdateObservers(); 1189 // Only update observers on user visible state changes.
1190 if (InternalToExternalState(old_state) != InternalToExternalState(state_))
1191 UpdateObservers();
1179 1192
1180 bool is_done = (state_ != IN_PROGRESS); 1193 bool is_done = (state_ != IN_PROGRESS_INTERNAL &&
1181 bool was_done = (old_state != IN_PROGRESS); 1194 state_ != COMPLETING_INTERNAL);
1195 bool was_done = (old_state != IN_PROGRESS_INTERNAL &&
1196 old_state != COMPLETING_INTERNAL);
1182 if (is_done && !was_done) 1197 if (is_done && !was_done)
1183 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE); 1198 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE);
1184 } 1199 }
1185 1200
1186 void DownloadItemImpl::SetDangerType(content::DownloadDangerType danger_type) { 1201 void DownloadItemImpl::SetDangerType(content::DownloadDangerType danger_type) {
1187 danger_type_ = danger_type; 1202 danger_type_ = danger_type;
1188 // Notify observers if the safety state has changed as a result of the new 1203 // Notify observers if the safety state has changed as a result of the new
1189 // danger type. 1204 // danger type.
1190 SafetyState updated_value = IsDangerous() ? 1205 SafetyState updated_value = IsDangerous() ?
1191 DownloadItem::DANGEROUS : DownloadItem::SAFE; 1206 DownloadItem::DANGEROUS : DownloadItem::SAFE;
(...skipping 13 matching lines...) Expand all
1205 << " " << DebugString(true); 1220 << " " << DebugString(true);
1206 DCHECK(!new_path.empty()); 1221 DCHECK(!new_path.empty());
1207 current_path_ = new_path; 1222 current_path_ = new_path;
1208 1223
1209 bound_net_log_.AddEvent( 1224 bound_net_log_.AddEvent(
1210 net::NetLog::TYPE_DOWNLOAD_ITEM_RENAMED, 1225 net::NetLog::TYPE_DOWNLOAD_ITEM_RENAMED,
1211 base::Bind(&download_net_logs::ItemRenamedCallback, 1226 base::Bind(&download_net_logs::ItemRenamedCallback,
1212 &current_path_, &new_path)); 1227 &current_path_, &new_path));
1213 } 1228 }
1214 1229
1230 // static
1231 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState(
1232 DownloadInternalState internal_state) {
1233 switch (internal_state) {
1234 case IN_PROGRESS_INTERNAL:
1235 return IN_PROGRESS;
1236 case COMPLETING_INTERNAL:
1237 return IN_PROGRESS;
1238 case COMPLETE_INTERNAL:
1239 return COMPLETE;
1240 case CANCELLED_INTERNAL:
1241 return CANCELLED;
1242 case INTERRUPTED_INTERNAL:
1243 return INTERRUPTED;
1244 default:
1245 NOTREACHED();
1246 }
1247 return MAX_DOWNLOAD_STATE;
1248 }
1215 1249
1250 // static
1251 DownloadItemImpl::DownloadInternalState
1252 DownloadItemImpl::ExternalToInternalState(
1253 DownloadState external_state) {
1254 switch (external_state) {
1255 case IN_PROGRESS:
1256 return IN_PROGRESS_INTERNAL;
1257 case COMPLETE:
1258 return COMPLETE_INTERNAL;
1259 case CANCELLED:
1260 return CANCELLED_INTERNAL;
1261 case INTERRUPTED:
1262 return INTERRUPTED_INTERNAL;
1263 default:
1264 NOTREACHED();
1265 }
1266 return MAX_DOWNLOAD_INTERNAL_STATE;
1267 }
1216 1268
1217 1269 const char* DownloadItemImpl::DebugDownloadStateString(
1270 DownloadInternalState state) {
1271 switch (state) {
1272 case IN_PROGRESS_INTERNAL:
1273 return "IN_PROGRESS";
1274 case COMPLETING_INTERNAL:
1275 return "COMPLETING";
1276 case COMPLETE_INTERNAL:
1277 return "COMPLETE";
1278 case CANCELLED_INTERNAL:
1279 return "CANCELLED";
1280 case INTERRUPTED_INTERNAL:
1281 return "INTERRUPTED";
1282 default:
1283 NOTREACHED() << "Unknown download state " << state;
1284 return "unknown";
1285 };
1286 }
OLDNEW
« no previous file with comments | « content/browser/download/download_item_impl.h ('k') | content/browser/download/download_item_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698