// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ash/plugin_vm/plugin_vm_image_download_client.h"
#include "base/functional/bind.h"
#include "base/task/sequenced_task_runner.h"
#include "chrome/browser/ash/plugin_vm/plugin_vm_installer.h"
#include "chrome/browser/ash/plugin_vm/plugin_vm_installer_factory.h"
#include "chrome/browser/download/background_download_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_key.h"
#include "components/download/public/background_service/background_download_service.h"
#include "components/download/public/background_service/download_metadata.h"
#include "services/network/public/cpp/resource_request_body.h"
namespace plugin_vm {
PluginVmImageDownloadClient::PluginVmImageDownloadClient(Profile* profile)
: profile_(profile) {}
PluginVmImageDownloadClient::~PluginVmImageDownloadClient() = default;
PluginVmInstaller* PluginVmImageDownloadClient::GetInstaller() {
return PluginVmInstallerFactory::GetForProfile(profile_);
}
bool PluginVmImageDownloadClient::IsCurrentDownload(const std::string& guid) {
return guid == GetInstaller()->GetCurrentDownloadGuid();
}
void PluginVmImageDownloadClient::OnServiceInitialized(
bool state_lost,
const std::vector<download::DownloadMetaData>& downloads) {
// TODO(timloh): It appears that only completed downloads (aka previous
// successful installations) surface here, so this logic might not be needed.
for (const auto& download : downloads) {
VLOG(1) << "Download tracked by BackgroundDownloadService: "
<< download.guid;
BackgroundDownloadServiceFactory::GetForKey(profile_->GetProfileKey())
->CancelDownload(download.guid);
}
}
void PluginVmImageDownloadClient::OnServiceUnavailable() {
}
void PluginVmImageDownloadClient::OnDownloadStarted(
const std::string& guid,
const std::vector<GURL>& url_chain,
const scoped_refptr<const net::HttpResponseHeaders>& headers) {
// We do not want downloads that are tracked by download service from its
// initialization to proceed.
if (!IsCurrentDownload(guid)) {
BackgroundDownloadServiceFactory::GetForKey(profile_->GetProfileKey())
->CancelDownload(guid);
return;
}
content_length_ = headers ? headers->GetContentLength() : -1;
response_code_ = headers ? headers->response_code() : -1;
GetInstaller()->OnDownloadStarted();
}
void PluginVmImageDownloadClient::OnDownloadUpdated(const std::string& guid,
uint64_t bytes_uploaded,
uint64_t bytes_downloaded) {
DCHECK(IsCurrentDownload(guid));
VLOG(1) << bytes_downloaded << " bytes downloaded";
GetInstaller()->OnDownloadProgressUpdated(bytes_downloaded, content_length_);
}
void PluginVmImageDownloadClient::OnDownloadFailed(
const std::string& guid,
const download::CompletionInfo& completion_info,
download::Client::FailureReason clientReason) {
auto failureReason =
PluginVmInstaller::FailureReason::DOWNLOAD_FAILED_UNKNOWN;
switch (clientReason) {
case download::Client::FailureReason::NETWORK:
VLOG(1) << "Failure reason: NETWORK, response_code: " << response_code_;
if (response_code_ == 401) {
failureReason = PluginVmInstaller::FailureReason::DOWNLOAD_FAILED_401;
} else if (response_code_ == 403) {
failureReason = PluginVmInstaller::FailureReason::DOWNLOAD_FAILED_403;
} else if (response_code_ == 404) {
failureReason = PluginVmInstaller::FailureReason::DOWNLOAD_FAILED_404;
} else {
failureReason =
PluginVmInstaller::FailureReason::DOWNLOAD_FAILED_NETWORK;
}
break;
case download::Client::FailureReason::UPLOAD_TIMEDOUT:
VLOG(1) << "Failure reason: UPLOAD_TIMEDOUT";
break;
case download::Client::FailureReason::TIMEDOUT:
VLOG(1) << "Failure reason: TIMEDOUT";
break;
case download::Client::FailureReason::UNKNOWN:
VLOG(1) << "Failure reason: UNKNOWN";
break;
case download::Client::FailureReason::ABORTED:
VLOG(1) << "Failure reason: ABORTED";
failureReason = PluginVmInstaller::FailureReason::DOWNLOAD_FAILED_ABORTED;
break;
case download::Client::FailureReason::CANCELLED:
VLOG(1) << "Failure reason: CANCELLED";
break;
}
if (!IsCurrentDownload(guid))
return;
GetInstaller()->OnDownloadFailed(failureReason);
}
void PluginVmImageDownloadClient::OnDownloadSucceeded(
const std::string& guid,
const download::CompletionInfo& completion_info) {
DCHECK(IsCurrentDownload(guid));
VLOG(1) << "Downloaded file is in " << completion_info.path.value();
GetInstaller()->OnDownloadCompleted(completion_info);
}
bool PluginVmImageDownloadClient::CanServiceRemoveDownloadedFile(
const std::string& guid,
bool force_delete) {
return true;
}
void PluginVmImageDownloadClient::GetUploadData(
const std::string& guid,
download::GetUploadDataCallback callback) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), nullptr));
}
} // namespace plugin_vm