// Copyright 2024 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/policy/skyvault/skyvault_rename_handler.h"
#include "base/files/file_util.h"
#include "chrome/browser/ash/drive/drive_integration_service.h"
#include "chrome/browser/ash/file_manager/fileapi_util.h"
#include "chrome/browser/ash/policy/skyvault/drive_upload_observer.h"
#include "chrome/browser/ash/policy/skyvault/odfs_skyvault_uploader.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "components/download/public/common/download_item.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/download_item_utils.h"
namespace policy {
namespace {
// Returns true if the file should be uploaded to the specified cloud provider.
bool ShouldUploadFile(Profile* profile,
SkyvaultRenameHandler::CloudProvider cloud_provider,
const base::FilePath& path) {
switch (cloud_provider) {
case SkyvaultRenameHandler::kGoogleDrive: {
drive::DriveIntegrationService* service =
drive::DriveIntegrationServiceFactory::FindForProfile(profile);
return service &&
service->GetRelativeDrivePath(path, /*drive_path=*/nullptr);
}
case SkyvaultRenameHandler::kOneDrive:
base::FilePath tmp_dir;
if (!base::GetTempDir(&tmp_dir)) {
return false;
}
return tmp_dir.IsParent(path);
}
}
} // namespace
// static
std::unique_ptr<SkyvaultRenameHandler> SkyvaultRenameHandler::CreateIfNeeded(
download::DownloadItem* download_item) {
if (!base::FeatureList::IsEnabled(features::kSkyVault)) {
return nullptr;
}
Profile* profile = Profile::FromBrowserContext(
content::DownloadItemUtils::GetBrowserContext(download_item));
if (!profile) {
return nullptr;
}
const auto downloads_path =
profile->GetPrefs()->GetFilePath(::prefs::kDownloadDefaultDirectory);
size_t position = downloads_path.value().find(
local_user_files::kOneDrivePolicyVariableName);
if (position != base::FilePath::StringType::npos) {
return std::make_unique<SkyvaultRenameHandler>(
profile, CloudProvider::kOneDrive, download_item);
}
position = downloads_path.value().find(
local_user_files::kGoogleDrivePolicyVariableName);
if (position != base::FilePath::StringType::npos &&
!local_user_files::LocalUserFilesAllowed()) {
return std::make_unique<SkyvaultRenameHandler>(
profile, CloudProvider::kGoogleDrive, download_item);
}
return nullptr;
}
SkyvaultRenameHandler::SkyvaultRenameHandler(
Profile* profile,
CloudProvider cloud_provider,
download::DownloadItem* download_item)
: download::DownloadItemRenameHandler(download_item),
profile_(profile),
cloud_provider_(cloud_provider) {}
SkyvaultRenameHandler::~SkyvaultRenameHandler() = default;
void SkyvaultRenameHandler::Start(ProgressCallback progress_callback,
RenameCallback rename_callback) {
progress_callback_ = std::move(progress_callback);
rename_callback_ = std::move(rename_callback);
if (!ShouldUploadFile(profile_, cloud_provider_,
download_item_->GetTargetFilePath())) {
std::move(rename_callback_)
.Run(download::DOWNLOAD_INTERRUPT_REASON_NONE,
download_item_->GetTargetFilePath());
return;
}
switch (cloud_provider_) {
case CloudProvider::kGoogleDrive:
ash::cloud_upload::DriveUploadObserver::Observe(
profile_, download_item_->GetTargetFilePath(),
download_item_->GetTotalBytes(),
base::BindRepeating(&SkyvaultRenameHandler::OnProgressUpdate,
weak_factory_.GetWeakPtr()),
base::BindOnce(&SkyvaultRenameHandler::OnDriveUploadDone,
weak_factory_.GetWeakPtr()));
break;
case CloudProvider::kOneDrive:
ash::cloud_upload::OdfsSkyvaultUploader::Upload(
profile_, download_item_->GetTargetFilePath(),
ash::cloud_upload::OdfsSkyvaultUploader::FileType::kDownload,
base::BindRepeating(&SkyvaultRenameHandler::OnProgressUpdate,
weak_factory_.GetWeakPtr()),
base::BindOnce(&SkyvaultRenameHandler::OnOneDriveUploadDone,
weak_factory_.GetWeakPtr()));
break;
}
}
bool SkyvaultRenameHandler::ShowRenameProgress() {
return true;
}
void SkyvaultRenameHandler::StartForTesting(ProgressCallback progress_callback,
RenameCallback rename_callback) {
progress_callback_ = std::move(progress_callback);
rename_callback_ = std::move(rename_callback);
}
void SkyvaultRenameHandler::OnProgressUpdate(int64_t bytes_so_far) {
if (!progress_callback_.is_null() && bytes_so_far > -1) {
progress_callback_.Run(bytes_so_far, /*bytes_per_sec=*/0u);
}
}
void SkyvaultRenameHandler::OnDriveUploadDone(bool success) {
DCHECK(!rename_callback_.is_null());
auto reason = success ? download::DOWNLOAD_INTERRUPT_REASON_NONE
: download::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
std::move(rename_callback_).Run(reason, download_item_->GetTargetFilePath());
}
void SkyvaultRenameHandler::OnOneDriveUploadDone(
bool success,
storage::FileSystemURL file_url) {
DCHECK(!rename_callback_.is_null());
auto reason = success ? download::DOWNLOAD_INTERRUPT_REASON_NONE
: download::DOWNLOAD_INTERRUPT_REASON_FILE_FAILED;
if (success) {
download_item_->SetDisplayName(file_url.path().BaseName());
}
std::move(rename_callback_).Run(reason, file_url.path());
}
} // namespace policy