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 | 5 // File method ordering: Methods in this file are in the same order |
6 // as in download_item_impl.h, with the following exception: The public | 6 // as in download_item_impl.h, with the following exception: The public |
7 // interfaces DelayedDownloadOpened, OnDownloadTargetDetermined, and | 7 // interfaces DelayedDownloadOpened, OnDownloadTargetDetermined, and |
8 // OnDownloadCompleting are placed in chronological order with the other | 8 // OnDownloadCompleting are placed in chronological order with the other |
9 // (private) routines that together define a DownloadItem's state transitions | 9 // (private) routines that together define a DownloadItem's state transitions |
10 // as the download progresses. See "Download progression cascade" later in | 10 // as the download progresses. See "Download progression cascade" later in |
(...skipping 28 matching lines...) Expand all Loading... | |
39 #include "content/browser/download/download_file.h" | 39 #include "content/browser/download/download_file.h" |
40 #include "content/browser/download/download_file_manager.h" | 40 #include "content/browser/download/download_file_manager.h" |
41 #include "content/browser/download/download_interrupt_reasons_impl.h" | 41 #include "content/browser/download/download_interrupt_reasons_impl.h" |
42 #include "content/browser/download/download_item_impl_delegate.h" | 42 #include "content/browser/download/download_item_impl_delegate.h" |
43 #include "content/browser/download/download_request_handle.h" | 43 #include "content/browser/download/download_request_handle.h" |
44 #include "content/browser/download/download_stats.h" | 44 #include "content/browser/download/download_stats.h" |
45 #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_thread.h" | 46 #include "content/public/browser/browser_thread.h" |
47 #include "content/public/browser/content_browser_client.h" | 47 #include "content/public/browser/content_browser_client.h" |
48 #include "content/public/browser/download_persistent_store_info.h" | 48 #include "content/public/browser/download_persistent_store_info.h" |
49 #include "content/public/browser/download_url_parameters.h" | |
49 #include "net/base/net_util.h" | 50 #include "net/base/net_util.h" |
50 | 51 |
51 using content::BrowserThread; | 52 using content::BrowserThread; |
52 using content::DownloadFile; | 53 using content::DownloadFile; |
53 using content::DownloadId; | 54 using content::DownloadId; |
54 using content::DownloadItem; | 55 using content::DownloadItem; |
55 using content::DownloadManager; | 56 using content::DownloadManager; |
56 using content::DownloadPersistentStoreInfo; | 57 using content::DownloadPersistentStoreInfo; |
57 using content::WebContents; | 58 using content::WebContents; |
58 | 59 |
59 namespace { | 60 namespace { |
60 | 61 |
61 static void DeleteDownloadedFile(const FilePath& path) { | 62 void DeleteDownloadedFile(const FilePath& path) { |
62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
63 | 64 |
64 // Make sure we only delete files. | 65 // Make sure we only delete files. |
65 if (!file_util::DirectoryExists(path)) | 66 if (!file_util::DirectoryExists(path)) |
66 file_util::Delete(path, false); | 67 file_util::Delete(path, false); |
67 } | 68 } |
68 | 69 |
69 const char* DebugSafetyStateString(DownloadItem::SafetyState state) { | 70 const char* DebugSafetyStateString(DownloadItem::SafetyState state) { |
70 switch (state) { | 71 switch (state) { |
71 case DownloadItem::SAFE: | 72 case DownloadItem::SAFE: |
(...skipping 20 matching lines...) Expand all Loading... | |
92 // DownloadRequestHandleInterface calls | 93 // DownloadRequestHandleInterface calls |
93 virtual WebContents* GetWebContents() const OVERRIDE { | 94 virtual WebContents* GetWebContents() const OVERRIDE { |
94 return NULL; | 95 return NULL; |
95 } | 96 } |
96 virtual DownloadManager* GetDownloadManager() const OVERRIDE { | 97 virtual DownloadManager* GetDownloadManager() const OVERRIDE { |
97 return NULL; | 98 return NULL; |
98 } | 99 } |
99 virtual void PauseRequest() const OVERRIDE {} | 100 virtual void PauseRequest() const OVERRIDE {} |
100 virtual void ResumeRequest() const OVERRIDE {} | 101 virtual void ResumeRequest() const OVERRIDE {} |
101 virtual void CancelRequest() const OVERRIDE {} | 102 virtual void CancelRequest() const OVERRIDE {} |
103 virtual void SetRequestId(int new_request_id) OVERRIDE {} | |
104 virtual int RequestId() const OVERRIDE { return -1; } | |
102 virtual std::string DebugString() const OVERRIDE { | 105 virtual std::string DebugString() const OVERRIDE { |
103 return "Null DownloadRequestHandle"; | 106 return "Null DownloadRequestHandle"; |
104 } | 107 } |
105 }; | 108 }; |
106 | 109 |
107 } // namespace | 110 } // namespace |
108 | 111 |
109 namespace content { | 112 namespace content { |
110 | 113 |
111 // Our download table ID starts at 1, so we use 0 to represent a download that | 114 // Our download table ID starts at 1, so we use 0 to represent a download that |
112 // has started, but has not yet had its data persisted in the table. We use fake | 115 // has started, but has not yet had its data persisted in the table. We use fake |
113 // database handles in incognito mode starting at -1 and progressively getting | 116 // database handles in incognito mode starting at -1 and progressively getting |
114 // more negative. | 117 // more negative. |
115 // static | 118 // static |
116 const int DownloadItem::kUninitializedHandle = 0; | 119 const int DownloadItem::kUninitializedHandle = 0; |
117 | 120 |
118 const char DownloadItem::kEmptyFileHash[] = ""; | 121 const char DownloadItem::kEmptyFileHash[] = ""; |
119 | 122 |
120 } | 123 } |
121 | 124 |
125 // The maximum number of attempts we will make to resume automatically. | |
126 const int DownloadItemImpl::kMaxAutoResumeAttempts = 5; | |
127 | |
122 // Our download table ID starts at 1, so we use 0 to represent a download that | 128 // Our download table ID starts at 1, so we use 0 to represent a download that |
123 // has started, but has not yet had its data persisted in the table. We use fake | 129 // has started, but has not yet had its data persisted in the table. We use fake |
124 // database handles in incognito mode starting at -1 and progressively getting | 130 // database handles in incognito mode starting at -1 and progressively getting |
125 // more negative. | 131 // more negative. |
126 | 132 |
127 // Constructor for reading from the history service. | 133 // Constructor for reading from the history service. |
128 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, | 134 DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate, |
129 DownloadId download_id, | 135 DownloadId download_id, |
130 const DownloadPersistentStoreInfo& info, | 136 const DownloadPersistentStoreInfo& info, |
131 const net::BoundNetLog& bound_net_log) | 137 const net::BoundNetLog& bound_net_log) |
(...skipping 10 matching lines...) Expand all Loading... | |
142 bytes_per_sec_(0), | 148 bytes_per_sec_(0), |
143 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE), | 149 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE), |
144 start_tick_(base::TimeTicks()), | 150 start_tick_(base::TimeTicks()), |
145 state_(ExternalToInternalState(info.state)), | 151 state_(ExternalToInternalState(info.state)), |
146 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), | 152 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), |
147 start_time_(info.start_time), | 153 start_time_(info.start_time), |
148 end_time_(info.end_time), | 154 end_time_(info.end_time), |
149 db_handle_(info.db_handle), | 155 db_handle_(info.db_handle), |
150 delegate_(delegate), | 156 delegate_(delegate), |
151 is_paused_(false), | 157 is_paused_(false), |
158 is_resuming_(false), | |
159 auto_resume_count_(0), | |
152 open_when_complete_(false), | 160 open_when_complete_(false), |
153 file_externally_removed_(false), | 161 file_externally_removed_(false), |
154 safety_state_(SAFE), | 162 safety_state_(SAFE), |
155 auto_opened_(false), | 163 auto_opened_(false), |
156 is_persisted_(true), | 164 is_persisted_(true), |
157 is_temporary_(false), | 165 is_temporary_(false), |
158 all_data_saved_(false), | 166 all_data_saved_(false), |
159 opened_(info.opened), | 167 opened_(info.opened), |
160 open_enabled_(true), | 168 open_enabled_(true), |
161 delegate_delayed_complete_(false), | 169 delegate_delayed_complete_(false), |
162 bound_net_log_(bound_net_log), | 170 bound_net_log_(bound_net_log), |
163 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | 171 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { |
164 delegate_->Attach(); | 172 delegate_->Attach(); |
165 if (state_ == IN_PROGRESS_INTERNAL) | 173 if (state_ == IN_PROGRESS_INTERNAL) |
166 state_ = CANCELLED_INTERNAL; | 174 state_ = CANCELLED_INTERNAL; |
167 if (state_ == COMPLETE_INTERNAL) | 175 if (state_ == COMPLETE_INTERNAL) |
168 all_data_saved_ = true; | 176 all_data_saved_ = true; |
169 Init(false /* not actively downloading */, | 177 Init(false /* not actively downloading */, |
170 download_net_logs::SRC_HISTORY_IMPORT); | 178 download_net_logs::SRC_HISTORY_IMPORT); |
171 } | 179 } |
172 | 180 |
173 // Constructing for a regular download: | 181 // Constructing for a regular download: |
174 DownloadItemImpl::DownloadItemImpl( | 182 DownloadItemImpl::DownloadItemImpl( |
175 DownloadItemImplDelegate* delegate, | 183 DownloadItemImplDelegate* delegate, |
176 const DownloadCreateInfo& info, | 184 const DownloadCreateInfo& info, |
177 scoped_ptr<DownloadRequestHandleInterface> request_handle, | |
178 const net::BoundNetLog& bound_net_log) | 185 const net::BoundNetLog& bound_net_log) |
179 : request_handle_(request_handle.Pass()), | 186 : download_id_(info.download_id), |
180 download_id_(info.download_id), | |
181 target_disposition_( | 187 target_disposition_( |
182 (info.prompt_user_for_save_location) ? | 188 (info.prompt_user_for_save_location) ? |
183 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE), | 189 TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE), |
184 url_chain_(info.url_chain), | 190 url_chain_(info.url_chain), |
185 referrer_url_(info.referrer_url), | 191 referrer_url_(info.referrer_url), |
186 suggested_filename_(UTF16ToUTF8(info.save_info.suggested_name)), | 192 suggested_filename_(UTF16ToUTF8(info.save_info.suggested_name)), |
187 forced_file_path_(info.save_info.file_path), | 193 forced_file_path_(info.save_info.file_path), |
188 transition_type_(info.transition_type), | 194 transition_type_(info.transition_type), |
189 has_user_gesture_(info.has_user_gesture), | 195 has_user_gesture_(info.has_user_gesture), |
190 content_disposition_(info.content_disposition), | 196 content_disposition_(info.content_disposition), |
191 mime_type_(info.mime_type), | 197 mime_type_(info.mime_type), |
192 original_mime_type_(info.original_mime_type), | 198 original_mime_type_(info.original_mime_type), |
193 referrer_charset_(info.referrer_charset), | 199 referrer_charset_(info.referrer_charset), |
194 remote_address_(info.remote_address), | 200 remote_address_(info.remote_address), |
195 total_bytes_(info.total_bytes), | 201 total_bytes_(info.total_bytes), |
196 received_bytes_(0), | 202 received_bytes_(0), |
197 bytes_per_sec_(0), | 203 bytes_per_sec_(0), |
198 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE), | 204 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE), |
199 start_tick_(base::TimeTicks::Now()), | 205 start_tick_(base::TimeTicks::Now()), |
200 state_(IN_PROGRESS_INTERNAL), | 206 state_(IN_PROGRESS_INTERNAL), |
201 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), | 207 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), |
202 start_time_(info.start_time), | 208 start_time_(info.start_time), |
203 db_handle_(DownloadItem::kUninitializedHandle), | 209 db_handle_(DownloadItem::kUninitializedHandle), |
204 delegate_(delegate), | 210 delegate_(delegate), |
205 is_paused_(false), | 211 is_paused_(false), |
212 is_resuming_(false), | |
213 auto_resume_count_(0), | |
206 open_when_complete_(false), | 214 open_when_complete_(false), |
207 file_externally_removed_(false), | 215 file_externally_removed_(false), |
208 safety_state_(SAFE), | 216 safety_state_(SAFE), |
209 auto_opened_(false), | 217 auto_opened_(false), |
210 is_persisted_(false), | 218 is_persisted_(false), |
211 is_temporary_(!info.save_info.file_path.empty()), | 219 is_temporary_(!info.save_info.file_path.empty()), |
212 all_data_saved_(false), | 220 all_data_saved_(false), |
213 opened_(false), | 221 opened_(false), |
214 open_enabled_(true), | 222 open_enabled_(true), |
215 delegate_delayed_complete_(false), | 223 delegate_delayed_complete_(false), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 received_bytes_(0), | 259 received_bytes_(0), |
252 bytes_per_sec_(0), | 260 bytes_per_sec_(0), |
253 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE), | 261 last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE), |
254 start_tick_(base::TimeTicks::Now()), | 262 start_tick_(base::TimeTicks::Now()), |
255 state_(IN_PROGRESS_INTERNAL), | 263 state_(IN_PROGRESS_INTERNAL), |
256 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), | 264 danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS), |
257 start_time_(base::Time::Now()), | 265 start_time_(base::Time::Now()), |
258 db_handle_(DownloadItem::kUninitializedHandle), | 266 db_handle_(DownloadItem::kUninitializedHandle), |
259 delegate_(delegate), | 267 delegate_(delegate), |
260 is_paused_(false), | 268 is_paused_(false), |
269 is_resuming_(false), | |
270 auto_resume_count_(0), | |
261 open_when_complete_(false), | 271 open_when_complete_(false), |
262 file_externally_removed_(false), | 272 file_externally_removed_(false), |
263 safety_state_(SAFE), | 273 safety_state_(SAFE), |
264 auto_opened_(false), | 274 auto_opened_(false), |
265 is_persisted_(false), | 275 is_persisted_(false), |
266 is_temporary_(false), | 276 is_temporary_(false), |
267 all_data_saved_(false), | 277 all_data_saved_(false), |
268 opened_(false), | 278 opened_(false), |
269 open_enabled_(true), | 279 open_enabled_(true), |
270 delegate_delayed_complete_(false), | 280 delegate_delayed_complete_(false), |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
314 | 324 |
315 safety_state_ = DANGEROUS_BUT_VALIDATED; | 325 safety_state_ = DANGEROUS_BUT_VALIDATED; |
316 | 326 |
317 bound_net_log_.AddEvent( | 327 bound_net_log_.AddEvent( |
318 net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED, | 328 net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED, |
319 base::Bind(&download_net_logs::ItemCheckedCallback, | 329 base::Bind(&download_net_logs::ItemCheckedCallback, |
320 GetDangerType(), GetSafetyState())); | 330 GetDangerType(), GetSafetyState())); |
321 | 331 |
322 UpdateObservers(); | 332 UpdateObservers(); |
323 | 333 |
324 delegate_->MaybeCompleteDownload(this); | 334 delegate_->MaybeCompleteDownload(download_id_.local()); |
325 } | 335 } |
326 | 336 |
327 void DownloadItemImpl::TogglePause() { | 337 void DownloadItemImpl::TogglePause() { |
328 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
329 | 339 |
330 DCHECK(state_ == IN_PROGRESS_INTERNAL || state_ == COMPLETING_INTERNAL); | 340 DCHECK(IsPartialDownload()); |
331 if (is_paused_) | 341 if (IsInProgress()) { |
332 request_handle_->ResumeRequest(); | 342 if (is_paused_) |
333 else | 343 request_handle_->ResumeRequest(); |
334 request_handle_->PauseRequest(); | 344 else |
335 is_paused_ = !is_paused_; | 345 request_handle_->PauseRequest(); |
346 is_paused_ = !is_paused_; | |
347 } else if (IsInterrupted()) { | |
348 auto_resume_count_ = 0; // User input resets the counter. | |
349 delegate_->RestartInterruptedDownload( | |
350 this, content::DownloadUrlParameters::OnStartedCallback()); | |
351 } | |
352 | |
336 UpdateObservers(); | 353 UpdateObservers(); |
337 } | 354 } |
338 | 355 |
339 void DownloadItemImpl::Cancel(bool user_cancel) { | 356 void DownloadItemImpl::Cancel(bool user_cancel) { |
340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
341 | 358 |
342 last_reason_ = user_cancel ? | |
343 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED : | |
344 content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN; | |
345 | |
346 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); | 359 VLOG(20) << __FUNCTION__ << "() download = " << DebugString(true); |
347 if (state_ != IN_PROGRESS_INTERNAL) { | 360 if (state_ != IN_PROGRESS_INTERNAL && state_ != INTERRUPTED_INTERNAL) { |
348 // Small downloads might be complete before this method has | 361 // Small downloads might be complete before this method has |
349 // a chance to run. | 362 // a chance to run. |
350 return; | 363 return; |
351 } | 364 } |
352 | 365 |
366 last_reason_ = user_cancel ? | |
367 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED : | |
368 content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN; | |
369 | |
353 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT); | 370 download_stats::RecordDownloadCount(download_stats::CANCELLED_COUNT); |
354 | 371 |
355 TransitionTo(CANCELLED_INTERNAL); | 372 TransitionTo(CANCELLED_INTERNAL); |
356 delegate_->DownloadStopped(this); | 373 delegate_->DownloadStopped(this); |
357 } | 374 } |
358 | 375 |
359 void DownloadItemImpl::Delete(DeleteReason reason) { | 376 void DownloadItemImpl::Delete(DeleteReason reason) { |
360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 377 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
361 | 378 |
362 switch (reason) { | 379 switch (reason) { |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
449 } | 466 } |
450 | 467 |
451 content::DownloadInterruptReason DownloadItemImpl::GetLastReason() const { | 468 content::DownloadInterruptReason DownloadItemImpl::GetLastReason() const { |
452 return last_reason_; | 469 return last_reason_; |
453 } | 470 } |
454 | 471 |
455 bool DownloadItemImpl::IsPaused() const { | 472 bool DownloadItemImpl::IsPaused() const { |
456 return is_paused_; | 473 return is_paused_; |
457 } | 474 } |
458 | 475 |
476 bool DownloadItemImpl::IsResuming() const { | |
477 return is_resuming_; | |
478 } | |
479 | |
480 void DownloadItemImpl::SetRequest( | |
481 scoped_ptr<DownloadRequestHandleInterface> request_handle) { | |
482 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
483 request_handle_ = request_handle.Pass(); | |
484 } | |
485 | |
486 DownloadItem::ResumeMode DownloadItemImpl::CanResumeInterrupted() const { | |
487 if (!IsInterrupted() || !is_persisted_) | |
488 return RESUME_MODE_INVALID; | |
489 | |
490 ResumeMode mode = RESUME_MODE_INVALID; | |
491 | |
492 switch(last_reason_) { | |
493 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR: | |
494 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT: | |
495 mode = RESUME_MODE_IMMEDIATE_CONTINUE; // Continue immediately. | |
496 break; | |
497 | |
498 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_PRECONDITION: | |
499 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE: | |
500 mode = RESUME_MODE_IMMEDIATE_RESTART; // Restart immediately. | |
501 break; | |
502 | |
503 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED: | |
504 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED: | |
505 case content::DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN: | |
506 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED: | |
507 case content::DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN: | |
508 case content::DOWNLOAD_INTERRUPT_REASON_CRASH: | |
509 mode = RESUME_MODE_USER_CONTINUE; // Continue via user input. | |
510 break; | |
511 | |
512 case content::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED: | |
513 case content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED: | |
514 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE: | |
515 case content::DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG: | |
516 case content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE: | |
517 mode = RESUME_MODE_USER_RESTART; // Restart via user input. | |
518 break; | |
519 | |
520 case content::DOWNLOAD_INTERRUPT_REASON_NONE: | |
521 case content::DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED: | |
522 case content::DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT: | |
523 case content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED: | |
524 break; | |
525 } | |
526 | |
527 // Check if we have exhausted the number of automatic retry attempts. | |
528 if (auto_resume_count_ >= kMaxAutoResumeAttempts) { | |
529 if (mode == RESUME_MODE_IMMEDIATE_CONTINUE) | |
530 mode = RESUME_MODE_USER_CONTINUE; | |
531 else if (mode == RESUME_MODE_IMMEDIATE_RESTART) | |
532 mode = RESUME_MODE_USER_RESTART; | |
533 } | |
534 | |
535 return mode; | |
536 } | |
537 | |
538 void DownloadItemImpl::AutoResumeIfValid() { | |
539 ResumeMode mode = CanResumeInterrupted(); | |
540 | |
541 if ((mode == RESUME_MODE_IMMEDIATE_RESTART) || | |
542 (mode == RESUME_MODE_IMMEDIATE_CONTINUE)) { | |
543 if (mode == RESUME_MODE_IMMEDIATE_RESTART) { | |
544 received_bytes_ = 0; // Restart instead of continuing. | |
545 hash_state_ = ""; | |
546 last_modified_time_ = ""; | |
547 etag_ = ""; | |
548 } | |
549 | |
550 auto_resume_count_++; | |
551 | |
552 delegate_->RestartInterruptedDownload( | |
553 this, content::DownloadUrlParameters::OnStartedCallback()); | |
554 } | |
555 } | |
556 | |
459 bool DownloadItemImpl::IsTemporary() const { | 557 bool DownloadItemImpl::IsTemporary() const { |
460 return is_temporary_; | 558 return is_temporary_; |
461 } | 559 } |
462 | 560 |
463 bool DownloadItemImpl::IsPersisted() const { | 561 bool DownloadItemImpl::IsPersisted() const { |
464 return is_persisted_; | 562 return is_persisted_; |
465 } | 563 } |
466 | 564 |
467 // TODO(ahendrickson) -- Move |INTERRUPTED| from |IsCancelled()| to | |
468 // |IsPartialDownload()|, when resuming interrupted downloads is implemented. | |
469 bool DownloadItemImpl::IsPartialDownload() const { | 565 bool DownloadItemImpl::IsPartialDownload() const { |
470 return InternalToExternalState(state_) == IN_PROGRESS; | 566 DownloadState state = InternalToExternalState(state_); |
567 return (state == IN_PROGRESS) || (state == INTERRUPTED); | |
benjhayden
2012/10/15 17:59:37
Have you audited all the callers of IsPartialDownl
| |
471 } | 568 } |
472 | 569 |
473 bool DownloadItemImpl::IsInProgress() const { | 570 bool DownloadItemImpl::IsInProgress() const { |
474 return InternalToExternalState(state_) == IN_PROGRESS; | 571 return InternalToExternalState(state_) == IN_PROGRESS; |
475 } | 572 } |
476 | 573 |
477 bool DownloadItemImpl::IsCancelled() const { | 574 bool DownloadItemImpl::IsCancelled() const { |
478 DownloadState external_state = InternalToExternalState(state_); | 575 return InternalToExternalState(state_) == CANCELLED; |
479 return external_state == CANCELLED || external_state == INTERRUPTED; | |
benjhayden
2012/10/15 17:59:37
Have you audited all the callers of IsCancelled()
| |
480 } | 576 } |
481 | 577 |
482 bool DownloadItemImpl::IsInterrupted() const { | 578 bool DownloadItemImpl::IsInterrupted() const { |
483 return InternalToExternalState(state_) == INTERRUPTED; | 579 return InternalToExternalState(state_) == INTERRUPTED; |
484 } | 580 } |
485 | 581 |
486 bool DownloadItemImpl::IsComplete() const { | 582 bool DownloadItemImpl::IsComplete() const { |
487 return InternalToExternalState(state_) == COMPLETE; | 583 return InternalToExternalState(state_) == COMPLETE; |
488 } | 584 } |
489 | 585 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
657 } | 753 } |
658 | 754 |
659 bool DownloadItemImpl::CanShowInFolder() { | 755 bool DownloadItemImpl::CanShowInFolder() { |
660 return state_ != CANCELLED_INTERNAL && !file_externally_removed_; | 756 return state_ != CANCELLED_INTERNAL && !file_externally_removed_; |
661 } | 757 } |
662 | 758 |
663 bool DownloadItemImpl::CanOpenDownload() { | 759 bool DownloadItemImpl::CanOpenDownload() { |
664 return !file_externally_removed_; | 760 return !file_externally_removed_; |
665 } | 761 } |
666 | 762 |
763 bool DownloadItemImpl::CanResumeDownload() const { | |
764 // Do not allow interrupted downloads to be resumed until the target name | |
765 // has been determined, and the user has validated any dangerous items. | |
766 // TODO(rdsmith) -- Add a state indicating that filename determination has | |
767 // occurred. | |
768 if (GetTargetFilePath().empty()) | |
769 return false; | |
770 | |
771 if (GetSafetyState() == DANGEROUS) | |
772 return false; | |
773 | |
774 return IsInProgress() || | |
775 (CanResumeInterrupted() != DownloadItem::RESUME_MODE_INVALID); | |
776 } | |
777 | |
667 bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() { | 778 bool DownloadItemImpl::ShouldOpenFileBasedOnExtension() { |
668 return delegate_->ShouldOpenFileBasedOnExtension(GetUserVerifiedFilePath()); | 779 return delegate_->ShouldOpenFileBasedOnExtension(GetUserVerifiedFilePath()); |
669 } | 780 } |
670 | 781 |
671 bool DownloadItemImpl::GetOpenWhenComplete() const { | 782 bool DownloadItemImpl::GetOpenWhenComplete() const { |
672 return open_when_complete_; | 783 return open_when_complete_; |
673 } | 784 } |
674 | 785 |
675 bool DownloadItemImpl::GetAutoOpened() { | 786 bool DownloadItemImpl::GetAutoOpened() { |
676 return auto_opened_; | 787 return auto_opened_; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
753 } | 864 } |
754 } | 865 } |
755 | 866 |
756 if (verbose) { | 867 if (verbose) { |
757 description += base::StringPrintf( | 868 description += base::StringPrintf( |
758 " db_handle = %" PRId64 | 869 " db_handle = %" PRId64 |
759 " total = %" PRId64 | 870 " total = %" PRId64 |
760 " received = %" PRId64 | 871 " received = %" PRId64 |
761 " reason = %s" | 872 " reason = %s" |
762 " paused = %c" | 873 " paused = %c" |
874 " resuming = %c" | |
875 " resume_mode = %s" | |
763 " safety = %s" | 876 " safety = %s" |
877 " all_data_saved = %c" | |
878 " persisted = %c" | |
764 " last_modified = '%s'" | 879 " last_modified = '%s'" |
765 " etag = '%s'" | 880 " etag = '%s'" |
766 " url_chain = \n\t\"%s\"\n\t" | 881 " url_chain = \n\t\"%s\"\n\t" |
767 " full_path = \"%" PRFilePath "\"" | 882 " full_path = \"%" PRFilePath "\"" |
768 " target_path = \"%" PRFilePath "\"", | 883 " target_path = \"%" PRFilePath "\"", |
769 GetDbHandle(), | 884 GetDbHandle(), |
770 GetTotalBytes(), | 885 GetTotalBytes(), |
771 GetReceivedBytes(), | 886 GetReceivedBytes(), |
772 InterruptReasonDebugString(last_reason_).c_str(), | 887 InterruptReasonDebugString(last_reason_).c_str(), |
773 IsPaused() ? 'T' : 'F', | 888 IsPaused() ? 'T' : 'F', |
889 IsResuming() ? 'T' : 'F', | |
890 DebugResumeModeString(CanResumeInterrupted()), | |
774 DebugSafetyStateString(GetSafetyState()), | 891 DebugSafetyStateString(GetSafetyState()), |
892 AllDataSaved() ? 'T' : 'F', | |
893 IsPersisted() ? 'T' : 'F', | |
775 GetLastModifiedTime().c_str(), | 894 GetLastModifiedTime().c_str(), |
776 GetETag().c_str(), | 895 GetETag().c_str(), |
777 url_list.c_str(), | 896 url_list.c_str(), |
778 GetFullPath().value().c_str(), | 897 GetFullPath().value().c_str(), |
779 GetTargetFilePath().value().c_str()); | 898 GetTargetFilePath().value().c_str()); |
780 } else { | 899 } else { |
781 description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); | 900 description += base::StringPrintf(" url = \"%s\"", url_list.c_str()); |
782 } | 901 } |
783 | 902 |
784 description += " }"; | 903 description += " }"; |
785 | 904 |
786 return description; | 905 return description; |
787 } | 906 } |
788 | 907 |
789 void DownloadItemImpl::MockDownloadOpenForTesting() { | 908 void DownloadItemImpl::MockDownloadOpenForTesting() { |
790 open_enabled_ = false; | 909 open_enabled_ = false; |
791 } | 910 } |
792 | 911 |
793 void DownloadItemImpl::NotifyRemoved() { | 912 void DownloadItemImpl::NotifyRemoved() { |
794 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this)); | 913 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadRemoved(this)); |
795 } | 914 } |
796 | 915 |
797 void DownloadItemImpl::OnDownloadedFileRemoved() { | 916 void DownloadItemImpl::OnDownloadedFileRemoved() { |
798 file_externally_removed_ = true; | 917 file_externally_removed_ = true; |
799 UpdateObservers(); | 918 UpdateObservers(); |
919 delegate_->MaybeCompleteDownload(download_id_.local()); | |
benjhayden
2012/10/15 17:59:37
Sorry, what's this doing? I looked in download_man
| |
800 } | 920 } |
801 | 921 |
802 void DownloadItemImpl::OffThreadCancel() { | 922 void DownloadItemImpl::OffThreadCancel() { |
803 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 923 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
804 request_handle_->CancelRequest(); | 924 request_handle_->CancelRequest(); |
805 | 925 |
806 BrowserThread::PostTask( | 926 BrowserThread::PostTask( |
807 BrowserThread::FILE, FROM_HERE, | 927 BrowserThread::FILE, FROM_HERE, |
808 base::Bind(&DownloadFileManager::CancelDownload, | 928 base::Bind(&DownloadFileManager::CancelDownload, |
809 delegate_->GetDownloadFileManager(), download_id_)); | 929 delegate_->GetDownloadFileManager(), download_id_)); |
810 } | 930 } |
811 | 931 |
932 void DownloadItemImpl::OffThreadInterrupt() { | |
933 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
934 request_handle_->CancelRequest(); | |
935 | |
936 BrowserThread::PostTask( | |
937 BrowserThread::FILE, | |
938 FROM_HERE, | |
939 base::Bind(&DownloadFileManager::InterruptDownload, | |
940 delegate_->GetDownloadFileManager(), | |
941 download_id_, | |
942 base::Closure())); | |
943 } | |
944 | |
812 // An error occurred somewhere. | 945 // An error occurred somewhere. |
813 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) { | 946 void DownloadItemImpl::Interrupt(content::DownloadInterruptReason reason) { |
814 // Somewhat counter-intuitively, it is possible for us to receive an | 947 // Somewhat counter-intuitively, it is possible for us to receive an |
815 // interrupt after we've already been interrupted. The generation of | 948 // interrupt after we've already been interrupted. The generation of |
816 // interrupts from the file thread Renames and the generation of | 949 // interrupts from the file thread Renames and the generation of |
817 // interrupts from disk writes go through two different mechanisms (driven | 950 // interrupts from disk writes go through two different mechanisms (driven |
818 // by rename requests from UI thread and by write requests from IO thread, | 951 // by rename requests from UI thread and by write requests from IO thread, |
819 // respectively), and since we choose not to keep state on the File thread, | 952 // respectively), and since we choose not to keep state on the File thread, |
820 // this is the place where the races collide. It's also possible for | 953 // this is the place where the races collide. It's also possible for |
821 // interrupts to race with cancels. | 954 // interrupts to race with cancels. |
822 | 955 |
823 // Whatever happens, the first one to hit the UI thread wins. | 956 // Whatever happens, the first one to hit the UI thread wins. |
824 if (state_ != IN_PROGRESS_INTERNAL) | 957 if (state_ != IN_PROGRESS_INTERNAL) |
825 return; | 958 return; |
826 | 959 |
827 last_reason_ = reason; | 960 last_reason_ = reason; |
961 is_resuming_ = false; | |
828 TransitionTo(INTERRUPTED_INTERNAL); | 962 TransitionTo(INTERRUPTED_INTERNAL); |
829 download_stats::RecordDownloadInterrupted( | 963 download_stats::RecordDownloadInterrupted( |
830 reason, received_bytes_, total_bytes_); | 964 reason, received_bytes_, total_bytes_); |
831 delegate_->DownloadStopped(this); | 965 delegate_->DownloadStopped(this); |
966 | |
967 AutoResumeIfValid(); | |
968 } | |
969 | |
970 void DownloadItemImpl::Resume( | |
971 scoped_ptr<DownloadRequestHandleInterface> req_handle) { | |
972 DVLOG(20) << __FUNCTION__ << "() " << DebugString(true); | |
973 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
974 | |
975 if (state_ != INTERRUPTED_INTERNAL) | |
976 return; | |
977 request_handle_ = req_handle.Pass(); | |
978 is_resuming_ = true; | |
979 TransitionTo(IN_PROGRESS_INTERNAL); | |
832 } | 980 } |
833 | 981 |
834 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) { | 982 void DownloadItemImpl::SetTotalBytes(int64 total_bytes) { |
835 total_bytes_ = total_bytes; | 983 total_bytes_ = total_bytes; |
836 } | 984 } |
837 | 985 |
838 // Updates from the download thread may have been posted while this download | 986 // Updates from the download thread may have been posted while this download |
839 // was being cancelled in the UI thread, so we'll accept them unless we're | 987 // was being cancelled in the UI thread, so we'll accept them unless we're |
840 // complete. | 988 // complete. |
841 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, | 989 void DownloadItemImpl::UpdateProgress(int64 bytes_so_far, |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1007 } else { | 1155 } else { |
1008 SetFullPath(full_path); | 1156 SetFullPath(full_path); |
1009 UpdateObservers(); | 1157 UpdateObservers(); |
1010 } | 1158 } |
1011 | 1159 |
1012 delegate_->DownloadRenamedToIntermediateName(this); | 1160 delegate_->DownloadRenamedToIntermediateName(this); |
1013 } | 1161 } |
1014 | 1162 |
1015 void DownloadItemImpl::MaybeCompleteDownload() { | 1163 void DownloadItemImpl::MaybeCompleteDownload() { |
1016 // TODO(rdsmith): Move logic for this function here. | 1164 // TODO(rdsmith): Move logic for this function here. |
1017 delegate_->MaybeCompleteDownload(this); | 1165 delegate_->MaybeCompleteDownload(download_id_.local()); |
1018 } | 1166 } |
1019 | 1167 |
1020 // Called by DownloadManagerImpl::MaybeCompleteDownload() when it has | 1168 // Called by DownloadManagerImpl::MaybeCompleteDownload() when it has |
1021 // determined that the download is ready for completion. | 1169 // determined that the download is ready for completion. |
1022 void DownloadItemImpl::OnDownloadCompleting() { | 1170 void DownloadItemImpl::OnDownloadCompleting() { |
1023 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1024 | 1172 |
1025 if (state_ != IN_PROGRESS_INTERNAL) | 1173 if (state_ != IN_PROGRESS_INTERNAL) |
1026 return; | 1174 return; |
1027 | 1175 |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1262 case CANCELLED: | 1410 case CANCELLED: |
1263 return CANCELLED_INTERNAL; | 1411 return CANCELLED_INTERNAL; |
1264 case INTERRUPTED: | 1412 case INTERRUPTED: |
1265 return INTERRUPTED_INTERNAL; | 1413 return INTERRUPTED_INTERNAL; |
1266 default: | 1414 default: |
1267 NOTREACHED(); | 1415 NOTREACHED(); |
1268 } | 1416 } |
1269 return MAX_DOWNLOAD_INTERNAL_STATE; | 1417 return MAX_DOWNLOAD_INTERNAL_STATE; |
1270 } | 1418 } |
1271 | 1419 |
1420 const net::BoundNetLog& DownloadItemImpl::GetBoundNetLog() const { | |
1421 return bound_net_log_; | |
1422 } | |
1423 | |
1272 const char* DownloadItemImpl::DebugDownloadStateString( | 1424 const char* DownloadItemImpl::DebugDownloadStateString( |
1273 DownloadInternalState state) { | 1425 DownloadInternalState state) { |
1274 switch (state) { | 1426 switch (state) { |
1275 case IN_PROGRESS_INTERNAL: | 1427 case IN_PROGRESS_INTERNAL: |
1276 return "IN_PROGRESS"; | 1428 return "IN_PROGRESS"; |
1277 case COMPLETING_INTERNAL: | 1429 case COMPLETING_INTERNAL: |
1278 return "COMPLETING"; | 1430 return "COMPLETING"; |
1279 case COMPLETE_INTERNAL: | 1431 case COMPLETE_INTERNAL: |
1280 return "COMPLETE"; | 1432 return "COMPLETE"; |
1281 case CANCELLED_INTERNAL: | 1433 case CANCELLED_INTERNAL: |
1282 return "CANCELLED"; | 1434 return "CANCELLED"; |
1283 case INTERRUPTED_INTERNAL: | 1435 case INTERRUPTED_INTERNAL: |
1284 return "INTERRUPTED"; | 1436 return "INTERRUPTED"; |
1285 default: | 1437 default: |
1286 NOTREACHED() << "Unknown download state " << state; | 1438 NOTREACHED() << "Unknown download state " << state; |
1287 return "unknown"; | 1439 return "unknown"; |
1288 }; | 1440 }; |
1289 } | 1441 } |
1442 | |
1443 const char* DownloadItemImpl::DebugResumeModeString( | |
1444 DownloadItem::ResumeMode mode) { | |
1445 switch (mode) { | |
1446 case DownloadItem::RESUME_MODE_INVALID: | |
1447 return "INVALID"; | |
1448 case DownloadItem::RESUME_MODE_IMMEDIATE_CONTINUE: | |
1449 return "IMMEDIATE_CONTINUE"; | |
1450 case DownloadItem::RESUME_MODE_IMMEDIATE_RESTART: | |
1451 return "IMMEDIATE_RESTART"; | |
1452 case DownloadItem::RESUME_MODE_USER_CONTINUE: | |
1453 return "USER_CONTINUE"; | |
1454 case DownloadItem::RESUME_MODE_USER_RESTART: | |
1455 return "USER_RESTART"; | |
1456 default: | |
1457 NOTREACHED() << "Unknown resume mode " << mode; | |
1458 return "unknown"; | |
1459 } | |
1460 } | |
OLD | NEW |