blob: 7785cc7db71fb5b4a75b6b3b217b98d55a7bd402 [file] [log] [blame]
// 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_controller.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "content/public/browser/device_service.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
namespace file_manager {
namespace io_task {
IOTaskController::IOTaskController() {
DETACH_FROM_SEQUENCE(sequence_checker_);
}
IOTaskController::~IOTaskController() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void IOTaskController::NotifyIOTaskObservers(const ProgressStatus& status) {
for (IOTaskController::Observer& observer : observers_) {
observer.OnIOTaskStatus(status);
}
}
void IOTaskController::OnIOTaskProgress(const ProgressStatus& status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NotifyIOTaskObservers(status);
}
void IOTaskController::OnIOTaskComplete(IOTaskId task_id,
ProgressStatus status) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
NotifyIOTaskObservers(status);
RemoveIOTask(task_id);
}
void IOTaskController::AddObserver(IOTaskController::Observer* observer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
observers_.AddObserver(observer);
}
void IOTaskController::RemoveObserver(IOTaskController::Observer* observer) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
observers_.RemoveObserver(observer);
}
IOTaskId IOTaskController::Add(std::unique_ptr<IOTask> task) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
IOTaskId task_id = ++last_id_;
task->SetTaskID(task_id);
// Notify observers that the task has been queued.
NotifyIOTaskObservers(task->progress());
// TODO(b/199807189): Queue the task.
PutIOTask(task_id, std::move(task))
->Execute(base::BindRepeating(&IOTaskController::OnIOTaskProgress,
weak_ptr_factory_.GetWeakPtr()),
base::BindPostTask(
base::SequencedTaskRunner::GetCurrentDefault(),
base::BindOnce(&IOTaskController::OnIOTaskComplete,
weak_ptr_factory_.GetWeakPtr(), task_id)));
return task_id;
}
void IOTaskController::Cancel(IOTaskId task_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = tasks_.find(task_id);
if (it != tasks_.end()) {
IOTask* task = it->second.get();
task->Cancel();
NotifyIOTaskObservers(task->progress());
RemoveIOTask(task_id);
} else {
LOG(WARNING) << "Failed to cancel task: " << task_id << " not found";
}
}
device::mojom::WakeLock* IOTaskController::GetWakeLock() {
if (!wake_lock_) {
mojo::Remote<device::mojom::WakeLockProvider> provider;
content::GetDeviceService().BindWakeLockProvider(
provider.BindNewPipeAndPassReceiver());
provider->GetWakeLockWithoutContext(
device::mojom::WakeLockType::kPreventDisplaySleep,
device::mojom::WakeLockReason::kOther, "IOTask",
wake_lock_.BindNewPipeAndPassReceiver());
}
return wake_lock_.get();
}
IOTask* IOTaskController::PutIOTask(const IOTaskId task_id,
std::unique_ptr<IOTask> task) {
if (tasks_.empty()) {
GetWakeLock()->RequestWakeLock();
++wake_lock_counter_for_tests_;
}
IOTask* task_ptr = task.get();
tasks_[task_id] = std::move(task);
return task_ptr;
}
void IOTaskController::RemoveIOTask(const IOTaskId task_id) {
tasks_.erase(task_id);
if (tasks_.empty()) {
GetWakeLock()->CancelWakeLock();
--wake_lock_counter_for_tests_;
}
}
} // namespace io_task
} // namespace file_manager