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

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

Issue 11571025: Initial CL for Downloads resumption. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Incorporated Pawel's comment. Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // File method ordering: Methods in this file are in the same order as 5 // File method ordering: Methods in this file are in the same order as
6 // in download_item_impl.h, with the following exception: The public 6 // in download_item_impl.h, with the following exception: The public
7 // interface Start is placed in chronological order with the other 7 // interface Start is placed in chronological order with the other
8 // (private) routines that together define a DownloadItem's state 8 // (private) routines that together define a DownloadItem's state
9 // transitions as the download progresses. See "Download progression 9 // transitions as the download progresses. See "Download progression
10 // cascade" later in this file. 10 // cascade" later in this file.
11 11
12 // A regular DownloadItem (created for a download in this session of the 12 // A regular DownloadItem (created for a download in this session of the
13 // browser) normally goes through the following states: 13 // browser) normally goes through the following states:
14 // * Created (when download starts) 14 // * Created (when download starts)
15 // * Destination filename determined 15 // * Destination filename determined
16 // * Entered into the history database. 16 // * Entered into the history database.
17 // * Made visible in the download shelf. 17 // * Made visible in the download shelf.
18 // * All the data is saved. Note that the actual data download occurs 18 // * All the data is saved. Note that the actual data download occurs
19 // in parallel with the above steps, but until those steps are 19 // in parallel with the above steps, but until those steps are
20 // complete, the state of the data save will be ignored. 20 // complete, the state of the data save will be ignored.
21 // * Download file is renamed to its final name, and possibly 21 // * Download file is renamed to its final name, and possibly
22 // auto-opened. 22 // auto-opened.
23 23
24 #include "content/browser/download/download_item_impl.h" 24 #include "content/browser/download/download_item_impl.h"
25 25
26 #include <vector> 26 #include <vector>
27 27
28 #include "base/basictypes.h" 28 #include "base/basictypes.h"
29 #include "base/bind.h" 29 #include "base/bind.h"
30 #include "base/command_line.h"
30 #include "base/file_util.h" 31 #include "base/file_util.h"
31 #include "base/format_macros.h" 32 #include "base/format_macros.h"
32 #include "base/logging.h" 33 #include "base/logging.h"
33 #include "base/metrics/histogram.h" 34 #include "base/metrics/histogram.h"
34 #include "base/stl_util.h" 35 #include "base/stl_util.h"
35 #include "base/stringprintf.h" 36 #include "base/stringprintf.h"
36 #include "base/utf_string_conversions.h" 37 #include "base/utf_string_conversions.h"
37 #include "content/browser/download/download_create_info.h" 38 #include "content/browser/download/download_create_info.h"
38 #include "content/browser/download/download_file.h" 39 #include "content/browser/download/download_file.h"
39 #include "content/browser/download/download_interrupt_reasons_impl.h" 40 #include "content/browser/download/download_interrupt_reasons_impl.h"
40 #include "content/browser/download/download_item_impl_delegate.h" 41 #include "content/browser/download/download_item_impl_delegate.h"
41 #include "content/browser/download/download_request_handle.h" 42 #include "content/browser/download/download_request_handle.h"
42 #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"
43 #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"
44 #include "content/public/browser/browser_thread.h" 47 #include "content/public/browser/browser_thread.h"
45 #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/content_switches.h"
52 #include "content/public/common/referrer.h"
46 #include "net/base/net_util.h" 53 #include "net/base/net_util.h"
47 54
48 namespace content { 55 namespace content {
56
49 namespace { 57 namespace {
50 58
51 static void DeleteDownloadedFile(const FilePath& path) { 59 void DeleteDownloadedFile(const FilePath& path) {
52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
53 61
54 // Make sure we only delete files. 62 // Make sure we only delete files.
55 if (!file_util::DirectoryExists(path)) 63 if (!file_util::DirectoryExists(path))
56 file_util::Delete(path, false); 64 file_util::Delete(path, false);
57 } 65 }
58 66
59 const char* DebugSafetyStateString(DownloadItem::SafetyState state) { 67 const char* DebugSafetyStateString(DownloadItem::SafetyState state) {
60 switch (state) { 68 switch (state) {
61 case DownloadItem::SAFE: 69 case DownloadItem::SAFE:
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 112
105 static void DownloadFileCancel(scoped_ptr<DownloadFile> download_file) { 113 static void DownloadFileCancel(scoped_ptr<DownloadFile> download_file) {
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
107 download_file->Cancel(); 115 download_file->Cancel();
108 } 116 }
109 117
110 } // namespace 118 } // namespace
111 119
112 const char DownloadItem::kEmptyFileHash[] = ""; 120 const char DownloadItem::kEmptyFileHash[] = "";
113 121
122 // The maximum number of attempts we will make to resume automatically.
123 const int DownloadItemImpl::kMaxAutoResumeAttempts = 5;
124
114 // Constructor for reading from the history service. 125 // Constructor for reading from the history service.
115 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, 126 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
116 DownloadId download_id, 127 DownloadId download_id,
117 const FilePath& path, 128 const FilePath& path,
118 const GURL& url, 129 const GURL& url,
119 const GURL& referrer_url, 130 const GURL& referrer_url,
120 const base::Time& start_time, 131 const base::Time& start_time,
121 const base::Time& end_time, 132 const base::Time& end_time,
122 int64 received_bytes, 133 int64 received_bytes,
123 int64 total_bytes, 134 int64 total_bytes,
(...skipping 13 matching lines...) Expand all
137 received_bytes_(received_bytes), 148 received_bytes_(received_bytes),
138 bytes_per_sec_(0), 149 bytes_per_sec_(0),
139 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), 150 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
140 start_tick_(base::TimeTicks()), 151 start_tick_(base::TimeTicks()),
141 state_(ExternalToInternalState(state)), 152 state_(ExternalToInternalState(state)),
142 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), 153 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
143 start_time_(start_time), 154 start_time_(start_time),
144 end_time_(end_time), 155 end_time_(end_time),
145 delegate_(delegate), 156 delegate_(delegate),
146 is_paused_(false), 157 is_paused_(false),
158 auto_resume_count_(0),
147 open_when_complete_(false), 159 open_when_complete_(false),
148 file_externally_removed_(false), 160 file_externally_removed_(false),
149 safety_state_(SAFE), 161 safety_state_(SAFE),
150 auto_opened_(false), 162 auto_opened_(false),
151 is_temporary_(false), 163 is_temporary_(false),
152 all_data_saved_(false), 164 all_data_saved_(false),
153 opened_(opened), 165 opened_(opened),
154 open_enabled_(true), 166 open_enabled_(true),
155 delegate_delayed_complete_(false), 167 delegate_delayed_complete_(false),
156 bound_net_log_(bound_net_log), 168 bound_net_log_(bound_net_log),
157 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { 169 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
158 delegate_->Attach(); 170 delegate_->Attach();
159 if (state_ == IN_PROGRESS_INTERNAL) 171 if (state_ == IN_PROGRESS_INTERNAL)
160 state_ = CANCELLED_INTERNAL; 172 state_ = CANCELLED_INTERNAL;
161 if (state_ == COMPLETE_INTERNAL) 173 if (state_ == COMPLETE_INTERNAL)
162 all_data_saved_ = true; 174 all_data_saved_ = true;
163 Init(false /* not actively downloading */, SRC_HISTORY_IMPORT); 175 Init(false /* not actively downloading */, SRC_HISTORY_IMPORT);
164 } 176 }
165 177
166 // Constructing for a regular download: 178 // Constructing for a regular download:
167 DownloadItemImpl::DownloadItemImpl( 179 DownloadItemImpl::DownloadItemImpl(
168 DownloadItemImplDelegate* delegate, 180 DownloadItemImplDelegate* delegate,
169 const DownloadCreateInfo& info, 181 const DownloadCreateInfo& info,
170 scoped_ptr<DownloadRequestHandleInterface> request_handle,
171 const net::BoundNetLog& bound_net_log) 182 const net::BoundNetLog& bound_net_log)
172 : is_save_package_download_(false), 183 : is_save_package_download_(false),
173 request_handle_(request_handle.Pass()),
174 download_id_(info.download_id), 184 download_id_(info.download_id),
175 target_disposition_( 185 target_disposition_(
176 (info.save_info->prompt_for_save_location) ? 186 (info.save_info->prompt_for_save_location) ?
177 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE), 187 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE),
178 url_chain_(info.url_chain), 188 url_chain_(info.url_chain),
179 referrer_url_(info.referrer_url), 189 referrer_url_(info.referrer_url),
180 suggested_filename_(UTF16ToUTF8(info.save_info->suggested_name)), 190 suggested_filename_(UTF16ToUTF8(info.save_info->suggested_name)),
181 forced_file_path_(info.save_info->file_path), 191 forced_file_path_(info.save_info->file_path),
182 transition_type_(info.transition_type), 192 transition_type_(info.transition_type),
183 has_user_gesture_(info.has_user_gesture), 193 has_user_gesture_(info.has_user_gesture),
184 content_disposition_(info.content_disposition), 194 content_disposition_(info.content_disposition),
185 mime_type_(info.mime_type), 195 mime_type_(info.mime_type),
186 original_mime_type_(info.original_mime_type), 196 original_mime_type_(info.original_mime_type),
187 remote_address_(info.remote_address), 197 remote_address_(info.remote_address),
188 total_bytes_(info.total_bytes), 198 total_bytes_(info.total_bytes),
189 received_bytes_(0), 199 received_bytes_(0),
190 bytes_per_sec_(0), 200 bytes_per_sec_(0),
191 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), 201 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
192 start_tick_(base::TimeTicks::Now()), 202 start_tick_(base::TimeTicks::Now()),
193 state_(IN_PROGRESS_INTERNAL), 203 state_(IN_PROGRESS_INTERNAL),
194 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), 204 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
195 start_time_(info.start_time), 205 start_time_(info.start_time),
196 delegate_(delegate), 206 delegate_(delegate),
197 is_paused_(false), 207 is_paused_(false),
208 auto_resume_count_(0),
198 open_when_complete_(false), 209 open_when_complete_(false),
199 file_externally_removed_(false), 210 file_externally_removed_(false),
200 safety_state_(SAFE), 211 safety_state_(SAFE),
201 auto_opened_(false), 212 auto_opened_(false),
202 is_temporary_(!info.save_info->file_path.empty()), 213 is_temporary_(!info.save_info->file_path.empty()),
203 all_data_saved_(false), 214 all_data_saved_(false),
204 opened_(false), 215 opened_(false),
205 open_enabled_(true), 216 open_enabled_(true),
206 delegate_delayed_complete_(false), 217 delegate_delayed_complete_(false),
207 bound_net_log_(bound_net_log), 218 bound_net_log_(bound_net_log),
208 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { 219 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
209 delegate_->Attach(); 220 delegate_->Attach();
210 Init(true /* actively downloading */, SRC_NEW_DOWNLOAD); 221 Init(true /* actively downloading */, SRC_ACTIVE_DOWNLOAD);
211 222
212 // Link the event sources. 223 // Link the event sources.
213 bound_net_log_.AddEvent( 224 bound_net_log_.AddEvent(
214 net::NetLog::TYPE_DOWNLOAD_URL_REQUEST, 225 net::NetLog::TYPE_DOWNLOAD_URL_REQUEST,
215 info.request_bound_net_log.source().ToEventParametersCallback()); 226 info.request_bound_net_log.source().ToEventParametersCallback());
216 227
217 info.request_bound_net_log.AddEvent( 228 info.request_bound_net_log.AddEvent(
218 net::NetLog::TYPE_DOWNLOAD_STARTED, 229 net::NetLog::TYPE_DOWNLOAD_STARTED,
219 bound_net_log_.source().ToEventParametersCallback()); 230 bound_net_log_.source().ToEventParametersCallback());
220 } 231 }
(...skipping 20 matching lines...) Expand all
241 total_bytes_(0), 252 total_bytes_(0),
242 received_bytes_(0), 253 received_bytes_(0),
243 bytes_per_sec_(0), 254 bytes_per_sec_(0),
244 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE), 255 last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
245 start_tick_(base::TimeTicks::Now()), 256 start_tick_(base::TimeTicks::Now()),
246 state_(IN_PROGRESS_INTERNAL), 257 state_(IN_PROGRESS_INTERNAL),
247 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), 258 danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
248 start_time_(base::Time::Now()), 259 start_time_(base::Time::Now()),
249 delegate_(delegate), 260 delegate_(delegate),
250 is_paused_(false), 261 is_paused_(false),
262 auto_resume_count_(0),
251 open_when_complete_(false), 263 open_when_complete_(false),
252 file_externally_removed_(false), 264 file_externally_removed_(false),
253 safety_state_(SAFE), 265 safety_state_(SAFE),
254 auto_opened_(false), 266 auto_opened_(false),
255 is_temporary_(false), 267 is_temporary_(false),
256 all_data_saved_(false), 268 all_data_saved_(false),
257 opened_(false), 269 opened_(false),
258 open_enabled_(true), 270 open_enabled_(true),
259 delegate_delayed_complete_(false), 271 delegate_delayed_complete_(false),
260 bound_net_log_(bound_net_log), 272 bound_net_log_(bound_net_log),
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 340
329 request_handle_->PauseRequest(); 341 request_handle_->PauseRequest();
330 is_paused_ = true; 342 is_paused_ = true;
331 UpdateObservers(); 343 UpdateObservers();
332 } 344 }
333 345
334 void DownloadItemImpl::Resume() { 346 void DownloadItemImpl::Resume() {
335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
336 348
337 // Ignore irrelevant states. 349 // Ignore irrelevant states.
338 if (state_ != IN_PROGRESS_INTERNAL || !is_paused_) 350 if (state_ == COMPLETE_INTERNAL || state_ == COMPLETING_INTERNAL ||
351 !is_paused_)
339 return; 352 return;
340 353
354 if (state_ == INTERRUPTED_INTERNAL) {
355 auto_resume_count_ = 0; // User input resets the counter.
356 ResumeInterruptedDownload();
357 return;
358 }
359 DCHECK_EQ(IN_PROGRESS_INTERNAL, state_);
360
341 request_handle_->ResumeRequest(); 361 request_handle_->ResumeRequest();
342 is_paused_ = false; 362 is_paused_ = false;
343 UpdateObservers(); 363 UpdateObservers();
344 } 364 }
345 365
346 void DownloadItemImpl::Cancel(bool user_cancel) { 366 void DownloadItemImpl::Cancel(bool user_cancel) {
347 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 367 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
348 368
369 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
370 if (state_ != IN_PROGRESS_INTERNAL && state_ != INTERRUPTED_INTERNAL) {
371 // Small downloads might be complete before this method has
372 // a chance to run.
373 return;
374 }
375
349 last_reason_ = user_cancel ? 376 last_reason_ = user_cancel ?
350 DOWNLOAD_INTERRUPT_REASON_USER_CANCELED : 377 DOWNLOAD_INTERRUPT_REASON_USER_CANCELED :
351 DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN; 378 DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
352 379
353 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
354 if (state_ != IN_PROGRESS_INTERNAL) {
355 // Small downloads might be complete before this method has
356 // a chance to run.
357 return;
358 }
359
360 RecordDownloadCount(CANCELLED_COUNT); 380 RecordDownloadCount(CANCELLED_COUNT);
361 381
362 TransitionTo(CANCELLED_INTERNAL); 382 TransitionTo(CANCELLED_INTERNAL);
363 383
364 CancelDownloadFile(); 384 CancelDownloadFile();
365 385
366 // Cancel the originating URL request. 386 // Cancel the originating URL request.
367 request_handle_->CancelRequest(); 387 request_handle_->CancelRequest();
368 } 388 }
369 389
370 void DownloadItemImpl::Delete(DeleteReason reason) { 390 void DownloadItemImpl::Delete(DeleteReason reason) {
391 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
372 393
373 switch (reason) { 394 switch (reason) {
374 case DELETE_DUE_TO_USER_DISCARD: 395 case DELETE_DUE_TO_USER_DISCARD:
375 UMA_HISTOGRAM_ENUMERATION( 396 UMA_HISTOGRAM_ENUMERATION(
376 "Download.UserDiscard", GetDangerType(), 397 "Download.UserDiscard", GetDangerType(),
377 DOWNLOAD_DANGER_TYPE_MAX); 398 DOWNLOAD_DANGER_TYPE_MAX);
378 break; 399 break;
379 case DELETE_DUE_TO_BROWSER_SHUTDOWN: 400 case DELETE_DUE_TO_BROWSER_SHUTDOWN:
380 UMA_HISTOGRAM_ENUMERATION( 401 UMA_HISTOGRAM_ENUMERATION(
381 "Download.Discard", GetDangerType(), 402 "Download.Discard", GetDangerType(),
382 DOWNLOAD_DANGER_TYPE_MAX); 403 DOWNLOAD_DANGER_TYPE_MAX);
383 break; 404 break;
384 default: 405 default:
385 NOTREACHED(); 406 NOTREACHED();
386 } 407 }
387 408
388 // Delete the file if it exists and is not owned by a DownloadFile object. 409 // Delete the file if it exists and is not owned by a DownloadFile object.
389 // (In the latter case the DownloadFile object will delete it on cancel.) 410 // (In the latter case the DownloadFile object will delete it on cancel.)
390 if (!current_path_.empty() && download_file_.get() == NULL) { 411 if (!current_path_.empty() && download_file_.get() == NULL) {
391 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 412 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
392 base::Bind(&DeleteDownloadedFile, current_path_)); 413 base::Bind(&DeleteDownloadedFile, current_path_));
393 } 414 }
394 Remove(); 415 Remove();
395 // We have now been deleted. 416 // We have now been deleted.
396 } 417 }
397 418
398 void DownloadItemImpl::Remove() { 419 void DownloadItemImpl::Remove() {
420 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
400 422
401 delegate_->AssertStateConsistent(this); 423 delegate_->AssertStateConsistent(this);
402 Cancel(true); 424 Cancel(true);
403 delegate_->AssertStateConsistent(this); 425 delegate_->AssertStateConsistent(this);
404 426
405 NotifyRemoved(); 427 NotifyRemoved();
406 delegate_->DownloadRemoved(this); 428 delegate_->DownloadRemoved(this);
407 // We have now been deleted. 429 // We have now been deleted.
408 } 430 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 } 484 }
463 485
464 bool DownloadItemImpl::IsPaused() const { 486 bool DownloadItemImpl::IsPaused() const {
465 return is_paused_; 487 return is_paused_;
466 } 488 }
467 489
468 bool DownloadItemImpl::IsTemporary() const { 490 bool DownloadItemImpl::IsTemporary() const {
469 return is_temporary_; 491 return is_temporary_;
470 } 492 }
471 493
472 // TODO(ahendrickson) -- Move |INTERRUPTED| from |IsCancelled()| to
473 // |IsPartialDownload()|, when resuming interrupted downloads is implemented.
474 bool DownloadItemImpl::IsPartialDownload() const { 494 bool DownloadItemImpl::IsPartialDownload() const {
475 return InternalToExternalState(state_) == IN_PROGRESS; 495 DownloadState state = InternalToExternalState(state_);
496 return (state == IN_PROGRESS) || (state == INTERRUPTED);
476 } 497 }
477 498
478 bool DownloadItemImpl::IsInProgress() const { 499 bool DownloadItemImpl::IsInProgress() const {
479 return InternalToExternalState(state_) == IN_PROGRESS; 500 return InternalToExternalState(state_) == IN_PROGRESS;
480 } 501 }
481 502
482 bool DownloadItemImpl::IsCancelled() const { 503 bool DownloadItemImpl::IsCancelled() const {
483 DownloadState external_state = InternalToExternalState(state_); 504 return InternalToExternalState(state_) == CANCELLED;
484 return external_state == CANCELLED || external_state == INTERRUPTED;
485 } 505 }
486 506
487 bool DownloadItemImpl::IsInterrupted() const { 507 bool DownloadItemImpl::IsInterrupted() const {
488 return InternalToExternalState(state_) == INTERRUPTED; 508 return InternalToExternalState(state_) == INTERRUPTED;
489 } 509 }
490 510
491 bool DownloadItemImpl::IsComplete() const { 511 bool DownloadItemImpl::IsComplete() const {
492 return InternalToExternalState(state_) == COMPLETE; 512 return InternalToExternalState(state_) == COMPLETE;
493 } 513 }
494 514
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 url_list += next_url.spec(); 770 url_list += next_url.spec();
751 } 771 }
752 } 772 }
753 773
754 if (verbose) { 774 if (verbose) {
755 description += base::StringPrintf( 775 description += base::StringPrintf(
756 " total = %" PRId64 776 " total = %" PRId64
757 " received = %" PRId64 777 " received = %" PRId64
758 " reason = %s" 778 " reason = %s"
759 " paused = %c" 779 " paused = %c"
780 " resume_mode = %s"
781 " auto_resume_count = %d"
760 " safety = %s" 782 " safety = %s"
783 " all_data_saved = %c"
761 " last_modified = '%s'" 784 " last_modified = '%s'"
762 " etag = '%s'" 785 " etag = '%s'"
786 " has_download_file = %s"
763 " url_chain = \n\t\"%s\"\n\t" 787 " url_chain = \n\t\"%s\"\n\t"
764 " full_path = \"%" PRFilePath "\"" 788 " full_path = \"%" PRFilePath "\"\n\t"
765 " target_path = \"%" PRFilePath "\"" 789 " target_path = \"%" PRFilePath "\"",
766 " has download file = %s",
767 GetTotalBytes(), 790 GetTotalBytes(),
768 GetReceivedBytes(), 791 GetReceivedBytes(),
769 InterruptReasonDebugString(last_reason_).c_str(), 792 InterruptReasonDebugString(last_reason_).c_str(),
770 IsPaused() ? 'T' : 'F', 793 IsPaused() ? 'T' : 'F',
794 DebugResumeModeString(GetResumeMode()),
795 auto_resume_count_,
771 DebugSafetyStateString(GetSafetyState()), 796 DebugSafetyStateString(GetSafetyState()),
797 AllDataSaved() ? 'T' : 'F',
772 GetLastModifiedTime().c_str(), 798 GetLastModifiedTime().c_str(),
773 GetETag().c_str(), 799 GetETag().c_str(),
800 download_file_.get() ? "true" : "false",
774 url_list.c_str(), 801 url_list.c_str(),
775 GetFullPath().value().c_str(), 802 GetFullPath().value().c_str(),
776 GetTargetFilePath().value().c_str(), 803 GetTargetFilePath().value().c_str());
777 download_file_.get() ? "true" : "false");
778 } else { 804 } else {
779 description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); 805 description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
780 } 806 }
781 807
782 description += " }"; 808 description += " }";
783 809
784 return description; 810 return description;
785 } 811 }
786 812
787 void DownloadItemImpl::MockDownloadOpenForTesting() { 813 void DownloadItemImpl::MockDownloadOpenForTesting() {
788 open_enabled_ = false; 814 open_enabled_ = false;
789 } 815 }
790 816
817 DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const {
818 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
819 if (!IsInterrupted())
820 return RESUME_MODE_INVALID;
821
822 // We can't continue without a handle on the intermediate file.
823 const bool force_restart = current_path_.empty();
824
825 // We won't auto-restart if we've used up our attempts or the
826 // download has been paused by user action.
827 const bool force_user =
828 (auto_resume_count_ >= kMaxAutoResumeAttempts || is_paused_);
829
830 ResumeMode mode = RESUME_MODE_INVALID;
831
832 switch(last_reason_) {
833 case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
834 case DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
835 if (force_restart && force_user)
836 mode = RESUME_MODE_USER_RESTART;
837 else if (force_restart)
838 mode = RESUME_MODE_IMMEDIATE_RESTART;
839 else if (force_user)
840 mode = RESUME_MODE_USER_CONTINUE;
841 else
842 mode = RESUME_MODE_IMMEDIATE_CONTINUE;
843 break;
844
845 case DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION:
846 case DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
847 case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:
848 if (force_user)
849 mode = RESUME_MODE_USER_RESTART;
850 else
851 mode = RESUME_MODE_IMMEDIATE_RESTART;
852 break;
853
854 case DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
855 case DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
856 case DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
857 case DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
858 case DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
859 case DOWNLOAD_INTERRUPT_REASON_CRASH:
860 if (force_restart)
861 mode = RESUME_MODE_USER_RESTART;
862 else
863 mode = RESUME_MODE_USER_CONTINUE;
864 break;
865
866 case DOWNLOAD_INTERRUPT_REASON_FILE_FAILED:
867 case DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
868 case DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
869 case DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
870 case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
871 mode = RESUME_MODE_USER_RESTART;
872 break;
873
874 case DOWNLOAD_INTERRUPT_REASON_NONE:
875 case DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
876 case DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT:
877 case DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
878 case DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED:
879 case DOWNLOAD_INTERRUPT_REASON_FILE_SECURITY_CHECK_FAILED:
880 mode = RESUME_MODE_INVALID;
881 break;
882 }
883
884 return mode;
885 }
886
887 void DownloadItemImpl::ResumeInterruptedDownload() {
888 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
889
890 // If the flag for downloads resumption isn't enabled, ignore
891 // this request.
892 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
893 if (!command_line.HasSwitch(switches::kEnableDownloadResumption))
894 return;
895
896 // Handle the case of clicking 'Resume' in the download shelf.
897 DCHECK(IsInterrupted());
898
899 DVLOG(20) << __FUNCTION__ << "()" << DebugString(true);
900
901 // If we can't get a web contents, we can't resume the download.
902 // TODO(rdsmith): Find some alternative web contents to use--this
903 // means we can't restart a download if it's a download imported
904 // from the history.
905 if (!GetWebContents())
906 return;
907
908 // Reset the appropriate state if restarting.
909 ResumeMode mode = GetResumeMode();
910 if (mode == RESUME_MODE_IMMEDIATE_RESTART ||
911 mode == RESUME_MODE_USER_RESTART) {
912 received_bytes_ = 0;
913 hash_state_ = "";
914 last_modified_time_ = "";
915 etag_ = "";
916 }
917
918 scoped_ptr<DownloadUrlParameters> download_params(
919 DownloadUrlParameters::FromWebContents(GetWebContents(),
920 GetOriginalUrl()));
921
922 download_params->set_file_path(GetFullPath());
923 download_params->set_offset(GetReceivedBytes());
924 download_params->set_hash_state(GetHashState());
925 download_params->set_last_modified(GetLastModifiedTime());
926 download_params->set_etag(GetETag());
927
928 delegate_->ResumeInterruptedDownload(download_params.Pass(), GetGlobalId());
929
930 // Just in case we were interrupted while paused.
931 is_paused_ = false;
932 }
933
791 void DownloadItemImpl::NotifyRemoved() { 934 void DownloadItemImpl::NotifyRemoved() {
792 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this)); 935 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this));
793 } 936 }
794 937
795 void DownloadItemImpl::OnDownloadedFileRemoved() { 938 void DownloadItemImpl::OnDownloadedFileRemoved() {
796 file_externally_removed_ = true; 939 file_externally_removed_ = true;
797 VLOG(20) << __FUNCTION__ << " download=" << DebugString(true); 940 VLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
798 UpdateObservers(); 941 UpdateObservers();
799 } 942 }
800 943
801 base::WeakPtr<DownloadDestinationObserver> 944 base::WeakPtr<DownloadDestinationObserver>
802 DownloadItemImpl::DestinationObserverAsWeakPtr() { 945 DownloadItemImpl::DestinationObserverAsWeakPtr() {
803 return weak_ptr_factory_.GetWeakPtr(); 946 return weak_ptr_factory_.GetWeakPtr();
804 } 947 }
805 948
949 const net::BoundNetLog& DownloadItemImpl::GetBoundNetLog() const {
950 return bound_net_log_;
951 }
952
806 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) { 953 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) {
807 total_bytes_ = total_bytes; 954 total_bytes_ = total_bytes;
808 } 955 }
809 956
810 // Updates from the download thread may have been posted while this download 957 // Updates from the download thread may have been posted while this download
811 // was being cancelled in the UI thread, so we'll accept them unless we're 958 // was being cancelled in the UI thread, so we'll accept them unless we're
812 // complete. 959 // complete.
813 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, 960 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far,
814 int64 bytes_per_sec, 961 int64 bytes_per_sec,
815 const std::string& hash_state) { 962 const std::string& hash_state) {
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
952 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data); 1099 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data);
953 } else { 1100 } else {
954 bound_net_log_.AddEvent( 1101 bound_net_log_.AddEvent(
955 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data); 1102 net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, active_data);
956 } 1103 }
957 1104
958 VLOG(20) << __FUNCTION__ << "() " << DebugString(true); 1105 VLOG(20) << __FUNCTION__ << "() " << DebugString(true);
959 } 1106 }
960 1107
961 // We're starting the download. 1108 // We're starting the download.
962 void DownloadItemImpl::Start(scoped_ptr<DownloadFile> file) { 1109 void DownloadItemImpl::Start(
1110 scoped_ptr<DownloadFile> file,
1111 scoped_ptr<DownloadRequestHandleInterface> req_handle) {
1112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
963 DCHECK(!download_file_.get()); 1113 DCHECK(!download_file_.get());
964 DCHECK(file.get()); 1114 DCHECK(file.get());
1115 DCHECK(req_handle.get());
1116
965 download_file_ = file.Pass(); 1117 download_file_ = file.Pass();
1118 request_handle_ = req_handle.Pass();
1119
1120 TransitionTo(IN_PROGRESS_INTERNAL);
1121
1122 last_reason_ = DOWNLOAD_INTERRUPT_REASON_NONE;
966 1123
967 BrowserThread::PostTask( 1124 BrowserThread::PostTask(
968 BrowserThread::FILE, FROM_HERE, 1125 BrowserThread::FILE, FROM_HERE,
969 base::Bind(&DownloadFile::Initialize, 1126 base::Bind(&DownloadFile::Initialize,
970 // Safe because we control download file lifetime. 1127 // Safe because we control download file lifetime.
971 base::Unretained(download_file_.get()), 1128 base::Unretained(download_file_.get()),
972 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized, 1129 base::Bind(&DownloadItemImpl::OnDownloadFileInitialized,
973 weak_ptr_factory_.GetWeakPtr()))); 1130 weak_ptr_factory_.GetWeakPtr())));
974 } 1131 }
975 1132
976 void DownloadItemImpl::OnDownloadFileInitialized( 1133 void DownloadItemImpl::OnDownloadFileInitialized(
977 DownloadInterruptReason result) { 1134 DownloadInterruptReason result) {
1135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
978 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) { 1136 if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
979 Interrupt(result); 1137 Interrupt(result);
980 // TODO(rdsmith): It makes no sense to continue along the 1138 // TODO(rdsmith): It makes no sense to continue along the
981 // regular download path after we've gotten an error. But it's 1139 // regular download path after we've gotten an error. But it's
982 // the way the code has historically worked, and this allows us 1140 // the way the code has historically worked, and this allows us
983 // to get the download persisted and observers of the download manager 1141 // to get the download persisted and observers of the download manager
984 // notified, so tests work. When we execute all side effects of cancel 1142 // notified, so tests work. When we execute all side effects of cancel
985 // (including queue removal) immedately rather than waiting for 1143 // (including queue removal) immediately rather than waiting for
986 // persistence we should replace this comment with a "return;". 1144 // persistence we should replace this comment with a "return;".
987 } 1145 }
988 1146
1147 // If we're resuming an interrupted download, we may already know
1148 // the download target so we can skip target name determination.
1149 if (!GetTargetFilePath().empty() && !GetFullPath().empty()) {
1150 delegate_->ShowDownloadInBrowser(this);
1151 MaybeCompleteDownload();
1152 return;
1153 }
1154
1155 // The target path might be set and the full path empty if we failed
1156 // the intermediate rename--re-do file name determination in this case.
1157 // TODO(rdsmith,asanka): Clean up this logic.
1158 target_path_ = FilePath();
1159
989 delegate_->DetermineDownloadTarget( 1160 delegate_->DetermineDownloadTarget(
990 this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined, 1161 this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined,
991 weak_ptr_factory_.GetWeakPtr())); 1162 weak_ptr_factory_.GetWeakPtr()));
992 } 1163 }
993 1164
994 // Called by delegate_ when the download target path has been 1165 // Called by delegate_ when the download target path has been
995 // determined. 1166 // determined.
996 void DownloadItemImpl::OnDownloadTargetDetermined( 1167 void DownloadItemImpl::OnDownloadTargetDetermined(
997 const FilePath& target_path, 1168 const FilePath& target_path,
998 TargetDisposition disposition, 1169 TargetDisposition disposition,
999 DownloadDangerType danger_type, 1170 DownloadDangerType danger_type,
1000 const FilePath& intermediate_path) { 1171 const FilePath& intermediate_path) {
1001 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1002 1173
1003 // If the |target_path| is empty, then we consider this download to be 1174 // If the |target_path| is empty, then we consider this download to be
1004 // canceled. 1175 // canceled.
1005 if (target_path.empty()) { 1176 if (target_path.empty()) {
1006 Cancel(true); 1177 Cancel(true);
1007 return; 1178 return;
1008 } 1179 }
1009 1180
1181 // TODO(rdsmith,asanka): We are ignoring the possibility that the download
1182 // has been interrupted at this point until we finish the intermediate
1183 // rename and set the full path. That's dangerous, because we might race
1184 // with resumption, either manual (because the interrupt is visible to the
1185 // UI) or automatic. If we keep the "ignore an error on download until file
1186 // name determination complete" semantics, we need to make sure that the
1187 // error is kept completely invisible until that point.
1188
1010 VLOG(20) << __FUNCTION__ << " " << target_path.value() << " " << disposition 1189 VLOG(20) << __FUNCTION__ << " " << target_path.value() << " " << disposition
1011 << " " << danger_type << " " << DebugString(true); 1190 << " " << danger_type << " " << DebugString(true);
1012 1191
1013 target_path_ = target_path; 1192 target_path_ = target_path;
1014 target_disposition_ = disposition; 1193 target_disposition_ = disposition;
1015 SetDangerType(danger_type); 1194 SetDangerType(danger_type);
1016 // TODO(asanka): SetDangerType() doesn't need to send a notification here. 1195 // TODO(asanka): SetDangerType() doesn't need to send a notification here.
1017 1196
1018 // We want the intermediate and target paths to refer to the same directory so 1197 // We want the intermediate and target paths to refer to the same directory so
1019 // that they are both on the same device and subject to same 1198 // that they are both on the same device and subject to same
1020 // space/permission/availability constraints. 1199 // space/permission/availability constraints.
1021 DCHECK(intermediate_path.DirName() == target_path.DirName()); 1200 DCHECK(intermediate_path.DirName() == target_path.DirName());
1022 1201
1023 if (state_ != IN_PROGRESS_INTERNAL) {
1024 // If we've been cancelled or interrupted while the target was being
1025 // determined, continue the cascade with a null name.
1026 // The error doesn't matter as the cause of download stoppage
1027 // will already have been recorded and will be retained, but we use
1028 // whatever was recorded for consistency.
1029 OnDownloadRenamedToIntermediateName(last_reason_, FilePath());
1030 return;
1031 }
1032
1033 // Rename to intermediate name. 1202 // Rename to intermediate name.
1034 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a 1203 // TODO(asanka): Skip this rename if AllDataSaved() is true. This avoids a
1035 // spurious rename when we can just rename to the final 1204 // spurious rename when we can just rename to the final
1036 // filename. Unnecessary renames may cause bugs like 1205 // filename. Unnecessary renames may cause bugs like
1037 // http://crbug.com/74187. 1206 // http://crbug.com/74187.
1038 DCHECK(!is_save_package_download_); 1207 DCHECK(!is_save_package_download_);
1039 DCHECK(download_file_.get()); 1208 DCHECK(download_file_.get());
1040 DownloadFile::RenameCompletionCallback callback = 1209 DownloadFile::RenameCompletionCallback callback =
1041 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName, 1210 base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName,
1042 weak_ptr_factory_.GetWeakPtr()); 1211 weak_ptr_factory_.GetWeakPtr());
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
1174 if (delegate_->ShouldOpenDownload( 1343 if (delegate_->ShouldOpenDownload(
1175 this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened, 1344 this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened,
1176 weak_ptr_factory_.GetWeakPtr()))) { 1345 weak_ptr_factory_.GetWeakPtr()))) {
1177 Completed(); 1346 Completed();
1178 } else { 1347 } else {
1179 delegate_delayed_complete_ = true; 1348 delegate_delayed_complete_ = true;
1180 } 1349 }
1181 } 1350 }
1182 1351
1183 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) { 1352 void DownloadItemImpl::DelayedDownloadOpened(bool auto_opened) {
1353 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1354
1184 auto_opened_ = auto_opened; 1355 auto_opened_ = auto_opened;
1185 Completed(); 1356 Completed();
1186 } 1357 }
1187 1358
1188 void DownloadItemImpl::Completed() { 1359 void DownloadItemImpl::Completed() {
1189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1190 1361
1191 VLOG(20) << __FUNCTION__ << "() " << DebugString(false); 1362 VLOG(20) << __FUNCTION__ << "() " << DebugString(false);
1192 1363
1193 DCHECK(all_data_saved_); 1364 DCHECK(all_data_saved_);
(...skipping 14 matching lines...) Expand all
1208 1379
1209 auto_opened_ = true; 1380 auto_opened_ = true;
1210 UpdateObservers(); 1381 UpdateObservers();
1211 } 1382 }
1212 } 1383 }
1213 1384
1214 // **** End of Download progression cascade 1385 // **** End of Download progression cascade
1215 1386
1216 // An error occurred somewhere. 1387 // An error occurred somewhere.
1217 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) { 1388 void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) {
1389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1390
1218 // Somewhat counter-intuitively, it is possible for us to receive an 1391 // Somewhat counter-intuitively, it is possible for us to receive an
1219 // interrupt after we've already been interrupted. The generation of 1392 // interrupt after we've already been interrupted. The generation of
1220 // interrupts from the file thread Renames and the generation of 1393 // interrupts from the file thread Renames and the generation of
1221 // interrupts from disk writes go through two different mechanisms (driven 1394 // interrupts from disk writes go through two different mechanisms (driven
1222 // by rename requests from UI thread and by write requests from IO thread, 1395 // 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, 1396 // 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 1397 // this is the place where the races collide. It's also possible for
1225 // interrupts to race with cancels. 1398 // interrupts to race with cancels.
1226 1399
1227 // Whatever happens, the first one to hit the UI thread wins. 1400 // Whatever happens, the first one to hit the UI thread wins.
1228 if (state_ != IN_PROGRESS_INTERNAL) 1401 if (state_ != IN_PROGRESS_INTERNAL)
1229 return; 1402 return;
1230 1403
1231 last_reason_ = reason; 1404 last_reason_ = reason;
1405
1232 TransitionTo(INTERRUPTED_INTERNAL); 1406 TransitionTo(INTERRUPTED_INTERNAL);
1233 1407
1234 CancelDownloadFile(); 1408 ResumeMode resume_mode = GetResumeMode();
1409 if (resume_mode == RESUME_MODE_IMMEDIATE_RESTART ||
1410 resume_mode == RESUME_MODE_USER_RESTART) {
1411 // Remove the download file; no point in leaving data around we
1412 // aren't going to use.
1413 CancelDownloadFile();
1414 } else {
1415 // Keep the file around and maybe re-use it.
1416 BrowserThread::PostTask(
1417 BrowserThread::FILE, FROM_HERE,
1418 base::Bind(&DownloadFileDetach, base::Passed(&download_file_)));
1419 }
1235 1420
1236 // Cancel the originating URL request. 1421 // Cancel the originating URL request.
1237 request_handle_->CancelRequest(); 1422 request_handle_->CancelRequest();
1238 1423
1239 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_); 1424 RecordDownloadInterrupted(reason, received_bytes_, total_bytes_);
1425 AutoResumeIfValid();
1240 } 1426 }
1241 1427
1242 void DownloadItemImpl::CancelDownloadFile() { 1428 void DownloadItemImpl::CancelDownloadFile() {
1429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1430
1243 // TODO(rdsmith/benjhayden): Remove condition as part of 1431 // TODO(rdsmith/benjhayden): Remove condition as part of
1244 // SavePackage integration. 1432 // |SavePackage| integration.
1245 // download_file_ can be NULL if Interrupt() is called after the download file 1433 // |download_file_| can be NULL if Interrupt() is called after the
1246 // has been released. 1434 // download file has been released.
1247 if (!is_save_package_download_ && download_file_.get()) { 1435 if (!is_save_package_download_ && download_file_.get()) {
1248 BrowserThread::PostTask( 1436 BrowserThread::PostTask(
1249 BrowserThread::FILE, FROM_HERE, 1437 BrowserThread::FILE, FROM_HERE,
1250 // Will be deleted at end of task execution. 1438 // Will be deleted at end of task execution.
1251 base::Bind(&DownloadFileCancel, base::Passed(&download_file_))); 1439 base::Bind(&DownloadFileCancel, base::Passed(&download_file_)));
1252 } 1440 }
1253 } 1441 }
1254 1442
1255 bool DownloadItemImpl::IsDownloadReadyForCompletion( 1443 bool DownloadItemImpl::IsDownloadReadyForCompletion(
1256 const base::Closure& state_change_notification) { 1444 const base::Closure& state_change_notification) {
(...skipping 24 matching lines...) Expand all
1281 1469
1282 // Give the delegate a chance to hold up a stop sign. It'll call 1470 // Give the delegate a chance to hold up a stop sign. It'll call
1283 // use back through the passed callback if it does and that state changes. 1471 // use back through the passed callback if it does and that state changes.
1284 if (!delegate_->ShouldCompleteDownload(this, state_change_notification)) 1472 if (!delegate_->ShouldCompleteDownload(this, state_change_notification))
1285 return false; 1473 return false;
1286 1474
1287 return true; 1475 return true;
1288 } 1476 }
1289 1477
1290 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) { 1478 void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {
1479 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1480
1291 if (state_ == new_state) 1481 if (state_ == new_state)
1292 return; 1482 return;
1293 1483
1294 DownloadInternalState old_state = state_; 1484 DownloadInternalState old_state = state_;
1295 state_ = new_state; 1485 state_ = new_state;
1296 1486
1297 switch (state_) { 1487 switch (state_) {
1298 case COMPLETING_INTERNAL: 1488 case COMPLETING_INTERNAL:
1299 bound_net_log_.AddEvent( 1489 bound_net_log_.AddEvent(
1300 net::NetLog::TYPE_DOWNLOAD_ITEM_COMPLETING, 1490 net::NetLog::TYPE_DOWNLOAD_ITEM_COMPLETING,
1301 base::Bind(&ItemCompletingNetLogCallback, received_bytes_, &hash_)); 1491 base::Bind(&ItemCompletingNetLogCallback, received_bytes_, &hash_));
1302 break; 1492 break;
1303 case COMPLETE_INTERNAL: 1493 case COMPLETE_INTERNAL:
1304 bound_net_log_.AddEvent( 1494 bound_net_log_.AddEvent(
1305 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED, 1495 net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED,
1306 base::Bind(&ItemFinishedNetLogCallback, auto_opened_)); 1496 base::Bind(&ItemFinishedNetLogCallback, auto_opened_));
1307 break; 1497 break;
1308 case INTERRUPTED_INTERNAL: 1498 case INTERRUPTED_INTERNAL:
1309 bound_net_log_.AddEvent( 1499 bound_net_log_.AddEvent(
1310 net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED, 1500 net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED,
1311 base::Bind(&ItemInterruptedNetLogCallback, last_reason_, 1501 base::Bind(&ItemInterruptedNetLogCallback, last_reason_,
1312 received_bytes_, &hash_state_)); 1502 received_bytes_, &hash_state_));
1313 break; 1503 break;
1504 case IN_PROGRESS_INTERNAL:
1505 if (old_state == INTERRUPTED_INTERNAL) {
1506 bound_net_log_.AddEvent(
1507 net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED,
1508 base::Bind(&ItemResumingNetLogCallback,
1509 false, last_reason_, received_bytes_, &hash_state_));
1510 }
1511 break;
1314 case CANCELLED_INTERNAL: 1512 case CANCELLED_INTERNAL:
1315 bound_net_log_.AddEvent( 1513 bound_net_log_.AddEvent(
1316 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED, 1514 net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED,
1317 base::Bind(&ItemCanceledNetLogCallback, received_bytes_, 1515 base::Bind(&ItemCanceledNetLogCallback, received_bytes_,
1318 &hash_state_)); 1516 &hash_state_));
1319 break; 1517 break;
1320 default: 1518 default:
1321 break; 1519 break;
1322 } 1520 }
1323 1521
1324 VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true) 1522 VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true)
1325 << " " << InternalToExternalState(old_state) 1523 << " " << InternalToExternalState(old_state)
1326 << " " << InternalToExternalState(state_); 1524 << " " << InternalToExternalState(state_);
1327 1525
1328 // Only update observers on user visible state changes. 1526 // Only update observers on user visible state changes.
1329 if (InternalToExternalState(old_state) != InternalToExternalState(state_)) 1527 if (InternalToExternalState(state_) != InternalToExternalState(old_state))
1330 UpdateObservers(); 1528 UpdateObservers();
1331 1529
1332 bool is_done = (state_ != IN_PROGRESS_INTERNAL && 1530 bool is_done = (state_ != IN_PROGRESS_INTERNAL &&
1333 state_ != COMPLETING_INTERNAL); 1531 state_ != COMPLETING_INTERNAL);
1334 bool was_done = (old_state != IN_PROGRESS_INTERNAL && 1532 bool was_done = (old_state != IN_PROGRESS_INTERNAL &&
1335 old_state != COMPLETING_INTERNAL); 1533 old_state != COMPLETING_INTERNAL);
1534 // Termination
1336 if (is_done && !was_done) 1535 if (is_done && !was_done)
1337 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE); 1536 bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE);
1537
1538 // Resumption
1539 if (was_done && !is_done) {
1540 std::string file_name(target_path_.BaseName().AsUTF8Unsafe());
1541 bound_net_log_.BeginEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE,
1542 base::Bind(&ItemActivatedNetLogCallback,
1543 this, SRC_ACTIVE_DOWNLOAD,
1544 &file_name));
1545 }
1338 } 1546 }
1339 1547
1340 void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) { 1548 void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) {
1341 danger_type_ = danger_type; 1549 danger_type_ = danger_type;
1342 // Notify observers if the safety state has changed as a result of the new 1550 // Notify observers if the safety state has changed as a result of the new
1343 // danger type. 1551 // danger type.
1344 SafetyState updated_value = IsDangerous() ? 1552 SafetyState updated_value = IsDangerous() ?
1345 DownloadItem::DANGEROUS : DownloadItem::SAFE; 1553 DownloadItem::DANGEROUS : DownloadItem::SAFE;
1346 if (updated_value != safety_state_) { 1554 if (updated_value != safety_state_) {
1347 safety_state_ = updated_value; 1555 safety_state_ = updated_value;
(...skipping 12 matching lines...) Expand all
1360 DCHECK(!new_path.empty()); 1568 DCHECK(!new_path.empty());
1361 1569
1362 bound_net_log_.AddEvent( 1570 bound_net_log_.AddEvent(
1363 net::NetLog::TYPE_DOWNLOAD_ITEM_RENAMED, 1571 net::NetLog::TYPE_DOWNLOAD_ITEM_RENAMED,
1364 base::Bind(&ItemRenamedNetLogCallback, &current_path_, &new_path)); 1572 base::Bind(&ItemRenamedNetLogCallback, &current_path_, &new_path));
1365 1573
1366 current_path_ = new_path; 1574 current_path_ = new_path;
1367 UpdateObservers(); 1575 UpdateObservers();
1368 } 1576 }
1369 1577
1578 void DownloadItemImpl::AutoResumeIfValid() {
1579 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true);
1580 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1581 ResumeMode mode = GetResumeMode();
1582
1583 if (mode != RESUME_MODE_IMMEDIATE_RESTART &&
1584 mode != RESUME_MODE_IMMEDIATE_CONTINUE) {
1585 return;
1586 }
1587
1588 auto_resume_count_++;
1589
1590 ResumeInterruptedDownload();
1591 }
1592
1370 // static 1593 // static
1371 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState( 1594 DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState(
1372 DownloadInternalState internal_state) { 1595 DownloadInternalState internal_state) {
1373 switch (internal_state) { 1596 switch (internal_state) {
1374 case IN_PROGRESS_INTERNAL: 1597 case IN_PROGRESS_INTERNAL:
1375 return IN_PROGRESS; 1598 return IN_PROGRESS;
1376 case COMPLETING_INTERNAL: 1599 case COMPLETING_INTERNAL:
1377 return IN_PROGRESS; 1600 return IN_PROGRESS;
1378 case COMPLETE_INTERNAL: 1601 case COMPLETE_INTERNAL:
1379 return COMPLETE; 1602 return COMPLETE;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1418 case CANCELLED_INTERNAL: 1641 case CANCELLED_INTERNAL:
1419 return "CANCELLED"; 1642 return "CANCELLED";
1420 case INTERRUPTED_INTERNAL: 1643 case INTERRUPTED_INTERNAL:
1421 return "INTERRUPTED"; 1644 return "INTERRUPTED";
1422 default: 1645 default:
1423 NOTREACHED() << "Unknown download state " << state; 1646 NOTREACHED() << "Unknown download state " << state;
1424 return "unknown"; 1647 return "unknown";
1425 }; 1648 };
1426 } 1649 }
1427 1650
1651 const char* DownloadItemImpl::DebugResumeModeString(ResumeMode mode) {
1652 switch (mode) {
1653 case RESUME_MODE_INVALID:
1654 return "INVALID";
1655 case RESUME_MODE_IMMEDIATE_CONTINUE:
1656 return "IMMEDIATE_CONTINUE";
1657 case RESUME_MODE_IMMEDIATE_RESTART:
1658 return "IMMEDIATE_RESTART";
1659 case RESUME_MODE_USER_CONTINUE:
1660 return "USER_CONTINUE";
1661 case RESUME_MODE_USER_RESTART:
1662 return "USER_RESTART";
1663 }
1664 NOTREACHED() << "Unknown resume mode " << mode;
1665 return "unknown";
1666 }
1667
1428 } // namespace content 1668 } // 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