blob: 20d71595bf250c1cef3a50a4f474802a9c2af624 [file] [log] [blame]
// Copyright 2018 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 "chrome/browser/component_updater/fake_cros_component_manager.h"
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/threading/sequenced_task_runner_handle.h"
namespace component_updater {
FakeCrOSComponentManager::ComponentInfo::ComponentInfo(
Error load_response,
const base::FilePath& install_path,
const base::FilePath& mount_path)
: load_response(load_response),
install_path(install_path),
mount_path(mount_path) {
// If component load fails, neither install nor mount path should be set.
DCHECK(load_response == Error::NONE ||
(install_path.empty() && mount_path.empty()));
// Component should have install path set if it's expected to be loaded.
DCHECK(load_response != Error::NONE || !install_path.empty());
}
FakeCrOSComponentManager::ComponentInfo::~ComponentInfo() = default;
FakeCrOSComponentManager::FakeCrOSComponentManager() = default;
FakeCrOSComponentManager::~FakeCrOSComponentManager() = default;
bool FakeCrOSComponentManager::FinishLoadRequest(
const std::string& name,
const ComponentInfo& component_info) {
if (!pending_loads_.count(name) || pending_loads_[name].empty()) {
LOG(ERROR) << "No pending load for " << name;
return false;
}
auto& pending_load = pending_loads_[name].front();
FinishComponentLoad(name, pending_load.mount_requested, component_info);
LoadCallback callback = std::move(pending_load.callback);
pending_loads_[name].pop_front();
std::move(callback).Run(component_info.load_response,
component_info.load_response == Error::NONE
? component_info.mount_path
: base::FilePath());
return true;
}
bool FakeCrOSComponentManager::ResetComponentState(const std::string& name,
const ComponentInfo& state) {
if (!supported_components_.count(name))
return false;
installed_components_.erase(name);
mounted_components_.erase(name);
component_infos_.erase(name);
component_infos_.emplace(
name,
ComponentInfo(state.load_response, state.install_path, state.mount_path));
return true;
}
bool FakeCrOSComponentManager::HasPendingInstall(
const std::string& name) const {
DCHECK(queue_load_requests_);
const auto& it = pending_loads_.find(name);
return it != pending_loads_.end() && !it->second.empty();
}
bool FakeCrOSComponentManager::UpdateRequested(const std::string& name) const {
DCHECK(queue_load_requests_);
const auto& it = pending_loads_.find(name);
return it != pending_loads_.end() && !it->second.empty() &&
it->second.front().needs_update;
}
void FakeCrOSComponentManager::SetDelegate(Delegate* delegate) {
// No-op, not used by the fake.
}
void FakeCrOSComponentManager::Load(const std::string& name,
MountPolicy mount_policy,
UpdatePolicy update_policy,
LoadCallback load_callback) {
if (!supported_components_.count(name)) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(load_callback),
Error::UNKNOWN_COMPONENT, base::FilePath()));
return;
}
bool needs_update = update_policy == UpdatePolicy::kForce ||
(!installed_components_.count(name) &&
update_policy != UpdatePolicy::kSkip);
// The request has to be handled if the component is not yet installed, or it
// requires immediate update.
if (needs_update || !installed_components_.count(name)) {
HandlePendingRequest(name, mount_policy == MountPolicy::kMount,
needs_update, std::move(load_callback));
return;
}
// Handle request if the component has yet to be mounted - e.g. if previous
// loads installed the component without mounting it.
if (!mounted_components_.count(name) && mount_policy == MountPolicy::kMount) {
HandlePendingRequest(name, true /*mount_requested*/, false /*needs_update*/,
std::move(load_callback));
return;
}
// The component has been prevoiusly installed, and mounted as required by
// this load request - run the callback according to the existing state.
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(load_callback), Error::NONE,
mount_policy == MountPolicy::kMount
? mounted_components_[name]
: base::FilePath()));
}
bool FakeCrOSComponentManager::Unload(const std::string& name) {
registered_components_.erase(name);
mounted_components_.erase(name);
installed_components_.erase(name);
return true;
}
void FakeCrOSComponentManager::RegisterCompatiblePath(
const std::string& name,
const base::FilePath& path) {
installed_components_[name] = path;
}
void FakeCrOSComponentManager::UnregisterCompatiblePath(
const std::string& name) {
installed_components_.erase(name);
}
base::FilePath FakeCrOSComponentManager::GetCompatiblePath(
const std::string& name) const {
const auto& it = installed_components_.find(name);
if (it == installed_components_.end())
return base::FilePath();
return it->second;
}
bool FakeCrOSComponentManager::IsRegistered(const std::string& name) const {
return registered_components_.count(name);
}
void FakeCrOSComponentManager::RegisterInstalled() {
NOTIMPLEMENTED();
}
FakeCrOSComponentManager::LoadRequest::LoadRequest(bool mount_requested,
bool needs_update,
LoadCallback callback)
: mount_requested(mount_requested),
needs_update(needs_update),
callback(std::move(callback)) {}
FakeCrOSComponentManager::LoadRequest::~LoadRequest() = default;
void FakeCrOSComponentManager::HandlePendingRequest(const std::string& name,
bool mount_requested,
bool needs_update,
LoadCallback callback) {
if (queue_load_requests_) {
pending_loads_[name].emplace_back(mount_requested, needs_update,
std::move(callback));
return;
}
const auto& component_info = component_infos_.find(name);
if (component_info == component_infos_.end()) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), Error::INSTALL_FAILURE,
base::FilePath()));
return;
}
FinishComponentLoad(name, mount_requested, component_info->second);
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), component_info->second.load_response,
component_info->second.mount_path));
}
void FakeCrOSComponentManager::FinishComponentLoad(
const std::string& name,
bool mount_requested,
const ComponentInfo& component_info) {
registered_components_.insert(name);
if (component_info.load_response != Error::NONE)
return;
DCHECK_EQ(mount_requested, !component_info.mount_path.empty());
installed_components_[name] = component_info.install_path;
if (mount_requested)
mounted_components_[name] = component_info.mount_path;
}
} // namespace component_updater