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