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