| // 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 |