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
25namespace 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.
47class 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().
58class DBusSigFilter : protected MessageHandler {
59 public:
60  enum DBusSigMessage { DSM_SIGNAL };
61
62  // This filter string should ususally come from BuildFilterString()
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.
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.
118class 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