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