// Copyright 2021 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/file_manager/io_task.h"
#include <type_traits>
#include <vector>
#include "base/files/file_path.h"
#include "base/functional/callback.h"
#include "base/task/sequenced_task_runner.h"
#include "chrome/browser/ash/file_manager/path_util.h"
#include "chrome/browser/ash/file_manager/volume_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "storage/browser/file_system/file_system_url.h"
namespace file_manager::io_task {
std::ostream& operator<<(std::ostream& out, const State state) {
switch (state) {
#define PRINT(s) \
case State::k##s: \
return out << #s;
PRINT(Queued)
PRINT(Scanning)
PRINT(InProgress)
PRINT(Paused)
PRINT(Success)
PRINT(Error)
PRINT(NeedPassword)
PRINT(Cancelled)
#undef PRINT
}
return out << "State(" << static_cast<std::underlying_type_t<State>>(state)
<< ")";
}
std::ostream& operator<<(std::ostream& out, OperationType op) {
switch (op) {
#define PRINT(s) \
case OperationType::k##s: \
return out << #s;
PRINT(Copy)
PRINT(Delete)
PRINT(EmptyTrash)
PRINT(Extract)
PRINT(Move)
PRINT(Restore)
PRINT(RestoreToDestination)
PRINT(Trash)
PRINT(Zip)
#undef PRINT
}
return out << "OperationType("
<< static_cast<std::underlying_type_t<OperationType>>(op) << ")";
}
void IOTask::Pause(PauseParams params) {}
void IOTask::Resume(ResumeParams) {}
void IOTask::CompleteWithError(PolicyError policy_error) {}
bool PolicyError::operator==(const PolicyError& other) const = default;
bool PolicyError::operator!=(const PolicyError& other) const = default;
bool ConflictPauseParams::operator==(const ConflictPauseParams& other) const =
default;
bool PolicyPauseParams::operator==(const PolicyPauseParams& other) const =
default;
PauseParams::PauseParams() = default;
PauseParams::PauseParams(const PauseParams& other) = default;
PauseParams& PauseParams::operator=(const PauseParams& other) = default;
PauseParams::PauseParams(PauseParams&& other) = default;
PauseParams& PauseParams::operator=(PauseParams&& other) = default;
bool PauseParams::operator==(const PauseParams& other) const {
return (conflict_params == other.conflict_params) &&
(policy_params == other.policy_params);
}
PauseParams::~PauseParams() = default;
ResumeParams::ResumeParams() = default;
ResumeParams::ResumeParams(const ResumeParams& other) = default;
ResumeParams& ResumeParams::operator=(const ResumeParams& other) = default;
ResumeParams::ResumeParams(ResumeParams&& other) = default;
ResumeParams& ResumeParams::operator=(ResumeParams&& other) = default;
ResumeParams::~ResumeParams() = default;
EntryStatus::EntryStatus(storage::FileSystemURL file_url,
std::optional<base::File::Error> file_error,
std::optional<storage::FileSystemURL> source_url)
: url(file_url), error(file_error), source_url(source_url) {}
EntryStatus::~EntryStatus() = default;
EntryStatus::EntryStatus(EntryStatus&& other) = default;
EntryStatus& EntryStatus::operator=(EntryStatus&& other) = default;
ProgressStatus::ProgressStatus() = default;
ProgressStatus::~ProgressStatus() = default;
ProgressStatus::ProgressStatus(ProgressStatus&& other) = default;
ProgressStatus& ProgressStatus::operator=(ProgressStatus&& other) = default;
bool ProgressStatus::IsPaused() const {
return state == State::kPaused;
}
bool ProgressStatus::IsCompleted() const {
return state == State::kSuccess || state == State::kError ||
state == State::kCancelled;
}
bool ProgressStatus::HasWarning() const {
// We should show a warning if the task is paused because of policy.
return IsPaused() && pause_params.policy_params.has_value();
}
bool ProgressStatus::HasPolicyError() const {
return state == State::kError && policy_error.has_value();
}
bool ProgressStatus::IsScanning() const {
return state == State::kScanning;
}
std::string ProgressStatus::GetSourceName(Profile* profile) const {
if (!source_name.empty()) {
return source_name;
}
if (sources.size() == 0) {
return {};
}
return util::GetDisplayablePath(profile, sources.front().url)
.value_or(base::FilePath())
.BaseName()
.value();
}
void ProgressStatus::SetDestinationFolder(storage::FileSystemURL folder,
Profile* const profile) {
destination_folder_ = std::move(folder);
destination_volume_id_.clear();
if (profile) {
if (VolumeManager* const volume_manager = VolumeManager::Get(profile)) {
if (const base::WeakPtr<const Volume> volume =
volume_manager->FindVolumeFromPath(destination_folder_.path())) {
destination_volume_id_ = volume->volume_id();
}
}
}
}
DummyIOTask::DummyIOTask(std::vector<storage::FileSystemURL> source_urls,
storage::FileSystemURL destination_folder,
OperationType type,
bool show_notifications,
bool progress_succeeds)
: IOTask(show_notifications), progress_succeeds_(progress_succeeds) {
progress_.state = State::kQueued;
progress_.type = type;
progress_.SetDestinationFolder(std::move(destination_folder));
progress_.bytes_transferred = 0;
progress_.total_bytes = 2;
for (auto& url : source_urls) {
progress_.sources.emplace_back(url, std::nullopt);
}
}
DummyIOTask::~DummyIOTask() = default;
void DummyIOTask::Execute(IOTask::ProgressCallback progress_callback,
IOTask::CompleteCallback complete_callback) {
progress_callback_ = std::move(progress_callback);
complete_callback_ = std::move(complete_callback);
progress_.state = State::kInProgress;
progress_callback_.Run(progress_);
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&DummyIOTask::DoProgress, weak_ptr_factory_.GetWeakPtr()));
}
void DummyIOTask::Pause(PauseParams pause_params) {
progress_.state = State::kPaused;
progress_.pause_params = pause_params;
}
void DummyIOTask::Resume(ResumeParams resume_params) {
progress_.state = State::kInProgress;
}
void DummyIOTask::Cancel() {
progress_.state = State::kCancelled;
}
void DummyIOTask::CompleteWithError(PolicyError policy_error) {
progress_.state = State::kError;
progress_.policy_error.emplace(std::move(policy_error));
}
void DummyIOTask::DoProgress() {
if (progress_.IsPaused()) {
return;
}
progress_.bytes_transferred = 1;
progress_callback_.Run(progress_);
if (progress_succeeds_) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&DummyIOTask::DoComplete,
weak_ptr_factory_.GetWeakPtr()));
}
}
void DummyIOTask::DoComplete() {
progress_.state = State::kSuccess;
progress_.bytes_transferred = 2;
for (auto& source : progress_.sources) {
source.error.emplace(base::File::FILE_OK);
}
std::move(complete_callback_).Run(std::move(progress_));
}
} // namespace file_manager::io_task