blob: b82fe8516e11b41a9da5f00b3b12dbf4e9253d01 [file] [log] [blame] [edit]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "lorgnette/dlc_client.h"
#include <base/functional/bind.h>
#include <brillo/errors/error.h>
#include <chromeos/constants/lorgnette_dlc.h>
#include <dlcservice/proto_bindings/dlcservice.pb.h>
#include <string>
#include "base/files/file_path.h"
#include "base/strings/strcat.h"
#include "base/task/single_thread_task_runner.h"
namespace lorgnette {
DlcClient::DlcClient()
: supported_dlc_ids_(std::set<std::string>({kSaneBackendsPfuDlcId})) {}
void DlcClient::Init(
std::unique_ptr<org::chromium::DlcServiceInterfaceProxyInterface>
dlcservice_client) {
dlcservice_client_ = std::move(dlcservice_client);
base::WeakPtr<DlcClient> weak_ptr = weak_factory_.GetWeakPtr();
LOG(INFO) << "Setting up DlcClient";
dlcservice_client_->RegisterDlcStateChangedSignalHandler(
base::BindRepeating(&DlcClient::OnDlcStateChanged, weak_ptr),
base::BindOnce(&DlcClient::OnDlcStateChangedConnect, weak_ptr));
}
void DlcClient::SetCallbacks(
base::RepeatingCallback<void(const std::string&, const base::FilePath&)>
success_cb,
base::RepeatingCallback<void(const std::string&, const std::string&)>
failure_cb) {
success_cb_ = std::move(success_cb);
failure_cb_ = std::move(failure_cb);
}
void DlcClient::OnDlcStateChanged(const dlcservice::DlcState& dlc_state) {
if (supported_dlc_ids_.find(dlc_state.id()) == supported_dlc_ids_.end()) {
return;
}
switch (dlc_state.state()) {
case dlcservice::DlcState::INSTALLED:
InvokeSuccessCb(dlc_state.id(), dlc_state.root_path());
break;
case dlcservice::DlcState::INSTALLING:
break;
case dlcservice::DlcState::NOT_INSTALLED: {
std::string err = base::StrCat({"Failed to install DLC: ", dlc_state.id(),
" Error: ", dlc_state.last_error_code()});
InvokeErrorCb(dlc_state.id(), err);
break;
}
default:
std::string err =
base::StrCat({"Unknown error when installing: ", dlc_state.id(),
" Error: ", dlc_state.last_error_code()});
InvokeErrorCb(dlc_state.id(), err);
break;
}
}
void DlcClient::OnDlcStateChangedConnect(const std::string& interface,
const std::string& signal,
bool success) {
LOG(INFO) << "OnDlcStateChangedConnect (" << interface << ":" << signal
<< "): " << (success ? "true" : "false");
if (!success) {
std::string err =
base::StrCat({"Error connecting ", interface, ". ", signal});
InvokeErrorCb(/*dlc_id=*/"", err);
}
}
void DlcClient::InstallDlc(const std::set<std::string>& dlc_ids) {
for (const std::string& id : dlc_ids) {
dlcservice::InstallRequest install_request;
install_request.set_id(id);
dlcservice_client_->InstallAsync(
install_request,
base::BindRepeating(&DlcClient::OnDlcInstall, base::Unretained(this)),
base::BindRepeating(&DlcClient::OnDlcInstallError,
base::Unretained(this), install_request.id()));
}
}
std::optional<std::string> DlcClient::GetRootPath(const std::string& in_id,
std::string* out_error) {
DCHECK(out_error);
dlcservice::DlcState state;
brillo::ErrorPtr error;
if (!dlcservice_client_->GetDlcState(in_id, &state, &error)) {
if (error) {
*out_error = "Error calling dlcservice (code=" + error->GetCode() +
"): " + error->GetMessage();
} else {
*out_error = "Error calling dlcservice: unknown";
}
return std::nullopt;
}
if (state.state() != dlcservice::DlcState::INSTALLED) {
*out_error = base::StrCat({in_id, " was not installed, its state is: ",
std::to_string(state.state()),
" with last error: ", state.last_error_code()});
return std::nullopt;
}
return state.root_path();
}
std::set<std::string> DlcClient::GetSupportedDlcIds() const {
return supported_dlc_ids_;
}
void DlcClient::OnDlcInstall() {
return;
}
void DlcClient::InvokeSuccessCb(const std::string& dlc_id,
std::string dlc_root_path) {
if (success_cb_) {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(success_cb_, dlc_id, base::FilePath(dlc_root_path)));
}
}
void DlcClient::OnDlcInstallError(const std::string& dlc_id,
brillo::Error* error) {
InvokeErrorCb(dlc_id, error->GetMessage());
}
void DlcClient::InvokeErrorCb(const std::string& dlc_id,
const std::string& error_msg) {
if (failure_cb_) {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(failure_cb_, dlc_id, error_msg));
}
}
} // namespace lorgnette