Home | History | Annotate | Download | only in glib
      1 // Copyright (c) 2009 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_GLIB_DBUS_H_
      6 #define LIBBRILLO_BRILLO_GLIB_DBUS_H_
      7 
      8 // IMPORTANT: Do not use this in new code. Instead, use libchrome's D-Bus
      9 // bindings. See https://goo.gl/EH3MmR for more details.
     10 
     11 #include <dbus/dbus-glib.h>
     12 #include <glib-object.h>
     13 
     14 #include <algorithm>
     15 #include <string>
     16 
     17 #include "base/logging.h"
     18 #include <brillo/brillo_export.h>
     19 #include <brillo/glib/object.h>
     20 
     21 struct DBusMessage;
     22 struct DBusConnection;
     23 
     24 namespace brillo {
     25 
     26 namespace dbus {
     27 
     28 // \brief   BusConnection manages the ref-count for a ::DBusGConnection*.
     29 //
     30 // A BusConnection has reference semantics bound to a particular communication
     31 // bus.
     32 //
     33 // \models Copyable, Assignable
     34 // \related GetSystemBusConnection()
     35 
     36 class BRILLO_EXPORT BusConnection {
     37  public:
     38   typedef ::DBusGConnection* value_type;
     39 
     40   BusConnection(const BusConnection& x) : object_(x.object_) {
     41     if (object_)
     42       ::dbus_g_connection_ref(object_);
     43   }
     44 
     45   ~BusConnection() {
     46     if (object_)
     47       ::dbus_g_connection_unref(object_);
     48   }
     49 
     50   BusConnection& operator=(BusConnection x) {
     51     swap(*this, x);
     52     return *this;
     53   }
     54 
     55   const value_type& g_connection() const {
     56     DCHECK(object_) << "referencing an empty connection";
     57     return object_;
     58   }
     59 
     60   operator bool() const { return object_; }
     61 
     62   bool HasConnection() const { return object_; }
     63 
     64  private:
     65   friend void swap(BusConnection& x, BusConnection& y);
     66 
     67   friend class Proxy;
     68   friend BusConnection GetSystemBusConnection();
     69   friend BusConnection GetPrivateBusConnection(const char* address);
     70 
     71   // Constructor takes ownership
     72   BRILLO_PRIVATE explicit BusConnection(::DBusGConnection* x) : object_(x) {}
     73 
     74   value_type object_;
     75 };
     76 
     77 inline void swap(BusConnection& x, BusConnection& y) {
     78   std::swap(x.object_, y.object_);
     79 }
     80 
     81 // \brief Proxy manages the ref-count for a ::DBusGProxy*.
     82 //
     83 // Proxy has reference semantics and represents a connection to on object on
     84 // the bus. A proxy object is constructed with a connection to a bus, a name
     85 // to an entity on the bus, a path to an object owned by the entity, and an
     86 // interface protocol name used to communicate with the object.
     87 
     88 class BRILLO_EXPORT Proxy {
     89  public:
     90   typedef ::DBusGProxy* value_type;
     91 
     92   Proxy();
     93 
     94   // Set |connect_to_name_owner| true if you'd like to use
     95   // dbus_g_proxy_new_for_name_owner() rather than dbus_g_proxy_new_for_name().
     96   Proxy(const BusConnection& connection,
     97         const char* name,
     98         const char* path,
     99         const char* interface,
    100         bool connect_to_name_owner);
    101 
    102   // Equivalent to Proxy(connection, name, path, interface, false).
    103   Proxy(const BusConnection& connection,
    104         const char* name,
    105         const char* path,
    106         const char* interface);
    107 
    108   // Creates a peer proxy using dbus_g_proxy_new_for_peer.
    109   Proxy(const BusConnection& connection,
    110         const char* path,
    111         const char* interface);
    112 
    113   Proxy(const Proxy& x);
    114 
    115   ~Proxy();
    116 
    117   Proxy& operator=(Proxy x) {
    118     swap(*this, x);
    119     return *this;
    120   }
    121 
    122   const char* path() const {
    123     DCHECK(object_) << "referencing an empty proxy";
    124     return ::dbus_g_proxy_get_path(object_);
    125   }
    126 
    127   // gproxy() returns a reference to the underlying ::DBusGProxy*. As this
    128   // library evolves, the gproxy() will be moved to be private.
    129 
    130   const value_type& gproxy() const {
    131     DCHECK(object_) << "referencing an empty proxy";
    132     return object_;
    133   }
    134 
    135   operator bool() const { return object_; }
    136 
    137  private:
    138   BRILLO_PRIVATE static value_type GetGProxy(const BusConnection& connection,
    139                                              const char* name,
    140                                              const char* path,
    141                                              const char* interface,
    142                                              bool connect_to_name_owner);
    143 
    144   BRILLO_PRIVATE static value_type GetGPeerProxy(
    145       const BusConnection& connection,
    146       const char* path,
    147       const char* interface);
    148 
    149   BRILLO_PRIVATE operator int() const;  // for safe bool cast
    150   friend void swap(Proxy& x, Proxy& y);
    151 
    152   value_type object_;
    153 };
    154 
    155 inline void swap(Proxy& x, Proxy& y) {
    156   std::swap(x.object_, y.object_);
    157 }
    158 
    159 // \brief RegisterExclusiveService configures a GObject to run as a service on
    160 //  a supplied ::BusConnection.
    161 //
    162 //  RegisterExclusiveService encapsulates the process of configuring the
    163 //  supplied \param object at \param service_path on the \param connection.
    164 //  Exclusivity is ensured by replacing any existing services at that named
    165 //  location and confirming that the connection is the primary owner.
    166 //
    167 //  Type information for the \param object must be installed with
    168 //  dbus_g_object_type_install_info prior to use.
    169 
    170 BRILLO_EXPORT bool RegisterExclusiveService(const BusConnection& connection,
    171                                             const char* interface_name,
    172                                             const char* service_name,
    173                                             const char* service_path,
    174                                             GObject* object);
    175 
    176 template<typename F>  // F is a function signature
    177 class MonitorConnection;
    178 
    179 template<typename A1>
    180 class MonitorConnection<void(A1)> {
    181  public:
    182   MonitorConnection(const Proxy& proxy,
    183                     const char* name,
    184                     void (*monitor)(void*, A1),
    185                     void* object)
    186       : proxy_(proxy), name_(name), monitor_(monitor), object_(object) {}
    187 
    188   static void Run(::DBusGProxy*, A1 x, MonitorConnection* self) {
    189     self->monitor_(self->object_, x);
    190   }
    191   const Proxy& proxy() const { return proxy_; }
    192   const std::string& name() const { return name_; }
    193 
    194  private:
    195   Proxy proxy_;
    196   std::string name_;
    197   void (*monitor_)(void*, A1);
    198   void* object_;
    199 };
    200 
    201 template<typename A1, typename A2>
    202 class MonitorConnection<void(A1, A2)> {
    203  public:
    204   MonitorConnection(const Proxy& proxy,
    205                     const char* name,
    206                     void (*monitor)(void*, A1, A2),
    207                     void* object)
    208       : proxy_(proxy), name_(name), monitor_(monitor), object_(object) {}
    209 
    210   static void Run(::DBusGProxy*, A1 x, A2 y, MonitorConnection* self) {
    211     self->monitor_(self->object_, x, y);
    212   }
    213   const Proxy& proxy() const { return proxy_; }
    214   const std::string& name() const { return name_; }
    215 
    216  private:
    217   Proxy proxy_;
    218   std::string name_;
    219   void (*monitor_)(void*, A1, A2);
    220   void* object_;
    221 };
    222 
    223 template<typename A1, typename A2, typename A3>
    224 class MonitorConnection<void(A1, A2, A3)> {
    225  public:
    226   MonitorConnection(const Proxy& proxy,
    227                     const char* name,
    228                     void (*monitor)(void*, A1, A2, A3),
    229                     void* object)
    230       : proxy_(proxy), name_(name), monitor_(monitor), object_(object) {}
    231 
    232   static void Run(::DBusGProxy*, A1 x, A2 y, A3 z, MonitorConnection* self) {
    233     self->monitor_(self->object_, x, y, z);
    234   }
    235   const Proxy& proxy() const { return proxy_; }
    236   const std::string& name() const { return name_; }
    237 
    238  private:
    239   Proxy proxy_;
    240   std::string name_;
    241   void (*monitor_)(void*, A1, A2, A3);
    242   void* object_;
    243 };
    244 
    245 template<typename A1, typename A2, typename A3, typename A4>
    246 class MonitorConnection<void(A1, A2, A3, A4)> {
    247  public:
    248   MonitorConnection(const Proxy& proxy,
    249                     const char* name,
    250                     void (*monitor)(void*, A1, A2, A3, A4),
    251                     void* object)
    252       : proxy_(proxy), name_(name), monitor_(monitor), object_(object) {}
    253 
    254   static void Run(::DBusGProxy*,
    255                   A1 x,
    256                   A2 y,
    257                   A3 z,
    258                   A4 w,
    259                   MonitorConnection* self) {
    260     self->monitor_(self->object_, x, y, z, w);
    261   }
    262   const Proxy& proxy() const { return proxy_; }
    263   const std::string& name() const { return name_; }
    264 
    265  private:
    266   Proxy proxy_;
    267   std::string name_;
    268   void (*monitor_)(void*, A1, A2, A3, A4);
    269   void* object_;
    270 };
    271 
    272 template<typename A1>
    273 MonitorConnection<void(A1)>* Monitor(const Proxy& proxy,
    274                                      const char* name,
    275                                      void (*monitor)(void*, A1),
    276                                      void* object) {
    277   typedef MonitorConnection<void(A1)> ConnectionType;
    278 
    279   ConnectionType* result = new ConnectionType(proxy, name, monitor, object);
    280 
    281   ::dbus_g_proxy_add_signal(
    282       proxy.gproxy(), name, glib::type_to_gtypeid<A1>(), G_TYPE_INVALID);
    283   ::dbus_g_proxy_connect_signal(
    284       proxy.gproxy(), name, G_CALLBACK(&ConnectionType::Run), result, nullptr);
    285   return result;
    286 }
    287 
    288 template<typename A1, typename A2>
    289 MonitorConnection<void(A1, A2)>* Monitor(const Proxy& proxy,
    290                                          const char* name,
    291                                          void (*monitor)(void*, A1, A2),
    292                                          void* object) {
    293   typedef MonitorConnection<void(A1, A2)> ConnectionType;
    294 
    295   ConnectionType* result = new ConnectionType(proxy, name, monitor, object);
    296 
    297   ::dbus_g_proxy_add_signal(proxy.gproxy(),
    298                             name,
    299                             glib::type_to_gtypeid<A1>(),
    300                             glib::type_to_gtypeid<A2>(),
    301                             G_TYPE_INVALID);
    302   ::dbus_g_proxy_connect_signal(
    303       proxy.gproxy(), name, G_CALLBACK(&ConnectionType::Run), result, nullptr);
    304   return result;
    305 }
    306 
    307 template<typename A1, typename A2, typename A3>
    308 MonitorConnection<void(A1, A2, A3)>* Monitor(const Proxy& proxy,
    309                                              const char* name,
    310                                              void (*monitor)(void*, A1, A2, A3),
    311                                              void* object) {
    312   typedef MonitorConnection<void(A1, A2, A3)> ConnectionType;
    313 
    314   ConnectionType* result = new ConnectionType(proxy, name, monitor, object);
    315 
    316   ::dbus_g_proxy_add_signal(proxy.gproxy(),
    317                             name,
    318                             glib::type_to_gtypeid<A1>(),
    319                             glib::type_to_gtypeid<A2>(),
    320                             glib::type_to_gtypeid<A3>(),
    321                             G_TYPE_INVALID);
    322   ::dbus_g_proxy_connect_signal(
    323       proxy.gproxy(), name, G_CALLBACK(&ConnectionType::Run), result, nullptr);
    324   return result;
    325 }
    326 
    327 template<typename A1, typename A2, typename A3, typename A4>
    328 MonitorConnection<void(A1, A2, A3, A4)>* Monitor(
    329     const Proxy& proxy,
    330     const char* name,
    331     void (*monitor)(void*, A1, A2, A3, A4),
    332     void* object) {
    333   typedef MonitorConnection<void(A1, A2, A3, A4)> ConnectionType;
    334 
    335   ConnectionType* result = new ConnectionType(proxy, name, monitor, object);
    336 
    337   ::dbus_g_proxy_add_signal(proxy.gproxy(),
    338                             name,
    339                             glib::type_to_gtypeid<A1>(),
    340                             glib::type_to_gtypeid<A2>(),
    341                             glib::type_to_gtypeid<A3>(),
    342                             glib::type_to_gtypeid<A4>(),
    343                             G_TYPE_INVALID);
    344   ::dbus_g_proxy_connect_signal(
    345       proxy.gproxy(), name, G_CALLBACK(&ConnectionType::Run), result, nullptr);
    346   return result;
    347 }
    348 
    349 template<typename F>
    350 void Disconnect(MonitorConnection<F>* connection) {
    351   typedef MonitorConnection<F> ConnectionType;
    352 
    353   ::dbus_g_proxy_disconnect_signal(connection->proxy().gproxy(),
    354                                    connection->name().c_str(),
    355                                    G_CALLBACK(&ConnectionType::Run),
    356                                    connection);
    357   delete connection;
    358 }
    359 
    360 // \brief call_PtrArray() invokes a method on a proxy returning a
    361 //  glib::PtrArray.
    362 //
    363 // CallPtrArray is the first instance of what is likely to be a general
    364 // way to make method calls to a proxy. It will likely be replaced with
    365 // something like Call(proxy, method, arg1, arg2, ..., ResultType*) in the
    366 // future. However, I don't yet have enough cases to generalize from.
    367 
    368 BRILLO_EXPORT bool CallPtrArray(const Proxy& proxy,
    369                                   const char* method,
    370                                   glib::ScopedPtrArray<const char*>* result);
    371 
    372 // \brief RetrieveProperty() retrieves a property of an object associated with a
    373 //  proxy.
    374 //
    375 // Given a proxy to an object supporting the org.freedesktop.DBus.Properties
    376 // interface, the RetrieveProperty() call will retrieve a property of the
    377 // specified interface on the object storing it in \param result and returning
    378 // \true. If the dbus call fails or the object returned is not of type \param T,
    379 // then \false is returned and \param result is unchanged.
    380 //
    381 // \example
    382 // Proxy proxy(GetSystemBusConnection(),
    383 //             "org.freedesktop.DeviceKit.Power", // A named entity on the bus
    384 //             battery_name,  // Path to a battery on the bus
    385 //             "org.freedesktop.DBus.Properties") // Properties interface
    386 //
    387 // double x;
    388 // if (RetrieveProperty(proxy,
    389 //                      "org.freedesktop.DeviceKit.Power.Device",
    390 //                      "percentage")
    391 //   std::cout << "Battery charge is " << x << "% of capacity.";
    392 // \end_example
    393 
    394 template<typename T>
    395 inline bool RetrieveProperty(const Proxy& proxy,
    396                              const char* interface,
    397                              const char* property,
    398                              T* result) {
    399   glib::ScopedError error;
    400   glib::Value value;
    401 
    402   if (!::dbus_g_proxy_call(proxy.gproxy(), "Get", &Resetter(&error).lvalue(),
    403                            G_TYPE_STRING, interface,
    404                            G_TYPE_STRING, property,
    405                            G_TYPE_INVALID,
    406                            G_TYPE_VALUE, &value,
    407                            G_TYPE_INVALID)) {
    408     LOG(ERROR) << "Getting property failed: "
    409                << (error->message ? error->message : "Unknown Error.");
    410     return false;
    411   }
    412   return glib::Retrieve(value, result);
    413 }
    414 
    415 // \brief RetrieveProperties returns a HashTable of all properties for the
    416 // specified interface.
    417 
    418 BRILLO_EXPORT bool RetrieveProperties(const Proxy& proxy,
    419                                       const char* interface,
    420                                       glib::ScopedHashTable* result);
    421 
    422 // \brief Returns a connection to the system bus.
    423 
    424 BRILLO_EXPORT BusConnection GetSystemBusConnection();
    425 
    426 // \brief Returns a private connection to a bus at |address|.
    427 
    428 BRILLO_EXPORT BusConnection GetPrivateBusConnection(const char* address);
    429 
    430 // \brief Calls a method |method_name| with no arguments per the given |path|
    431 // and |interface_name|.  Ignores return value.
    432 
    433 BRILLO_EXPORT void CallMethodWithNoArguments(const char* service_name,
    434                                              const char* path,
    435                                              const char* interface_name,
    436                                              const char* method_name);
    437 
    438 // \brief Low-level signal monitor base class.
    439 //
    440 // Used when there is no definite named signal sender (that Proxy
    441 // could be used for).
    442 
    443 class BRILLO_EXPORT SignalWatcher {
    444  public:
    445   SignalWatcher() {}
    446   ~SignalWatcher();
    447   void StartMonitoring(const std::string& interface, const std::string& signal);
    448 
    449  private:
    450   // Callback invoked on the given signal arrival.
    451   virtual void OnSignal(DBusMessage* message) = 0;
    452 
    453   // Returns a string matching the D-Bus messages that we want to listen for.
    454   BRILLO_PRIVATE std::string GetDBusMatchString() const;
    455 
    456   // A D-Bus message filter to receive signals.
    457   BRILLO_PRIVATE static DBusHandlerResult FilterDBusMessage(
    458       DBusConnection* dbus_conn,
    459       DBusMessage* message,
    460       void* data);
    461   std::string interface_;
    462   std::string signal_;
    463 };
    464 
    465 }  // namespace dbus
    466 }  // namespace brillo
    467 
    468 #endif  // LIBBRILLO_BRILLO_GLIB_DBUS_H_
    469