// Copyright 2021 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "weblayer/browser/persistent_download.h" #include "base/bind.h" #include "base/files/file_path.h" #include "base/memory/ptr_util.h" #include "base/threading/sequenced_task_runner_handle.h" #include "components/download/public/common/download_item.h" namespace weblayer { namespace { const char kPersistentDownloadKeyName[] = "weblayer_download_impl"; } PersistentDownload::~PersistentDownload() = default; void PersistentDownload::Create(download::DownloadItem* item) { item->SetUserData(kPersistentDownloadKeyName, base::WrapUnique(new PersistentDownload(item))); } PersistentDownload* PersistentDownload::Get(download::DownloadItem* item) { return static_cast( item->GetUserData(kPersistentDownloadKeyName)); } DownloadState PersistentDownload::GetState() { if (item_->GetState() == download::DownloadItem::COMPLETE) return DownloadState::kComplete; if (cancel_pending_ || item_->GetState() == download::DownloadItem::CANCELLED) return DownloadState::kCancelled; if (pause_pending_ || (item_->IsPaused() && !resume_pending_)) return DownloadState::kPaused; if (resume_pending_ || item_->GetState() == download::DownloadItem::IN_PROGRESS) { return DownloadState::kInProgress; } return DownloadState::kFailed; } int64_t PersistentDownload::GetTotalBytes() { return item_->GetTotalBytes(); } int64_t PersistentDownload::GetReceivedBytes() { return item_->GetReceivedBytes(); } void PersistentDownload::Pause() { // The Pause/Resume/Cancel methods need to be called in a PostTask because we // may be in a callback from the download subsystem and it doesn't handle // nested calls. resume_pending_ = false; pause_pending_ = true; base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&PersistentDownload::PauseInternal, weak_ptr_factory_.GetWeakPtr())); } void PersistentDownload::Resume() { pause_pending_ = false; resume_pending_ = true; base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&PersistentDownload::ResumeInternal, weak_ptr_factory_.GetWeakPtr())); } void PersistentDownload::Cancel() { cancel_pending_ = true; base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&PersistentDownload::CancelInternal, weak_ptr_factory_.GetWeakPtr())); } base::FilePath PersistentDownload::GetLocation() { return item_->GetTargetFilePath(); } std::u16string PersistentDownload::GetFileNameToReportToUser() { return item_->GetFileNameToReportUser().LossyDisplayName(); } std::string PersistentDownload::GetMimeType() { return item_->GetMimeType(); } DownloadError PersistentDownload::GetError() { auto reason = item_->GetLastReason(); if (reason == download::DOWNLOAD_INTERRUPT_REASON_NONE) return DownloadError::kNoError; if (reason == download::DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM) return DownloadError::kSSLError; if (reason >= download::DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED && reason <= download::DOWNLOAD_INTERRUPT_REASON_SERVER_CROSS_ORIGIN_REDIRECT) return DownloadError::kServerError; if (reason >= download::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED && reason <= download::DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST) return DownloadError::kConnectivityError; if (reason == download::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE) return DownloadError::kNoSpace; if (reason >= download::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED && reason <= download::DOWNLOAD_INTERRUPT_REASON_FILE_SAME_AS_SOURCE) return DownloadError::kFileError; if (reason == download::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED) return DownloadError::kCancelled; return DownloadError::kOtherError; } PersistentDownload::PersistentDownload(download::DownloadItem* item) : item_(item) {} void PersistentDownload::PauseInternal() { if (pause_pending_) { pause_pending_ = false; item_->Pause(); } } int PersistentDownload::GetNotificationId() { return item_->GetId(); } bool PersistentDownload::IsTransient() { return false; } GURL PersistentDownload::GetSourceUrl() { return {}; } const SkBitmap* PersistentDownload::GetLargeIcon() { return nullptr; } void PersistentDownload::OnFinished(bool activated) { // For this type of download, activation is handled purely in Java. } void PersistentDownload::ResumeInternal() { if (resume_pending_) { resume_pending_ = false; item_->Resume(true); } } void PersistentDownload::CancelInternal() { cancel_pending_ = false; item_->Cancel(true); } } // namespace weblayer