| 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 |