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_SIGNAL_HANDLER_H_ 6 #define LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_ 7 8 #include <string> 9 10 #include <brillo/bind_lambda.h> 11 #include <brillo/dbus/dbus_param_reader.h> 12 #include <dbus/message.h> 13 #include <dbus/object_proxy.h> 14 15 namespace brillo { 16 namespace dbus_utils { 17 18 // brillo::dbus_utils::ConnectToSignal() is a helper function similar to 19 // dbus::ObjectProxy::ConnectToSignal() but the |signal_callback| is an actual 20 // C++ signal handler with expected signal parameters as native method args. 21 // 22 // brillo::dbus_utils::ConnectToSignal() actually registers a stub signal 23 // handler with D-Bus which has a standard signature that matches 24 // dbus::ObjectProxy::SignalCallback. 25 // 26 // When a D-Bus signal is emitted, the stub handler is invoked, which unpacks 27 // the expected parameters from dbus::Signal message and then calls 28 // |signal_callback| with unpacked arguments. 29 // 30 // If the signal message doesn't contain correct number or types of arguments, 31 // an error message is logged to the system log and the signal is ignored 32 // (|signal_callback| is not invoked). 33 template<typename... Args> 34 void ConnectToSignal( 35 dbus::ObjectProxy* object_proxy, 36 const std::string& interface_name, 37 const std::string& signal_name, 38 base::Callback<void(Args...)> signal_callback, 39 dbus::ObjectProxy::OnConnectedCallback on_connected_callback) { 40 // Raw signal handler stub method. When called, unpacks the signal arguments 41 // from |signal| message buffer and redirects the call to 42 // |signal_callback_wrapper| which, in turn, would call the user-provided 43 // |signal_callback|. 44 auto dbus_signal_callback = []( 45 const base::Callback<void(Args...)>& signal_callback, 46 dbus::Signal* signal) { 47 // DBusParamReader::Invoke() needs a functor object, not a base::Callback. 48 // Wrap the callback with lambda so we can redirect the call. 49 auto signal_callback_wrapper = [signal_callback](const Args&... args) { 50 if (!signal_callback.is_null()) { 51 signal_callback.Run(args...); 52 } 53 }; 54 55 dbus::MessageReader reader(signal); 56 DBusParamReader<false, Args...>::Invoke( 57 signal_callback_wrapper, &reader, nullptr); 58 }; 59 60 // Register our stub handler with D-Bus ObjectProxy. 61 object_proxy->ConnectToSignal(interface_name, 62 signal_name, 63 base::Bind(dbus_signal_callback, signal_callback), 64 on_connected_callback); 65 } 66 67 } // namespace dbus_utils 68 } // namespace brillo 69 70 #endif // LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_ 71