blob: 169495d3a204f4062c9cace47b7d9cf04dc2c7c1 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "printscanmgr/executor/upstart_tools.h"
#include <memory>
#include <string>
#include <base/check.h>
#include <base/strings/stringprintf.h>
#include <dbus/bus.h>
#include <dbus/message.h>
#include <dbus/object_path.h>
#include <dbus/object_proxy.h>
#include "printscanmgr/mojom/executor.mojom.h"
namespace printscanmgr {
namespace {
constexpr char kUpstartServiceName[] = "com.ubuntu.Upstart";
constexpr char kUpstartServicePath[] = "/com/ubuntu/Upstart";
constexpr char kUpstartJobInterface[] = "com.ubuntu.Upstart0_6.Job";
constexpr char kGetInstanceMethod[] = "GetInstance";
constexpr char kRestartMethod[] = "Restart";
constexpr char kUpstartJobPath[] = "/com/ubuntu/Upstart/jobs/";
std::string UpstartJobToString(mojom::UpstartJob job) {
switch (job) {
case mojom::UpstartJob::kCupsd:
return "cupsd";
}
}
// Production implementation of UpstartTools.
class UpstartToolsImpl : public UpstartTools {
public:
explicit UpstartToolsImpl(const scoped_refptr<dbus::Bus>& bus) : bus_(bus) {
upstart_proxy_ = bus_->GetObjectProxy(
kUpstartServiceName, dbus::ObjectPath(kUpstartServicePath));
}
~UpstartToolsImpl() override = default;
bool IsJobRunning(mojom::UpstartJob job, std::string* error) override {
return CallJobMethod(job, kGetInstanceMethod, error);
}
bool RestartJob(mojom::UpstartJob job, std::string* error) override {
if (!IsJobRunning(job, error)) {
return true;
}
return CallJobMethod(job, kRestartMethod, error);
}
private:
bool CallJobMethod(mojom::UpstartJob job,
const std::string& method,
std::string* error) {
DCHECK(error);
std::string job_name = UpstartJobToString(job);
dbus::ObjectProxy* job_proxy = bus_->GetObjectProxy(
kUpstartServiceName, dbus::ObjectPath(kUpstartJobPath + job_name));
if (job_proxy == nullptr) {
*error = base::StringPrintf("Failed to get job proxy for %s.",
job_name.c_str());
return false;
}
dbus::MethodCall method_call(kUpstartJobInterface, method);
dbus::MessageWriter writer(&method_call);
writer.AppendArrayOfStrings(/*environment=*/{});
if (method != kGetInstanceMethod) {
// GetInstance is the only Job method we call without the wait argument.
writer.AppendBool(/*wait=*/true);
}
std::unique_ptr<dbus::Response> method_response =
job_proxy
->CallMethodAndBlock(&method_call,
dbus::ObjectProxy::TIMEOUT_USE_DEFAULT)
.value_or(nullptr);
if (!method_response) {
*error = base::StringPrintf("%s job (%s) request had no response.",
method.c_str(), job_name.c_str());
return false;
}
dbus::MessageReader reader(method_response.get());
dbus::ObjectPath job_path;
if (!reader.PopObjectPath(&job_path)) {
*error = base::StringPrintf("Failed to parse %s job (%s) response.",
method.c_str(), job_name.c_str());
return false;
}
return true;
}
scoped_refptr<dbus::Bus> bus_;
dbus::ObjectProxy* upstart_proxy_;
};
} // namespace
// static
std::unique_ptr<UpstartTools> UpstartTools::Create(
const scoped_refptr<dbus::Bus>& bus) {
return std::make_unique<UpstartToolsImpl>(bus);
}
} // namespace printscanmgr