Chromium Code Reviews| 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 |