OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |