// Copyright 2020 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/download_impl.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" #if defined(OS_ANDROID) #include "base/android/jni_string.h" #include "weblayer/browser/java/jni/DownloadImpl_jni.h" #endif namespace weblayer { namespace { const char kDownloadImplKeyName[] = "weblayer_download_impl"; } void DownloadImpl::Create(download::DownloadItem* item) { item->SetUserData(kDownloadImplKeyName, base::WrapUnique(new DownloadImpl(item))); } DownloadImpl* DownloadImpl::Get(download::DownloadItem* item) { return static_cast(item->GetUserData(kDownloadImplKeyName)); } DownloadImpl::DownloadImpl(download::DownloadItem* item) : item_(item) {} DownloadImpl::~DownloadImpl() { #if defined(OS_ANDROID) if (java_download_) { Java_DownloadImpl_onNativeDestroyed(base::android::AttachCurrentThread(), java_download_); } #endif } #if defined(OS_ANDROID) void DownloadImpl::SetJavaDownload( JNIEnv* env, const base::android::JavaParamRef& java_download) { java_download_.Reset(env, java_download); } base::android::ScopedJavaLocalRef DownloadImpl::GetLocation( JNIEnv* env) { return base::android::ScopedJavaLocalRef( base::android::ConvertUTF8ToJavaString(env, GetLocation().value())); } base::android::ScopedJavaLocalRef DownloadImpl::GetFileNameToReportToUser(JNIEnv* env) { return base::android::ScopedJavaLocalRef( base::android::ConvertUTF8ToJavaString( env, GetFileNameToReportToUser().value())); } base::android::ScopedJavaLocalRef DownloadImpl::GetMimeTypeImpl( JNIEnv* env) { return base::android::ScopedJavaLocalRef( base::android::ConvertUTF8ToJavaString(env, GetMimeType())); } #endif DownloadState DownloadImpl::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 DownloadImpl::GetTotalBytes() { return item_->GetTotalBytes(); } int64_t DownloadImpl::GetReceivedBytes() { return item_->GetReceivedBytes(); } void DownloadImpl::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(&DownloadImpl::PauseInternal, weak_ptr_factory_.GetWeakPtr())); } void DownloadImpl::Resume() { pause_pending_ = false; resume_pending_ = true; base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&DownloadImpl::ResumeInternal, weak_ptr_factory_.GetWeakPtr())); } void DownloadImpl::Cancel() { cancel_pending_ = true; base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&DownloadImpl::CancelInternal, weak_ptr_factory_.GetWeakPtr())); } base::FilePath DownloadImpl::GetLocation() { return item_->GetTargetFilePath(); } base::FilePath DownloadImpl::GetFileNameToReportToUser() { return item_->GetFileNameToReportUser(); } std::string DownloadImpl::GetMimeType() { return item_->GetMimeType(); } DownloadError DownloadImpl::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; } void DownloadImpl::PauseInternal() { if (pause_pending_) { pause_pending_ = false; item_->Pause(); } } uint32_t DownloadImpl::GetId() { return item_->GetId(); } void DownloadImpl::ResumeInternal() { if (resume_pending_) { resume_pending_ = false; item_->Resume(true); } } void DownloadImpl::CancelInternal() { cancel_pending_ = false; item_->Cancel(true); } } // namespace weblayer