1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef WEBRTC_BASE_DBUS_H_
12 #define WEBRTC_BASE_DBUS_H_
13 
14 #ifdef HAVE_DBUS_GLIB
15 
16 #include <dbus/dbus.h>
17 
18 #include <string>
19 #include <vector>
20 
21 #include "webrtc/base/libdbusglibsymboltable.h"
22 #include "webrtc/base/messagehandler.h"
23 #include "webrtc/base/thread.h"
24 
25 namespace rtc {
26 
27 #define DBUS_TYPE                   "type"
28 #define DBUS_SIGNAL                 "signal"
29 #define DBUS_PATH                   "path"
30 #define DBUS_INTERFACE              "interface"
31 #define DBUS_MEMBER                 "member"
32 
33 #ifdef CHROMEOS
34 #define CROS_PM_PATH                "/"
35 #define CROS_PM_INTERFACE           "org.chromium.PowerManager"
36 #define CROS_SIG_POWERCHANGED       "PowerStateChanged"
37 #define CROS_VALUE_SLEEP            "mem"
38 #define CROS_VALUE_RESUME           "on"
39 #else
40 #define UP_PATH                     "/org/freedesktop/UPower"
41 #define UP_INTERFACE                "org.freedesktop.UPower"
42 #define UP_SIG_SLEEPING             "Sleeping"
43 #define UP_SIG_RESUMING             "Resuming"
44 #endif  // CHROMEOS
45 
46 // Wraps a DBus messages.
47 class DBusSigMessageData : public TypedMessageData<DBusMessage *> {
48  public:
49   explicit DBusSigMessageData(DBusMessage *message);
50   ~DBusSigMessageData();
51 };
52 
53 // DBusSigFilter is an abstract class that defines the interface of DBus
54 // signal handling.
55 // The subclasses implement ProcessSignal() for various purposes.
56 // When a DBus signal comes, a DSM_SIGNAL message is posted to the caller thread
57 // which will then invokes ProcessSignal().
58 class DBusSigFilter : protected MessageHandler {
59  public:
60   enum DBusSigMessage { DSM_SIGNAL };
61 
62   // This filter string should ususally come from BuildFilterString()
DBusSigFilter(const std::string & filter)63   explicit DBusSigFilter(const std::string &filter)
64       : caller_thread_(Thread::Current()), filter_(filter) {
65   }
66 
67   // Builds a DBus monitor filter string from given DBus path, interface, and
68   // member.
69   // See http://dbus.freedesktop.org/doc/api/html/group__DBusConnection.html
70   static std::string BuildFilterString(const std::string &path,
71                                        const std::string &interface,
72                                        const std::string &member);
73 
74   // Handles callback on DBus messages by DBus system.
75   static DBusHandlerResult DBusCallback(DBusConnection *dbus_conn,
76                                         DBusMessage *message,
77                                         void *instance);
78 
79   // Handles callback on DBus messages to each DBusSigFilter instance.
80   DBusHandlerResult Callback(DBusMessage *message);
81 
82   // From MessageHandler.
83   virtual void OnMessage(Message *message);
84 
85   // Returns the DBus monitor filter string.
filter()86   const std::string &filter() const { return filter_; }
87 
88  private:
89   // On caller thread.
90   virtual void ProcessSignal(DBusMessage *message) = 0;
91 
92   Thread *caller_thread_;
93   const std::string filter_;
94 };
95 
96 // DBusMonitor is a class for DBus signal monitoring.
97 //
98 // The caller-thread calls AddFilter() first to add the signals that it wants to
99 // monitor and then calls StartMonitoring() to start the monitoring.
100 // This will create a worker-thread which listens on DBus connection and sends
101 // DBus signals back through the callback.
102 // The worker-thread will be running forever until either StopMonitoring() is
103 // called from the caller-thread or the worker-thread hit some error.
104 //
105 // Programming model:
106 //   1. Caller-thread: Creates an object of DBusMonitor.
107 //   2. Caller-thread: Calls DBusMonitor::AddFilter() one or several times.
108 //   3. Caller-thread: StartMonitoring().
109 //      ...
110 //   4. Worker-thread: DBus signal recieved. Post a message to caller-thread.
111 //   5. Caller-thread: DBusFilterBase::ProcessSignal() is invoked.
112 //      ...
113 //   6. Caller-thread: StopMonitoring().
114 //
115 // Assumption:
116 //   AddFilter(), StartMonitoring(), and StopMonitoring() methods are called by
117 //   a single thread. Hence, there is no need to make them thread safe.
118 class DBusMonitor {
119  public:
120   // Status of DBus monitoring.
121   enum DBusMonitorStatus {
122     DMS_NOT_INITIALIZED,  // Not initialized.
123     DMS_INITIALIZING,     // Initializing the monitoring thread.
124     DMS_RUNNING,          // Monitoring.
125     DMS_STOPPED,          // Not monitoring. Stopped normally.
126     DMS_FAILED,           // Not monitoring. Failed.
127   };
128 
129   // Returns the DBus-Glib symbol table.
130   // We should only use this function to access DBus-Glib symbols.
131   static LibDBusGlibSymbolTable *GetDBusGlibSymbolTable();
132 
133   // Creates an instance of DBusMonitor.
134   static DBusMonitor *Create(DBusBusType type);
135   ~DBusMonitor();
136 
137   // Adds a filter to DBusMonitor.
138   bool AddFilter(DBusSigFilter *filter);
139 
140   // Starts DBus message monitoring.
141   bool StartMonitoring();
142 
143   // Stops DBus message monitoring.
144   bool StopMonitoring();
145 
146   // Gets the status of DBus monitoring.
147   DBusMonitorStatus GetStatus();
148 
149  private:
150   // Forward declaration. Defined in the .cc file.
151   class DBusMonitoringThread;
152 
153   explicit DBusMonitor(DBusBusType type);
154 
155   // Updates status_ when monitoring status has changed.
156   void OnMonitoringStatusChanged(DBusMonitorStatus status);
157 
158   DBusBusType type_;
159   DBusMonitorStatus status_;
160   DBusMonitoringThread *monitoring_thread_;
161   std::vector<DBusSigFilter *> filter_list_;
162 };
163 
164 }  // namespace rtc
165 
166 #endif  // HAVE_DBUS_GLIB
167 
168 #endif  // WEBRTC_BASE_DBUS_H_
169