| // Copyright 2014 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_ |
| #define LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_ |
| |
| #include <functional> |
| #include <string> |
| |
| #include <brillo/bind_lambda.h> |
| #include <brillo/dbus/dbus_param_reader.h> |
| #include <dbus/message.h> |
| #include <dbus/object_proxy.h> |
| |
| namespace brillo { |
| namespace dbus_utils { |
| |
| // brillo::dbus_utils::ConnectToSignal() is a helper function similar to |
| // dbus::ObjectProxy::ConnectToSignal() but the |signal_callback| is an actual |
| // C++ signal handler with expected signal parameters as native method args. |
| // |
| // brillo::dbus_utils::ConnectToSignal() actually registers a stub signal |
| // handler with D-Bus which has a standard signature that matches |
| // dbus::ObjectProxy::SignalCallback. |
| // |
| // When a D-Bus signal is emitted, the stub handler is invoked, which unpacks |
| // the expected parameters from dbus::Signal message and then calls |
| // |signal_callback| with unpacked arguments. |
| // |
| // If the signal message doesn't contain correct number or types of arguments, |
| // an error message is logged to the system log and the signal is ignored |
| // (|signal_callback| is not invoked). |
| template<typename... Args> |
| void ConnectToSignal( |
| dbus::ObjectProxy* object_proxy, |
| const std::string& interface_name, |
| const std::string& signal_name, |
| base::Callback<void(Args...)> signal_callback, |
| dbus::ObjectProxy::OnConnectedCallback on_connected_callback) { |
| // Raw signal handler stub method. When called, unpacks the signal arguments |
| // from |signal| message buffer and redirects the call to |
| // |signal_callback_wrapper| which, in turn, would call the user-provided |
| // |signal_callback|. |
| auto dbus_signal_callback = []( |
| const base::Callback<void(Args...)>& signal_callback, |
| dbus::Signal* signal) { |
| // DBusParamReader::Invoke() needs a functor object, not a base::Callback. |
| // Wrap the callback with lambda so we can redirect the call. |
| auto signal_callback_wrapper = [signal_callback](const Args&... args) { |
| if (!signal_callback.is_null()) { |
| signal_callback.Run(args...); |
| } |
| }; |
| |
| dbus::MessageReader reader(signal); |
| DBusParamReader<false, Args...>::Invoke( |
| signal_callback_wrapper, &reader, nullptr); |
| }; |
| |
| // Register our stub handler with D-Bus ObjectProxy. |
| object_proxy->ConnectToSignal( |
| interface_name, |
| signal_name, |
| base::Bind(dbus_signal_callback, signal_callback), |
| on_connected_callback); |
| } |
| |
| } // namespace dbus_utils |
| } // namespace brillo |
| |
| #endif // LIBBRILLO_BRILLO_DBUS_DBUS_SIGNAL_HANDLER_H_ |