blob: 1daa690b0b49f7661bfd89ecaf7dcbbdd298ae5e [file] [log] [blame]
// 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<DownloadImpl*>(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<jobject>& java_download) {
java_download_.Reset(env, java_download);
}
base::android::ScopedJavaLocalRef<jstring> DownloadImpl::GetLocation(
JNIEnv* env) {
return base::android::ScopedJavaLocalRef<jstring>(
base::android::ConvertUTF8ToJavaString(env, GetLocation().value()));
}
base::android::ScopedJavaLocalRef<jstring>
DownloadImpl::GetFileNameToReportToUser(JNIEnv* env) {
return base::android::ScopedJavaLocalRef<jstring>(
base::android::ConvertUTF8ToJavaString(
env, GetFileNameToReportToUser().value()));
}
base::android::ScopedJavaLocalRef<jstring> DownloadImpl::GetMimeTypeImpl(
JNIEnv* env) {
return base::android::ScopedJavaLocalRef<jstring>(
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