xref: /aosp_15_r20/external/libbrillo/brillo/dbus/dbus_method_response.h (revision 1a96fba65179ea7d3f56207137718607415c5953)
1*1a96fba6SXin Li // Copyright 2014 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li 
5*1a96fba6SXin Li #ifndef LIBBRILLO_BRILLO_DBUS_DBUS_METHOD_RESPONSE_H_
6*1a96fba6SXin Li #define LIBBRILLO_BRILLO_DBUS_DBUS_METHOD_RESPONSE_H_
7*1a96fba6SXin Li 
8*1a96fba6SXin Li #include <memory>
9*1a96fba6SXin Li #include <string>
10*1a96fba6SXin Li #include <utility>
11*1a96fba6SXin Li 
12*1a96fba6SXin Li #include <base/bind.h>
13*1a96fba6SXin Li #include <base/location.h>
14*1a96fba6SXin Li #include <base/macros.h>
15*1a96fba6SXin Li #include <brillo/brillo_export.h>
16*1a96fba6SXin Li #include <brillo/dbus/dbus_param_writer.h>
17*1a96fba6SXin Li #include <brillo/errors/error.h>
18*1a96fba6SXin Li #include <dbus/exported_object.h>
19*1a96fba6SXin Li #include <dbus/message.h>
20*1a96fba6SXin Li 
21*1a96fba6SXin Li namespace brillo {
22*1a96fba6SXin Li 
23*1a96fba6SXin Li class Error;
24*1a96fba6SXin Li 
25*1a96fba6SXin Li namespace dbus_utils {
26*1a96fba6SXin Li 
27*1a96fba6SXin Li using ResponseSender = ::dbus::ExportedObject::ResponseSender;
28*1a96fba6SXin Li 
29*1a96fba6SXin Li // DBusMethodResponseBase is a helper class used with asynchronous D-Bus method
30*1a96fba6SXin Li // handlers to encapsulate the information needed to send the method call
31*1a96fba6SXin Li // response when it is available.
32*1a96fba6SXin Li class BRILLO_EXPORT DBusMethodResponseBase {
33*1a96fba6SXin Li  public:
34*1a96fba6SXin Li   DBusMethodResponseBase(::dbus::MethodCall* method_call,
35*1a96fba6SXin Li                          ResponseSender sender);
DBusMethodResponseBase(DBusMethodResponseBase && other)36*1a96fba6SXin Li   DBusMethodResponseBase(DBusMethodResponseBase&& other)
37*1a96fba6SXin Li       : sender_(std::exchange(
38*1a96fba6SXin Li             other.sender_,
39*1a96fba6SXin Li             base::Bind([](std::unique_ptr<dbus::Response> response) {
40*1a96fba6SXin Li               LOG(DFATAL)
41*1a96fba6SXin Li                   << "Empty DBusMethodResponseBase attempts to send a response";
42*1a96fba6SXin Li             }))),
43*1a96fba6SXin Li         method_call_(std::exchange(other.method_call_, nullptr)) {}
44*1a96fba6SXin Li   DBusMethodResponseBase& operator=(DBusMethodResponseBase&& other) = delete;
45*1a96fba6SXin Li 
46*1a96fba6SXin Li   virtual ~DBusMethodResponseBase();
47*1a96fba6SXin Li 
48*1a96fba6SXin Li   // Sends an error response. Marshals the |error| object over D-Bus.
49*1a96fba6SXin Li   // If |error| is from the "dbus" error domain, takes the |error_code| from
50*1a96fba6SXin Li   // |error| and uses it as the DBus error name.
51*1a96fba6SXin Li   // For error is from other domains, the full error information (domain, error
52*1a96fba6SXin Li   // code, error message) is encoded into the D-Bus error message and returned
53*1a96fba6SXin Li   // to the caller as "org.freedesktop.DBus.Failed".
54*1a96fba6SXin Li   virtual void ReplyWithError(const brillo::Error* error);
55*1a96fba6SXin Li 
56*1a96fba6SXin Li   // Constructs brillo::Error object from the parameters specified and send
57*1a96fba6SXin Li   // the error information over D-Bus using the method above.
58*1a96fba6SXin Li   virtual void ReplyWithError(const base::Location& location,
59*1a96fba6SXin Li                               const std::string& error_domain,
60*1a96fba6SXin Li                               const std::string& error_code,
61*1a96fba6SXin Li                               const std::string& error_message);
62*1a96fba6SXin Li 
63*1a96fba6SXin Li   // Sends a raw D-Bus response message.
64*1a96fba6SXin Li   void SendRawResponse(std::unique_ptr<::dbus::Response> response);
65*1a96fba6SXin Li 
66*1a96fba6SXin Li   // Creates a custom response object for the current method call.
67*1a96fba6SXin Li   std::unique_ptr<::dbus::Response> CreateCustomResponse() const;
68*1a96fba6SXin Li 
69*1a96fba6SXin Li   // Checks if the response has been sent already.
70*1a96fba6SXin Li   bool IsResponseSent() const;
71*1a96fba6SXin Li 
72*1a96fba6SXin Li  protected:
73*1a96fba6SXin Li   void CheckCanSendResponse() const;
74*1a96fba6SXin Li 
75*1a96fba6SXin Li   // Aborts the method execution. Does not send any response message.
76*1a96fba6SXin Li   void Abort();
77*1a96fba6SXin Li 
78*1a96fba6SXin Li  private:
79*1a96fba6SXin Li   // A callback to be called to send the method call response message.
80*1a96fba6SXin Li   ResponseSender sender_;
81*1a96fba6SXin Li   // |method_call_| is actually owned by |sender_| (it is embedded as unique_ptr
82*1a96fba6SXin Li   // in the bound parameter list in the Callback). We set it to nullptr after
83*1a96fba6SXin Li   // the method call response has been sent to ensure we can't possibly try
84*1a96fba6SXin Li   // to send a response again somehow.
85*1a96fba6SXin Li   ::dbus::MethodCall* method_call_;
86*1a96fba6SXin Li };
87*1a96fba6SXin Li 
88*1a96fba6SXin Li // DBusMethodResponse is an explicitly-typed version of DBusMethodResponse.
89*1a96fba6SXin Li // Using DBusMethodResponse<Types...> indicates the types a D-Bus method
90*1a96fba6SXin Li // is expected to return.
91*1a96fba6SXin Li template<typename... Types>
92*1a96fba6SXin Li class DBusMethodResponse : public DBusMethodResponseBase {
93*1a96fba6SXin Li  public:
94*1a96fba6SXin Li   // Make the base class's custom constructor available to DBusMethodResponse.
95*1a96fba6SXin Li   using DBusMethodResponseBase::DBusMethodResponseBase;
96*1a96fba6SXin Li 
97*1a96fba6SXin Li   // Sends the a successful response. |return_values| can contain a list
98*1a96fba6SXin Li   // of return values to be sent to the caller.
Return(const Types &...return_values)99*1a96fba6SXin Li   virtual void Return(const Types&... return_values) {
100*1a96fba6SXin Li     CheckCanSendResponse();
101*1a96fba6SXin Li     auto response = CreateCustomResponse();
102*1a96fba6SXin Li     ::dbus::MessageWriter writer(response.get());
103*1a96fba6SXin Li     DBusParamWriter::Append(&writer, return_values...);
104*1a96fba6SXin Li     SendRawResponse(std::move(response));
105*1a96fba6SXin Li   }
106*1a96fba6SXin Li };
107*1a96fba6SXin Li 
108*1a96fba6SXin Li }  // namespace dbus_utils
109*1a96fba6SXin Li }  // namespace brillo
110*1a96fba6SXin Li 
111*1a96fba6SXin Li #endif  // LIBBRILLO_BRILLO_DBUS_DBUS_METHOD_RESPONSE_H_
112