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

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

Issue 10831302: Download resumption - Preliminary (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fixed signed/unsigned compare issue. Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // File method ordering: Methods in this file are in the same order as 5 // File method ordering: Methods in this file are in the same order as
6 // in download_item_impl.h, with the following exception: The public 6 // in download_item_impl.h, with the following exception: The public
7 // interfaces Start, MaybeCompleteDownload, and OnDownloadCompleting 7 // interfaces Start, MaybeCompleteDownload, and OnDownloadCompleting
8 // are placed in chronological order with the other (private) routines 8 // are placed in chronological order with the other (private) routines
9 // that together define a DownloadItem's state transitions 9 // 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 23 matching lines...) Expand all
34 #include "base/metrics/histogram.h" 34 #include "base/metrics/histogram.h"
35 #include "base/stl_util.h" 35 #include "base/stl_util.h"
36 #include "base/stringprintf.h" 36 #include "base/stringprintf.h"
37 #include "base/utf_string_conversions.h" 37 #include "base/utf_string_conversions.h"
38 #include "content/browser/download/download_create_info.h" 38 #include "content/browser/download/download_create_info.h"
39 #include "content/browser/download/download_file.h" 39 #include "content/browser/download/download_file.h"
40 #include "content/browser/download/download_interrupt_reasons_impl.h" 40 #include "content/browser/download/download_interrupt_reasons_impl.h"
41 #include "content/browser/download/download_item_impl_delegate.h" 41 #include "content/browser/download/download_item_impl_delegate.h"
42 #include "content/browser/download/download_request_handle.h" 42 #include "content/browser/download/download_request_handle.h"
43 #include "content/browser/download/download_stats.h" 43 #include "content/browser/download/download_stats.h"
44 #include "content/browser/renderer_host/render_view_host_impl.h"
44 #include "content/browser/web_contents/web_contents_impl.h" 45 #include "content/browser/web_contents/web_contents_impl.h"
46 #include "content/public/browser/browser_context.h"
45 #include "content/public/browser/browser_thread.h" 47 #include "content/public/browser/browser_thread.h"
46 #include "content/public/browser/content_browser_client.h" 48 #include "content/public/browser/content_browser_client.h"
49 #include "content/public/browser/download_interrupt_reasons.h"
50 #include "content/public/browser/download_url_parameters.h"
51 #include "content/public/common/referrer.h"
47 #include "net/base/net_util.h" 52 #include "net/base/net_util.h"
48 53
49 namespace content { 54 namespace content {
55
50 namespace { 56 namespace {
51 57
52 static void DeleteDownloadedFile(const FilePath& path) { 58 void DeleteDownloadedFile(const FilePath& path) {
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
54 60
55 // Make sure we only delete files. 61 // Make sure we only delete files.
56 if (!file_util::DirectoryExists(path)) 62 if (!file_util::DirectoryExists(path))
57 file_util::Delete(path, false); 63 file_util::Delete(path, false);
58 } 64 }
59 65
60 const char* DebugSafetyStateString(DownloadItem::SafetyState state) { 66 const char* DebugSafetyStateString(DownloadItem::SafetyState state) {
61 switch (state) { 67 switch (state) {
62 case DownloadItem::SAFE: 68 case DownloadItem::SAFE:
(...skipping 20 matching lines...) Expand all
83 // DownloadRequestHandleInterface calls 89 // DownloadRequestHandleInterface calls
84 virtual WebContents* GetWebContents() const OVERRIDE { 90 virtual WebContents* GetWebContents() const OVERRIDE {
85 return NULL; 91 return NULL;
86 } 92 }
87 virtual DownloadManager* GetDownloadManager() const OVERRIDE { 93 virtual DownloadManager* GetDownloadManager() const OVERRIDE {
88 return NULL; 94 return NULL;
89 } 95 }
90 virtual void PauseRequest() const OVERRIDE {} 96 virtual void PauseRequest() const OVERRIDE {}
91 virtual void ResumeRequest() const OVERRIDE {} 97 virtual void ResumeRequest() const OVERRIDE {}
92 virtual void CancelRequest() const OVERRIDE {} 98 virtual void CancelRequest() const OVERRIDE {}
99 virtual void SetRequestId(int new_request_id) OVERRIDE {}
100 virtual int RequestId() const OVERRIDE { return -1; }
93 virtual std::string DebugString() const OVERRIDE { 101 virtual std::string DebugString() const OVERRIDE {
94 return "Null DownloadRequestHandle"; 102 return "Null DownloadRequestHandle";
95 } 103 }
96 }; 104 };
97 105
98 // Wrapper around DownloadFile::Detach and DownloadFile::Cancel that 106 // Wrapper around DownloadFile::Detach and DownloadFile::Cancel that
99 // takes ownership of the DownloadFile and hence implicitly destroys it 107 // takes ownership of the DownloadFile and hence implicitly destroys it
100 // at the end of the function. 108 // at the end of the function.
101 static void DownloadFileDetach(scoped_ptr<DownloadFile> download_file) { 109 static void DownloadFileDetach(scoped_ptr<DownloadFile> download_file) {
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
103 download_file->Detach(); 111 download_file->Detach();
104 } 112 }
105 113
106 static void DownloadFileCancel(scoped_ptr<DownloadFile> download_file) { 114 static void DownloadFileCancel(scoped_ptr<DownloadFile> download_file) {
107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
108 download_file->Cancel(); 116 download_file->Cancel();
109 } 117 }
110 118
111 } // namespace 119 } // namespace
112 120
113 const char DownloadItem::kEmptyFileHash[] = ""; 121 const char DownloadItem::kEmptyFileHash[] = "";
114 122
123 // The maximum number of attempts we will make to resume automatically.
124 const int DownloadItemImpl::kMaxAutoResumeAttempts = 5;
125
115 // Constructor for reading from the history service. 126 // Constructor for reading from the history service.
116 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, 127 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
117 DownloadId download_id, 128 DownloadId download_id,
118 const FilePath& path, 129 const FilePath& path,
119 const GURL& url, 130 const GURL& url,
120 const GURL& referrer_url, 131 const GURL& referrer_url,
121 const base::Time& start_time, 132 const base::Time& start_time,
122 const base::Time& end_time, 133 const base::Time& end_time,
123 int64 received_bytes, 134 int64 received_bytes,
124 int64 total_bytes, 135 int64 total_bytes,
(...skipping 13 matching lines...) Expand all
138 received_bytes_(received_bytes), 149 received_bytes_(received_bytes),
139 bytes_per_sec_(0), 150 bytes_per_sec_(0),
140 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), 151 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
141 start_tick_(base::TimeTicks()), 152 start_tick_(base::TimeTicks()),
142 state_(ExternalToInternalState(state)), 153 state_(ExternalToInternalState(state)),
143 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), 154 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
144 start_time_(start_time), 155 start_time_(start_time),
145 end_time_(end_time), 156 end_time_(end_time),
146 delegate_(delegate), 157 delegate_(delegate),
147 is_paused_(false), 158 is_paused_(false),
159 is_resuming_(false),
160 auto_resume_count_(0),
148 open_when_complete_(false), 161 open_when_complete_(false),
149 file_externally_removed_(false), 162 file_externally_removed_(false),
150 safety_state_(SAFE), 163 safety_state_(SAFE),
151 auto_opened_(false), 164 auto_opened_(false),
152 is_temporary_(false), 165 is_temporary_(false),
153 all_data_saved_(false), 166 all_data_saved_(false),
154 opened_(opened), 167 opened_(opened),
155 open_enabled_(true), 168 open_enabled_(true),
156 delegate_delayed_complete_(false), 169 delegate_delayed_complete_(false),
157 bound_net_log_(bound_net_log), 170 bound_net_log_(bound_net_log),
158 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { 171 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
159 delegate_->Attach(); 172 delegate_->Attach();
160 if (state_ == IN_PROGRESS_INTERNAL) 173 if (state_ == IN_PROGRESS_INTERNAL)
161 state_ = CANCELLED_INTERNAL; 174 state_ = CANCELLED_INTERNAL;
162 if (state_ == COMPLETE_INTERNAL) 175 if (state_ == COMPLETE_INTERNAL)
163 all_data_saved_ = true; 176 all_data_saved_ = true;
164 Init(false /* not actively downloading */, SRC_HISTORY_IMPORT); 177 Init(false /* not actively downloading */, SRC_HISTORY_IMPORT);
165 } 178 }
166 179
167 // Constructing for a regular download: 180 // Constructing for a regular download:
168 DownloadItemImpl::DownloadItemImpl( 181 DownloadItemImpl::DownloadItemImpl(
169 DownloadItemImplDelegate* delegate, 182 DownloadItemImplDelegate* delegate,
170 const DownloadCreateInfo& info, 183 const DownloadCreateInfo& info,
171 scoped_ptr<DownloadRequestHandleInterface> request_handle,
172 const net::BoundNetLog& bound_net_log) 184 const net::BoundNetLog& bound_net_log)
173 : is_save_package_download_(false), 185 : is_save_package_download_(false),
174 request_handle_(request_handle.Pass()),
175 download_id_(info.download_id), 186 download_id_(info.download_id),
176 target_disposition_( 187 target_disposition_(
177 (info.save_info->prompt_for_save_location) ? 188 (info.save_info->prompt_for_save_location) ?
178 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE), 189 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE),
179 url_chain_(info.url_chain), 190 url_chain_(info.url_chain),
180 referrer_url_(info.referrer_url), 191 referrer_url_(info.referrer_url),
181 suggested_filename_(UTF16ToUTF8(info.save_info->suggested_name)), 192 suggested_filename_(UTF16ToUTF8(info.save_info->suggested_name)),
182 forced_file_path_(info.save_info->file_path), 193 forced_file_path_(info.save_info->file_path),
183 transition_type_(info.transition_type), 194 transition_type_(info.transition_type),
184 has_user_gesture_(info.has_user_gesture), 195 has_user_gesture_(info.has_user_gesture),
185 content_disposition_(info.content_disposition), 196 content_disposition_(info.content_disposition),
186 mime_type_(info.mime_type), 197 mime_type_(info.mime_type),
187 original_mime_type_(info.original_mime_type), 198 original_mime_type_(info.original_mime_type),
188 remote_address_(info.remote_address), 199 remote_address_(info.remote_address),
189 total_bytes_(info.total_bytes), 200 total_bytes_(info.total_bytes),
190 received_bytes_(0), 201 received_bytes_(0),
191 bytes_per_sec_(0), 202 bytes_per_sec_(0),
192 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), 203 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
193 start_tick_(base::TimeTicks::Now()), 204 start_tick_(base::TimeTicks::Now()),
194 state_(IN_PROGRESS_INTERNAL), 205 state_(IN_PROGRESS_INTERNAL),
195 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), 206 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
196 start_time_(info.start_time), 207 start_time_(info.start_time),
197 delegate_(delegate), 208 delegate_(delegate),
198 is_paused_(false), 209 is_paused_(false),
210 is_resuming_(false),
211 auto_resume_count_(0),
199 open_when_complete_(false), 212 open_when_complete_(false),
200 file_externally_removed_(false), 213 file_externally_removed_(false),
201 safety_state_(SAFE), 214 safety_state_(SAFE),
202 auto_opened_(false), 215 auto_opened_(false),
203 is_temporary_(!info.save_info->file_path.empty()), 216 is_temporary_(!info.save_info->file_path.empty()),
204 all_data_saved_(false), 217 all_data_saved_(false),
205 opened_(false), 218 opened_(false),
206 open_enabled_(true), 219 open_enabled_(true),
207 delegate_delayed_complete_(false), 220 delegate_delayed_complete_(false),
208 bound_net_log_(bound_net_log), 221 bound_net_log_(bound_net_log),
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 total_bytes_(0), 255 total_bytes_(0),
243 received_bytes_(0), 256 received_bytes_(0),
244 bytes_per_sec_(0), 257 bytes_per_sec_(0),
245 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), 258 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
246 start_tick_(base::TimeTicks::Now()), 259 start_tick_(base::TimeTicks::Now()),
247 state_(IN_PROGRESS_INTERNAL), 260 state_(IN_PROGRESS_INTERNAL),
248 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), 261 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
249 start_time_(base::Time::Now()), 262 start_time_(base::Time::Now()),
250 delegate_(delegate), 263 delegate_(delegate),
251 is_paused_(false), 264 is_paused_(false),
265 is_resuming_(false),
266 auto_resume_count_(0),
252 open_when_complete_(false), 267 open_when_complete_(false),
253 file_externally_removed_(false), 268 file_externally_removed_(false),
254 safety_state_(SAFE), 269 safety_state_(SAFE),
255 auto_opened_(false), 270 auto_opened_(false),
256 is_temporary_(false), 271 is_temporary_(false),
257 all_data_saved_(false), 272 all_data_saved_(false),
258 opened_(false), 273 opened_(false),
259 open_enabled_(true), 274 open_enabled_(true),
260 delegate_delayed_complete_(false), 275 delegate_delayed_complete_(false),
261 bound_net_log_(bound_net_log), 276 bound_net_log_(bound_net_log),
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 base::Bind(&ItemCheckedNetLogCallback, 330 base::Bind(&ItemCheckedNetLogCallback,
316 GetDangerType(), GetSafetyState())); 331 GetDangerType(), GetSafetyState()));
317 332
318 UpdateObservers(); 333 UpdateObservers();
319 334
320 MaybeCompleteDownload(); 335 MaybeCompleteDownload();
321 } 336 }
322 337
323 void DownloadItemImpl::TogglePause() { 338 void DownloadItemImpl::TogglePause() {
324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
325 DCHECK(state_ == IN_PROGRESS_INTERNAL || state_ == COMPLETING_INTERNAL); 340 DCHECK(IsPartialDownload());
326 VLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 341 VLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
327 342
328 // Ignore pauses when we've passed the commit point. 343 // Ignore pauses when we've passed the commit point.
329 if (state_ == COMPLETING_INTERNAL) 344 if (state_ == COMPLETING_INTERNAL)
330 return; 345 return;
331 346
332 if (is_paused_) 347 if (IsInProgress()) {
333 request_handle_->ResumeRequest(); 348 if (is_paused_)
334 else 349 request_handle_->ResumeRequest();
335 request_handle_->PauseRequest(); 350 else
336 is_paused_ = !is_paused_; 351 request_handle_->PauseRequest();
352 is_paused_ = !is_paused_;
353 } else if (IsInterrupted()) {
354 auto_resume_count_ = 0; // User input resets the counter.
355 ResumeInterruptedDownload();
356 }
357
337 UpdateObservers(); 358 UpdateObservers();
338 } 359 }
339 360
340 void DownloadItemImpl::Cancel(bool user_cancel) { 361 void DownloadItemImpl::Cancel(bool user_cancel) {
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
342 363
343 last_reason_ = user_cancel ?
344 DOWNLOAD_INTERRUPT_REASON_USER_CANCELED :
345 DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
346
347 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); 364 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
348 if (state_ != IN_PROGRESS_INTERNAL) { 365 if (state_ != IN_PROGRESS_INTERNAL && state_ != INTERRUPTED_INTERNAL) {
349 // Small downloads might be complete before this method has 366 // Small downloads might be complete before this method has
350 // a chance to run. 367 // a chance to run.
351 return; 368 return;
352 } 369 }
353 370
371 last_reason_ = user_cancel ?
372 DOWNLOAD_INTERRUPT_REASON_USER_CANCELED :
373 DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
374
354 RecordDownloadCount(CANCELLED_COUNT); 375 RecordDownloadCount(CANCELLED_COUNT);
355 376
356 TransitionTo(CANCELLED_INTERNAL); 377 TransitionTo(CANCELLED_INTERNAL);
357 378
358 CancelDownloadFile(); 379 CancelDownloadFile();
359 380
360 // Cancel the originating URL request. 381 // Cancel the originating URL request.
361 request_handle_->CancelRequest(); 382 request_handle_->CancelRequest();
362 383
363 delegate_->DownloadStopped(this); 384 delegate_->DownloadStopped(this);
364 } 385 }
365 386
366 void DownloadItemImpl::Delete(DeleteReason reason) { 387 void DownloadItemImpl::Delete(DeleteReason reason) {
388 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
367 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
368 390
369 switch (reason) { 391 switch (reason) {
370 case DELETE_DUE_TO_USER_DISCARD: 392 case DELETE_DUE_TO_USER_DISCARD:
371 UMA_HISTOGRAM_ENUMERATION( 393 UMA_HISTOGRAM_ENUMERATION(
372 "Download.UserDiscard", GetDangerType(), 394 "Download.UserDiscard", GetDangerType(),
373 DOWNLOAD_DANGER_TYPE_MAX); 395 DOWNLOAD_DANGER_TYPE_MAX);
374 break; 396 break;
375 case DELETE_DUE_TO_BROWSER_SHUTDOWN: 397 case DELETE_DUE_TO_BROWSER_SHUTDOWN:
376 UMA_HISTOGRAM_ENUMERATION( 398 UMA_HISTOGRAM_ENUMERATION(
377 "Download.Discard", GetDangerType(), 399 "Download.Discard", GetDangerType(),
378 DOWNLOAD_DANGER_TYPE_MAX); 400 DOWNLOAD_DANGER_TYPE_MAX);
379 break; 401 break;
380 default: 402 default:
381 NOTREACHED(); 403 NOTREACHED();
382 } 404 }
383 405
384 // Delete the file if it exists and is not owned by a DownloadFile object. 406 // Delete the file if it exists and is not owned by a DownloadFile object.
385 // (In the latter case the DownloadFile object will delete it on cancel.) 407 // (In the latter case the DownloadFile object will delete it on cancel.)
386 if (!current_path_.empty() && download_file_.get() == NULL) { 408 if (!current_path_.empty() && download_file_.get() == NULL) {
387 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 409 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
388 base::Bind(&DeleteDownloadedFile, current_path_)); 410 base::Bind(&DeleteDownloadedFile, current_path_));
389 } 411 }
390 Remove(); 412 Remove();
391 // We have now been deleted. 413 // We have now been deleted.
392 } 414 }
393 415
394 void DownloadItemImpl::Remove() { 416 void DownloadItemImpl::Remove() {
417 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
396 419
397 delegate_->AssertStateConsistent(this); 420 delegate_->AssertStateConsistent(this);
398 Cancel(true); 421 Cancel(true);
399 delegate_->AssertStateConsistent(this); 422 delegate_->AssertStateConsistent(this);
400 423
401 NotifyRemoved(); 424 NotifyRemoved();
402 delegate_->DownloadRemoved(this); 425 delegate_->DownloadRemoved(this);
403 // We have now been deleted. 426 // We have now been deleted.
404 } 427 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 } 477 }
455 478
456 DownloadInterruptReason DownloadItemImpl::GetLastReason() const { 479 DownloadInterruptReason DownloadItemImpl::GetLastReason() const {
457 return last_reason_; 480 return last_reason_;
458 } 481 }
459 482
460 bool DownloadItemImpl::IsPaused() const { 483 bool DownloadItemImpl::IsPaused() const {
461 return is_paused_; 484 return is_paused_;
462 } 485 }
463 486
487 bool DownloadItemImpl::IsResuming() const {
488 return is_resuming_;
489 }
490
491 bool DownloadItemImpl::CanResumeInterrupted() const {
492 return GetResumeMode() != RESUME_MODE_INVALID;
493 }
494
495 DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const {
496 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
497 if (!IsInterrupted())
498 return RESUME_MODE_INVALID;
499
500 ResumeMode mode = RESUME_MODE_INVALID;
501
502 switch(last_reason_) {
503 case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
504 case DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
505 mode = RESUME_MODE_IMMEDIATE_CONTINUE; // Continue immediately.
506 break;
507
508 case DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION:
509 case DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
510 mode = RESUME_MODE_IMMEDIATE_RESTART; // Restart immediately.
511 break;
512
513 case DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
514 case DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
515 case DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
516 case DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
517 case DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
518 case DOWNLOAD_INTERRUPT_REASON_CRASH:
519 mode = RESUME_MODE_USER_CONTINUE; // Continue via user input.
520 break;
521
522 case DOWNLOAD_INTERRUPT_REASON_FILE_FAILED:
523 case DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
524 case DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
525 case DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
526 case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
527 mode = RESUME_MODE_USER_RESTART; // Restart via user input.
528 break;
529
530 case DOWNLOAD_INTERRUPT_REASON_NONE:
531 case DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
532 case DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT:
533 case DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
534 break;
535
536 case DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
537 case DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
538 break;
539 }
540
541 // Check if we have exhausted the number of automatic retry attempts.
542 if (auto_resume_count_ >= kMaxAutoResumeAttempts) {
543 if (mode == RESUME_MODE_IMMEDIATE_CONTINUE)
544 mode = RESUME_MODE_USER_CONTINUE;
545 else if (mode == RESUME_MODE_IMMEDIATE_RESTART)
546 mode = RESUME_MODE_USER_RESTART;
547 }
548
549 return mode;
550 }
551
552 void DownloadItemImpl::AutoResumeIfValid() {
553 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true);
554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
555 ResumeMode mode = GetResumeMode();
556
557 if ((mode == RESUME_MODE_IMMEDIATE_RESTART) ||
558 (mode == RESUME_MODE_IMMEDIATE_CONTINUE)) {
559 if (mode == RESUME_MODE_IMMEDIATE_RESTART) {
560 received_bytes_ = 0; // Restart instead of continuing.
561 hash_state_ = "";
562 last_modified_time_ = "";
563 etag_ = "";
564 }
565
566 auto_resume_count_++;
567
568 ResumeInterruptedDownload();
569 }
570 }
571
464 bool DownloadItemImpl::IsTemporary() const { 572 bool DownloadItemImpl::IsTemporary() const {
465 return is_temporary_; 573 return is_temporary_;
466 } 574 }
467 575
468 // TODO(ahendrickson) -- Move |INTERRUPTED| from |IsCancelled()| to
469 // |IsPartialDownload()|, when resuming interrupted downloads is implemented.
470 bool DownloadItemImpl::IsPartialDownload() const { 576 bool DownloadItemImpl::IsPartialDownload() const {
471 return InternalToExternalState(state_) == IN_PROGRESS; 577 DownloadState state = InternalToExternalState(state_);
578 return (state == IN_PROGRESS) || (state == INTERRUPTED);
472 } 579 }
473 580
474 bool DownloadItemImpl::IsInProgress() const { 581 bool DownloadItemImpl::IsInProgress() const {
475 return InternalToExternalState(state_) == IN_PROGRESS; 582 return InternalToExternalState(state_) == IN_PROGRESS;
476 } 583 }
477 584
478 bool DownloadItemImpl::IsCancelled() const { 585 bool DownloadItemImpl::IsCancelled() const {
479 DownloadState external_state = InternalToExternalState(state_); 586 return InternalToExternalState(state_) == CANCELLED;
480 return external_state == CANCELLED || external_state == INTERRUPTED;
481 } 587 }
482 588
483 bool DownloadItemImpl::IsInterrupted() const { 589 bool DownloadItemImpl::IsInterrupted() const {
484 return InternalToExternalState(state_) == INTERRUPTED; 590 return InternalToExternalState(state_) == INTERRUPTED;
485 } 591 }
486 592
487 bool DownloadItemImpl::IsComplete() const { 593 bool DownloadItemImpl::IsComplete() const {
488 return InternalToExternalState(state_) == COMPLETE; 594 return InternalToExternalState(state_) == COMPLETE;
489 } 595 }
490 596
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
658 } 764 }
659 765
660 bool DownloadItemImpl::CanShowInFolder() { 766 bool DownloadItemImpl::CanShowInFolder() {
661 return state_ != CANCELLED_INTERNAL && !file_externally_removed_; 767 return state_ != CANCELLED_INTERNAL && !file_externally_removed_;
662 } 768 }
663 769
664 bool DownloadItemImpl::CanOpenDownload() { 770 bool DownloadItemImpl::CanOpenDownload() {
665 return !file_externally_removed_; 771 return !file_externally_removed_;
666 } 772 }
667 773
774 bool DownloadItemImpl::CanResumeDownload() const {
775 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
776
777 // Do not allow interrupted downloads to be resumed until the target name
778 // has been determined, and the user has validated any dangerous items.
779 // TODO(rdsmith) -- Add a state indicating that filename determination has
780 // occurred.
781 if (GetTargetFilePath().empty())
782 return false;
783
784 if (GetSafetyState() == DANGEROUS)
785 return false;
786
787 return IsInProgress() || CanResumeInterrupted();
788 }
789
668 bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() { 790 bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() {
669 return delegate_->ShouldOpenFileBasedOnExtension(GetUserVerifiedFilePath()); 791 return delegate_->ShouldOpenFileBasedOnExtension(GetUserVerifiedFilePath());
670 } 792 }
671 793
672 bool DownloadItemImpl::GetOpenWhenComplete() const { 794 bool DownloadItemImpl::GetOpenWhenComplete() const {
673 return open_when_complete_; 795 return open_when_complete_;
674 } 796 }
675 797
676 bool DownloadItemImpl::GetAutoOpened() { 798 bool DownloadItemImpl::GetAutoOpened() {
677 return auto_opened_; 799 return auto_opened_;
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
740 url_list += next_url.spec(); 862 url_list += next_url.spec();
741 } 863 }
742 } 864 }
743 865
744 if (verbose) { 866 if (verbose) {
745 description += base::StringPrintf( 867 description += base::StringPrintf(
746 " total = %" PRId64 868 " total = %" PRId64
747 " received = %" PRId64 869 " received = %" PRId64
748 " reason = %s" 870 " reason = %s"
749 " paused = %c" 871 " paused = %c"
872 " resuming = %c"
873 " resume_mode = %s"
874 " auto_resume_count = %d"
750 " safety = %s" 875 " safety = %s"
876 " all_data_saved = %c"
751 " last_modified = '%s'" 877 " last_modified = '%s'"
752 " etag = '%s'" 878 " etag = '%s'"
879 " has_download_file = %s"
753 " url_chain = \n\t\"%s\"\n\t" 880 " url_chain = \n\t\"%s\"\n\t"
754 " full_path = \"%" PRFilePath "\"" 881 " full_path = \"%" PRFilePath "\"\n\t"
755 " target_path = \"%" PRFilePath "\"" 882 " target_path = \"%" PRFilePath "\"",
756 " has download file = %s",
757 GetTotalBytes(), 883 GetTotalBytes(),
758 GetReceivedBytes(), 884 GetReceivedBytes(),
759 InterruptReasonDebugString(last_reason_).c_str(), 885 InterruptReasonDebugString(last_reason_).c_str(),
760 IsPaused() ? 'T' : 'F', 886 IsPaused() ? 'T' : 'F',
887 IsResuming() ? 'T' : 'F',
888 DebugResumeModeString(GetResumeMode()),
889 auto_resume_count_,
761 DebugSafetyStateString(GetSafetyState()), 890 DebugSafetyStateString(GetSafetyState()),
891 AllDataSaved() ? 'T' : 'F',
762 GetLastModifiedTime().c_str(), 892 GetLastModifiedTime().c_str(),
763 GetETag().c_str(), 893 GetETag().c_str(),
894 download_file_.get() ? "true" : "false",
764 url_list.c_str(), 895 url_list.c_str(),
765 GetFullPath().value().c_str(), 896 GetFullPath().value().c_str(),
766 GetTargetFilePath().value().c_str(), 897 GetTargetFilePath().value().c_str());
767 download_file_.get() ? "true" : "false");
768 } else { 898 } else {
769 description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); 899 description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
770 } 900 }
771 901
772 description += " }"; 902 description += " }";
773 903
774 return description; 904 return description;
775 } 905 }
776 906
777 void DownloadItemImpl::MockDownloadOpenForTesting() { 907 void DownloadItemImpl::MockDownloadOpenForTesting() {
778 open_enabled_ = false; 908 open_enabled_ = false;
779 } 909 }
780 910
781 void DownloadItemImpl::NotifyRemoved() { 911 void DownloadItemImpl::NotifyRemoved() {
782 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this)); 912 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this));
783 } 913 }
784 914
785 void DownloadItemImpl::OnDownloadedFileRemoved() { 915 void DownloadItemImpl::OnDownloadedFileRemoved() {
786 file_externally_removed_ = true; 916 file_externally_removed_ = true;
787 VLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 917 VLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
788 UpdateObservers(); 918 UpdateObservers();
789 } 919 }
790 920
791 base::WeakPtr<DownloadDestinationObserver>
792 DownloadItemImpl::DestinationObserverAsWeakPtr() {
793 return weak_ptr_factory_.GetWeakPtr();
794 }
795
796 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) { 921 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) {
797 total_bytes_ = total_bytes; 922 total_bytes_ = total_bytes;
798 } 923 }
799 924
800 // Updates from the download thread may have been posted while this download 925 // Updates from the download thread may have been posted while this download
801 // was being cancelled in the UI thread, so we'll accept them unless we're 926 // was being cancelled in the UI thread, so we'll accept them unless we're
802 // complete. 927 // complete.
803 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, 928 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far,
804 int64 bytes_per_sec, 929 int64 bytes_per_sec,
805 const std::string& hash_state) { 930 const std::string& hash_state) {
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
942 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data); 1067 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data);
943 } else { 1068 } else {
944 bound_net_log_.AddEvent( 1069 bound_net_log_.AddEvent(
945 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data); 1070 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data);
946 } 1071 }
947 1072
948 VLOG(20) << __FUNCTION__ << "() " << DebugString(true); 1073 VLOG(20) << __FUNCTION__ << "() " << DebugString(true);
949 } 1074 }
950 1075
951 // We're starting the download. 1076 // We're starting the download.
952 void DownloadItemImpl::Start(scoped_ptr<DownloadFile> file) { 1077 void DownloadItemImpl::Start(
1078 scoped_ptr<DownloadFile> file,
1079 scoped_ptr<DownloadRequestHandleInterface> req_handle) {
1080 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
953 DCHECK(!download_file_.get()); 1081 DCHECK(!download_file_.get());
954 DCHECK(file.get()); 1082 DCHECK(file.get());
1083 DCHECK(req_handle.get());
1084
955 download_file_ = file.Pass(); 1085 download_file_ = file.Pass();
1086 request_handle_ = req_handle.Pass();
1087
1088 is_resuming_ = (state_ == INTERRUPTED_INTERNAL);
1089
1090 TransitionTo(IN_PROGRESS_INTERNAL);
1091
1092 last_reason_ = DOWNLOAD_INTERRUPT_REASON_NONE;
1093
1094 if (is_resuming_) {
1095 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadResumed(this));
1096 }
956 1097
957 BrowserThread::PostTask( 1098 BrowserThread::PostTask(
958 BrowserThread::FILE, FROM_HERE, 1099 BrowserThread::FILE, FROM_HERE,
959 base::Bind(&DownloadFile::Initialize, 1100 base::Bind(&DownloadFile::Initialize,
960 // Safe because we control download file lifetime. 1101 // Safe because we control download file lifetime.
961 base::Unretained(download_file_.get()), 1102 base::Unretained(download_file_.get()),
962 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, 1103 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
963 weak_ptr_factory_.GetWeakPtr()))); 1104 weak_ptr_factory_.GetWeakPtr())));
964 } 1105 }
965 1106
966 void DownloadItemImpl::OnDownloadFileInitialized( 1107 void DownloadItemImpl::OnDownloadFileInitialized(
967 DownloadInterruptReason result) { 1108 DownloadInterruptReason result) {
1109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
968 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { 1110 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
969 Interrupt(result); 1111 Interrupt(result);
970 // TODO(rdsmith): It makes no sense to continue along the 1112 // TODO(rdsmith): It makes no sense to continue along the
971 // regular download path after we've gotten an error. But it's 1113 // regular download path after we've gotten an error. But it's
972 // the way the code has historically worked, and this allows us 1114 // the way the code has historically worked, and this allows us
973 // to get the download persisted and observers of the download manager 1115 // to get the download persisted and observers of the download manager
974 // notified, so tests work. When we execute all side effects of cancel 1116 // notified, so tests work. When we execute all side effects of cancel
975 // (including queue removal) immedately rather than waiting for 1117 // (including queue removal) immediately rather than waiting for
976 // persistence we should replace this comment with a "return;". 1118 // persistence we should replace this comment with a "return;".
977 } 1119 }
978 1120
979 delegate_->DetermineDownloadTarget( 1121 delegate_->DetermineDownloadTarget(
980 this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined, 1122 this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined,
981 weak_ptr_factory_.GetWeakPtr())); 1123 weak_ptr_factory_.GetWeakPtr()));
982 } 1124 }
983 1125
984 // Called by delegate_ when the download target path has been 1126 // Called by delegate_ when the download target path has been
985 // determined. 1127 // determined.
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1090 if (state_ != IN_PROGRESS_INTERNAL) 1232 if (state_ != IN_PROGRESS_INTERNAL)
1091 return; 1233 return;
1092 1234
1093 // Give the delegate a chance to override. 1235 // Give the delegate a chance to override.
1094 delegate_->ReadyForDownloadCompletion( 1236 delegate_->ReadyForDownloadCompletion(
1095 this, base::Bind(&DownloadItemImpl::ReadyForDownloadCompletionDone, 1237 this, base::Bind(&DownloadItemImpl::ReadyForDownloadCompletionDone,
1096 weak_ptr_factory_.GetWeakPtr())); 1238 weak_ptr_factory_.GetWeakPtr()));
1097 } 1239 }
1098 1240
1099 void DownloadItemImpl::ReadyForDownloadCompletionDone() { 1241 void DownloadItemImpl::ReadyForDownloadCompletionDone() {
1242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1243
1100 if (state_ != IN_PROGRESS_INTERNAL) 1244 if (state_ != IN_PROGRESS_INTERNAL)
1101 return; 1245 return;
1102 1246
1103 VLOG(20) << __FUNCTION__ << "()" 1247 VLOG(20) << __FUNCTION__ << "()" << " " << DebugString(true);
1104 << " " << DebugString(true);
1105 DCHECK(!GetTargetFilePath().empty()); 1248 DCHECK(!GetTargetFilePath().empty());
1106 DCHECK_NE(DANGEROUS, GetSafetyState()); 1249 DCHECK_NE(DANGEROUS, GetSafetyState());
1107 1250
1108 // TODO(rdsmith/benjhayden): Remove as part of SavePackage integration. 1251 // TODO(rdsmith/benjhayden): Remove as part of SavePackage integration.
1109 if (is_save_package_download_) { 1252 if (is_save_package_download_) {
1110 // Avoid doing anything on the file thread; there's nothing we control 1253 // Avoid doing anything on the file thread; there's nothing we control
1111 // there. 1254 // there.
1112 // Strictly speaking, this skips giving the embedder a chance to open 1255 // Strictly speaking, this skips giving the embedder a chance to open
1113 // the download. But on a save package download, there's no real 1256 // the download. But on a save package download, there's no real
1114 // concept of opening. 1257 // concept of opening.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1173 if (delegate_->ShouldOpenDownload( 1316 if (delegate_->ShouldOpenDownload(
1174 this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened, 1317 this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened,
1175 weak_ptr_factory_.GetWeakPtr()))) { 1318 weak_ptr_factory_.GetWeakPtr()))) {
1176 Completed(); 1319 Completed();
1177 } else { 1320 } else {
1178 delegate_delayed_complete_ = true; 1321 delegate_delayed_complete_ = true;
1179 } 1322 }
1180 } 1323 }
1181 1324
1182 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { 1325 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) {
1326 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1327
1183 auto_opened_ = auto_opened; 1328 auto_opened_ = auto_opened;
1184 Completed(); 1329 Completed();
1185 } 1330 }
1186 1331
1187 void DownloadItemImpl::Completed() { 1332 void DownloadItemImpl::Completed() {
1188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1189 1334
1190 VLOG(20) << __FUNCTION__ << "() " << DebugString(false); 1335 VLOG(20) << __FUNCTION__ << "() " << DebugString(false);
1191 1336
1192 DCHECK(all_data_saved_); 1337 DCHECK(all_data_saved_);
(...skipping 13 matching lines...) Expand all
1206 if (!IsTemporary()) 1351 if (!IsTemporary())
1207 OpenDownload(); 1352 OpenDownload();
1208 1353
1209 auto_opened_ = true; 1354 auto_opened_ = true;
1210 UpdateObservers(); 1355 UpdateObservers();
1211 } 1356 }
1212 } 1357 }
1213 1358
1214 // **** End of Download progression cascade 1359 // **** End of Download progression cascade
1215 1360
1361 void DownloadItemImpl::ResumeInterruptedDownload() {
1362 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1363
1364 // Handle the case of clicking 'Resume' in the download shelf.
1365 DCHECK(IsInterrupted());
1366
1367 DVLOG(20) << __FUNCTION__ << "()" << DebugString(true);
1368
1369 // Restart the download.
1370 if (!GetWebContents()) {
1371 Interrupt(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
1372 return;
1373 }
1374
1375 scoped_ptr<DownloadUrlParameters> download_params(
1376 DownloadUrlParameters::FromWebContents(GetWebContents(),
1377 GetOriginalUrl()));
1378
1379 download_params->set_file_path(GetFullPath());
1380 download_params->set_offset(GetReceivedBytes());
1381 download_params->set_hash_state(GetHashState());
1382
1383 Referrer referrer(GetReferrerUrl(), WebKit::WebReferrerPolicyDefault);
1384 download_params->set_referrer(referrer);
1385 download_params->set_last_modified(GetLastModifiedTime());
1386 download_params->set_etag(GetETag());
1387 download_params->set_callback(DownloadUrlParameters::OnStartedCallback());
1388
1389 delegate_->ResumeInterruptedDownload(download_params.Pass(), GetGlobalId());
1390 }
1391
1216 // An error occurred somewhere. 1392 // An error occurred somewhere.
1217 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { 1393 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) {
1394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1395
1218 // Somewhat counter-intuitively, it is possible for us to receive an 1396 // Somewhat counter-intuitively, it is possible for us to receive an
1219 // interrupt after we've already been interrupted. The generation of 1397 // interrupt after we've already been interrupted. The generation of
1220 // interrupts from the file thread Renames and the generation of 1398 // interrupts from the file thread Renames and the generation of
1221 // interrupts from disk writes go through two different mechanisms (driven 1399 // interrupts from disk writes go through two different mechanisms (driven
1222 // by rename requests from UI thread and by write requests from IO thread, 1400 // by rename requests from UI thread and by write requests from IO thread,
1223 // respectively), and since we choose not to keep state on the File thread, 1401 // respectively), and since we choose not to keep state on the File thread,
1224 // this is the place where the races collide. It's also possible for 1402 // this is the place where the races collide. It's also possible for
1225 // interrupts to race with cancels. 1403 // interrupts to race with cancels.
1226 1404
1227 // Whatever happens, the first one to hit the UI thread wins. 1405 // Whatever happens, the first one to hit the UI thread wins.
1228 if (state_ != IN_PROGRESS_INTERNAL) 1406 if (state_ != IN_PROGRESS_INTERNAL)
1229 return; 1407 return;
1230 1408
1231 last_reason_ = reason; 1409 last_reason_ = reason;
1410 is_resuming_ = false;
1411
1232 TransitionTo(INTERRUPTED_INTERNAL); 1412 TransitionTo(INTERRUPTED_INTERNAL);
1233 1413
1234 CancelDownloadFile(); 1414 CancelDownloadFile();
1235 1415
1236 // Cancel the originating URL request. 1416 // Cancel the originating URL request.
1237 request_handle_->CancelRequest(); 1417 request_handle_->CancelRequest();
1238 1418
1419 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadInterrupted(this));
1420
1239 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_); 1421 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_);
1240 delegate_->DownloadStopped(this); 1422 delegate_->DownloadStopped(this);
1423
1424 AutoResumeIfValid();
1425 }
1426
1427 base::WeakPtr<DownloadDestinationObserver>
1428 DownloadItemImpl::DestinationObserverAsWeakPtr() {
1429 return weak_ptr_factory_.GetWeakPtr();
1241 } 1430 }
1242 1431
1243 void DownloadItemImpl::CancelDownloadFile() { 1432 void DownloadItemImpl::CancelDownloadFile() {
1433 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1434
1244 // TODO(rdsmith/benjhayden): Remove condition as part of 1435 // TODO(rdsmith/benjhayden): Remove condition as part of
1245 // SavePackage integration. 1436 // |SavePackage| integration.
1246 // download_file_ can be NULL if Interrupt() is called after the download file 1437 // |download_file_| can be NULL if Interrupt() is called after the
1247 // has been released. 1438 // download file has been released.
1248 if (!is_save_package_download_ && download_file_.get()) { 1439 if (!is_save_package_download_ && download_file_.get()) {
1249 BrowserThread::PostTask( 1440 BrowserThread::PostTask(
1250 BrowserThread::FILE, FROM_HERE, 1441 BrowserThread::FILE, FROM_HERE,
1251 // Will be deleted at end of task execution. 1442 // Will be deleted at end of task execution.
1252 base::Bind(&DownloadFileCancel, base::Passed(download_file_.Pass()))); 1443 base::Bind(&DownloadFileCancel, base::Passed(download_file_.Pass())));
1253 } 1444 }
1254 } 1445 }
1255 1446
1256 bool DownloadItemImpl::IsDownloadReadyForCompletion() { 1447 bool DownloadItemImpl::IsDownloadReadyForCompletion() {
1257 VLOG(20) << __FUNCTION__ << " " << AllDataSaved() 1448 VLOG(20) << __FUNCTION__ << " " << AllDataSaved()
1258 << " " << (GetSafetyState() != DownloadItem::DANGEROUS) 1449 << " " << (GetSafetyState() != DownloadItem::DANGEROUS)
1259 << " " << (state_ == IN_PROGRESS_INTERNAL) 1450 << " " << (state_ == IN_PROGRESS_INTERNAL)
1260 << " " << !GetTargetFilePath().empty() 1451 << " " << !GetTargetFilePath().empty()
1261 << " " << (target_path_.DirName() == current_path_.DirName()); 1452 << " " << (target_path_.DirName() == current_path_.DirName());
1453 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1454
1262 // If we don't have all the data, the download is not ready for 1455 // If we don't have all the data, the download is not ready for
1263 // completion. 1456 // completion.
1264 if (!AllDataSaved()) 1457 if (!AllDataSaved())
1265 return false; 1458 return false;
1266 1459
1267 // If the download is dangerous, but not yet validated, it's not ready for 1460 // If the download is dangerous, but not yet validated, it's not ready for
1268 // completion. 1461 // completion.
1269 if (GetSafetyState() == DownloadItem::DANGEROUS) 1462 if (GetSafetyState() == DownloadItem::DANGEROUS)
1270 return false; 1463 return false;
1271 1464
1272 // If the download isn't active (e.g. has been cancelled) it's not 1465 // If the download isn't active (e.g. has been cancelled) it's not
1273 // ready for completion. 1466 // ready for completion.
1274 if (state_ != IN_PROGRESS_INTERNAL) 1467 if (state_ != IN_PROGRESS_INTERNAL)
1275 return false; 1468 return false;
1276 1469
1277 // If the target filename hasn't been determined, then it's not ready for 1470 // If the target filename hasn't been determined, then it's not ready for
1278 // completion. This is checked in ReadyForDownloadCompletionDone(). 1471 // completion. This is checked in ReadyForDownloadCompletionDone().
1279 if (GetTargetFilePath().empty()) 1472 if (GetTargetFilePath().empty())
1280 return false; 1473 return false;
1281 1474
1282 // This is checked in NeedsRename(). Without this conditional, 1475 // This is checked in NeedsRename(). Without this conditional,
1283 // browser_tests:DownloadTest.DownloadMimeType fails the DCHECK. 1476 // browser_tests:DownloadTest.DownloadMimeType fails the DCHECK.
1284 if (target_path_.DirName() != current_path_.DirName()) 1477 if (target_path_.DirName() != current_path_.DirName())
1285 return false; 1478 return false;
1286 1479
1287 return true; 1480 return true;
1288 } 1481 }
1289 1482
1290 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) { 1483 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {
1484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1485
1291 if (state_ == new_state) 1486 if (state_ == new_state)
1292 return; 1487 return;
1293 1488
1294 DownloadInternalState old_state = state_; 1489 DownloadInternalState old_state = state_;
1295 state_ = new_state; 1490 state_ = new_state;
1296 1491
1297 switch (state_) { 1492 switch (state_) {
1298 case COMPLETING_INTERNAL: 1493 case COMPLETING_INTERNAL:
1299 bound_net_log_.AddEvent( 1494 bound_net_log_.AddEvent(
1300 net::NetLog::TYPE_DOWNLOAD_ITEM_COMPLETING, 1495 net::NetLog::TYPE_DOWNLOAD_ITEM_COMPLETING,
1301 base::Bind(&ItemCompletingNetLogCallback, received_bytes_, &hash_)); 1496 base::Bind(&ItemCompletingNetLogCallback, received_bytes_, &hash_));
1302 break; 1497 break;
1303 case COMPLETE_INTERNAL: 1498 case COMPLETE_INTERNAL:
1304 bound_net_log_.AddEvent( 1499 bound_net_log_.AddEvent(
1305 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED, 1500 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED,
1306 base::Bind(&ItemFinishedNetLogCallback, auto_opened_)); 1501 base::Bind(&ItemFinishedNetLogCallback, auto_opened_));
1307 break; 1502 break;
1308 case INTERRUPTED_INTERNAL: 1503 case INTERRUPTED_INTERNAL:
1309 bound_net_log_.AddEvent( 1504 bound_net_log_.AddEvent(
1310 net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED, 1505 net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED,
1311 base::Bind(&ItemInterruptedNetLogCallback, last_reason_, 1506 base::Bind(&ItemInterruptedNetLogCallback, last_reason_,
1312 received_bytes_, &hash_state_)); 1507 received_bytes_, &hash_state_));
1313 break; 1508 break;
1509 case IN_PROGRESS_INTERNAL:
1510 if (is_resuming_) {
1511 bound_net_log_.AddEvent(
1512 net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED,
1513 base::Bind(&ItemResumingNetLogCallback,
1514 false, last_reason_, received_bytes_, &hash_state_));
1515 }
1516 break;
1314 case CANCELLED_INTERNAL: 1517 case CANCELLED_INTERNAL:
1315 bound_net_log_.AddEvent( 1518 bound_net_log_.AddEvent(
1316 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED, 1519 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED,
1317 base::Bind(&ItemCanceledNetLogCallback, received_bytes_, 1520 base::Bind(&ItemCanceledNetLogCallback, received_bytes_,
1318 &hash_state_)); 1521 &hash_state_));
1319 break; 1522 break;
1320 default: 1523 default:
1321 break; 1524 break;
1322 } 1525 }
1323 1526
1324 VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true) 1527 VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true)
1325 << " " << InternalToExternalState(old_state) 1528 << " " << InternalToExternalState(old_state)
1326 << " " << InternalToExternalState(state_); 1529 << " " << InternalToExternalState(state_);
1327 1530
1328 // Only update observers on user visible state changes. 1531 // Only update observers on user visible state changes.
1329 if (InternalToExternalState(old_state) != InternalToExternalState(state_)) 1532 DownloadState external_state = InternalToExternalState(state_);
1533 DownloadState old_external_state = InternalToExternalState(old_state);
1534
1535 if (old_external_state != external_state)
1330 UpdateObservers(); 1536 UpdateObservers();
1331 1537
1332 bool is_done = (state_ != IN_PROGRESS_INTERNAL && 1538 bool is_done = external_state != IN_PROGRESS;
1333 state_ != COMPLETING_INTERNAL); 1539 bool was_done = old_external_state != IN_PROGRESS;
1334 bool was_done = (old_state != IN_PROGRESS_INTERNAL &&
1335 old_state != COMPLETING_INTERNAL);
1336 if (is_done && !was_done) 1540 if (is_done && !was_done)
1337 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE); 1541 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE);
1338 } 1542 }
1339 1543
1340 void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) { 1544 void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) {
1341 danger_type_ = danger_type; 1545 danger_type_ = danger_type;
1342 // Notify observers if the safety state has changed as a result of the new 1546 // Notify observers if the safety state has changed as a result of the new
1343 // danger type. 1547 // danger type.
1344 SafetyState updated_value = IsDangerous() ? 1548 SafetyState updated_value = IsDangerous() ?
1345 DownloadItem::DANGEROUS : DownloadItem::SAFE; 1549 DownloadItem::DANGEROUS : DownloadItem::SAFE;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1398 case CANCELLED: 1602 case CANCELLED:
1399 return CANCELLED_INTERNAL; 1603 return CANCELLED_INTERNAL;
1400 case INTERRUPTED: 1604 case INTERRUPTED:
1401 return INTERRUPTED_INTERNAL; 1605 return INTERRUPTED_INTERNAL;
1402 default: 1606 default:
1403 NOTREACHED(); 1607 NOTREACHED();
1404 } 1608 }
1405 return MAX_DOWNLOAD_INTERNAL_STATE; 1609 return MAX_DOWNLOAD_INTERNAL_STATE;
1406 } 1610 }
1407 1611
1612 const net::BoundNetLog& DownloadItemImpl::GetBoundNetLog() const {
1613 return bound_net_log_;
1614 }
1615
1408 const char* DownloadItemImpl::DebugDownloadStateString( 1616 const char* DownloadItemImpl::DebugDownloadStateString(
1409 DownloadInternalState state) { 1617 DownloadInternalState state) {
1410 switch (state) { 1618 switch (state) {
1411 case IN_PROGRESS_INTERNAL: 1619 case IN_PROGRESS_INTERNAL:
1412 return "IN_PROGRESS"; 1620 return "IN_PROGRESS";
1413 case COMPLETING_INTERNAL: 1621 case COMPLETING_INTERNAL:
1414 return "COMPLETING"; 1622 return "COMPLETING";
1415 case COMPLETE_INTERNAL: 1623 case COMPLETE_INTERNAL:
1416 return "COMPLETE"; 1624 return "COMPLETE";
1417 case CANCELLED_INTERNAL: 1625 case CANCELLED_INTERNAL:
1418 return "CANCELLED"; 1626 return "CANCELLED";
1419 case INTERRUPTED_INTERNAL: 1627 case INTERRUPTED_INTERNAL:
1420 return "INTERRUPTED"; 1628 return "INTERRUPTED";
1421 default: 1629 default:
1422 NOTREACHED() << "Unknown download state " << state; 1630 NOTREACHED() << "Unknown download state " << state;
1423 return "unknown"; 1631 return "unknown";
1424 }; 1632 };
1425 } 1633 }
1426 1634
1635 const char* DownloadItemImpl::DebugResumeModeString(ResumeMode mode) {
1636 switch (mode) {
1637 case RESUME_MODE_INVALID:
1638 return "INVALID";
1639 case RESUME_MODE_IMMEDIATE_CONTINUE:
1640 return "IMMEDIATE_CONTINUE";
1641 case RESUME_MODE_IMMEDIATE_RESTART:
1642 return "IMMEDIATE_RESTART";
1643 case RESUME_MODE_USER_CONTINUE:
1644 return "USER_CONTINUE";
1645 case RESUME_MODE_USER_RESTART:
1646 return "USER_RESTART";
1647 default:
1648 NOTREACHED() << "Unknown resume mode " << mode;
1649 return "unknown";
1650 }
1651 }
1652
1427 } // namespace content 1653 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/download_item_impl.h ('k') | content/browser/download/download_item_impl_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698