Home | History | Annotate | Download | only in dbus
      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