OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 The Chromium 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 DBUS_BUS_H_ | |
6 #define DBUS_BUS_H_ | |
7 #pragma once | |
8 | |
9 #include <set> | |
10 #include <string> | |
11 #include <dbus/dbus.h> | |
12 | |
13 #include "base/callback.h" | |
14 #include "base/memory/ref_counted.h" | |
15 #include "base/memory/scoped_ptr.h" | |
16 #include "base/tracked_objects.h" | |
17 | |
18 class MessageLoop; | |
19 | |
20 namespace base { | |
21 class Thread; | |
22 } | |
23 | |
24 namespace dbus { | |
25 | |
26 class ExportedObject; | |
27 class ObjectProxy; | |
28 | |
29 // Bus is used to establish a connection with D-Bus, create object | |
30 // proxies, and export objects. | |
31 // | |
32 // For asynchronous operations such as an asynchronous method call, the | |
33 // bus object will use a message loop to monitor the underlying file | |
34 // descriptor used for D-Bus communication. By default, the bus will use | |
35 // the current thread's MessageLoopForIO. If |dbus_thread| option is | |
36 // specified, the bus will use the D-Bus thread's message loop. | |
37 // | |
38 // THREADING | |
39 // | |
40 // In the D-Bus library, we use the two threads: | |
41 // | |
42 // - The origin thread: the thread that created the Bus object. | |
43 // - The D-Bus thread: the thread supplifed by |dbus_thread| option. | |
44 // | |
45 // The origin thread is usually Chrome's UI thread. The D-Bus thread is | |
46 // usually a dedicated thread for the D-Bus library. | |
47 // | |
48 // BLOCKING CALLS | |
49 // | |
50 // Functions that issue blocking calls are marked "BLOCKING CALL" and | |
51 // these functions should be called in the D-Bus thread (if | |
52 // supplied). AssertOnDBusThread() is placed in these functions. | |
53 // | |
54 // Note that it's hard to tell if a libdbus function is actually blocking | |
55 // or not (ex. dbus_bus_request_name() internally calls | |
56 // dbus_connection_send_with_reply_and_block(), which is a blocking | |
57 // call). To err on the side, we consider all libdbus functions that deal | |
58 // with the connection to dbus-damoen to be blocking. | |
59 // | |
60 // EXAMPLE USAGE: | |
61 // | |
62 // Synchronous method call: | |
63 // | |
64 // dbus::Bus::Options options; | |
65 // // Set up the bus options here. | |
66 // ... | |
67 // dbus::Bus bus(options); | |
68 // | |
69 // dbus::ObjectProxy* object_proxy = | |
70 // bus.GetObjectProxy(service_name, object_path); | |
71 // | |
72 // dbus::MethodCall method_call(interface_name, method_name); | |
73 // dbus::Response response; | |
74 // bool success = | |
75 // object_proxy.CallMethodAndBlock(&method_call, timeout_ms, &response); | |
76 // | |
77 // Asynchronous method call: | |
78 // | |
79 // void OnResponse(dbus::Response* response) { | |
80 // // response is NULL if the method call failed. | |
81 // if (!response) | |
82 // return; | |
83 // // Do something with response here, and delete it. | |
84 // delete response; | |
85 // } | |
86 // | |
87 // ... | |
88 // object_proxy.CallMethod(&method_call, timeout_ms, | |
89 // base::Bind(&OnResponse)); | |
90 // | |
91 // Exporting a method: | |
92 // | |
93 // Response* Echo(dbus::MethodCall* method_call) { | |
94 // // Do something with method_call. | |
95 // Response* response = Response::FromMethodCall(method_call); | |
96 // // Build response here. | |
97 // return response; | |
98 // } | |
99 // | |
100 // void OnExported(const std::string& interface_name, | |
101 // const std::string& object_path, | |
102 // bool success) { | |
103 // // success is true if the method was exported successfully. | |
104 // } | |
105 // | |
106 // ... | |
107 // dbus::ExportedObject* exported_object = | |
108 // bus.GetExportedObject(service_name, object_path); | |
109 // exported_object.ExportMethod(interface_name, method_name, | |
110 // base::Bind(&Echo), | |
111 // base::Bind(&OnExported)); | |
112 // | |
113 // WHY IS THIS A REF COUNTED OBJECT? | |
114 // | |
115 // Bus is a ref counted object, to ensure that |this| of the object is | |
116 // alive when callbacks referencing |this| are called. However, after | |
117 // Shutdown() is called, |connection_| can be NULL. Hence, calbacks should | |
118 // not rely on that |connection_| is alive. | |
119 class Bus : public base::RefCountedThreadSafe<Bus> { | |
120 public: | |
121 // Specifies the bus type. SESSION is used to communicate with per-user | |
122 // services like GNOME applications. SYSTEM is used to communicate with | |
123 // system-wide services like NetworkManager. | |
124 enum BusType { | |
125 SESSION = DBUS_BUS_SESSION, | |
126 SYSTEM = DBUS_BUS_SYSTEM, | |
127 }; | |
128 | |
129 // Specifies the connection type. PRIVATE should usually be used unless | |
130 // you are sure that SHARED is safe for you, which is unlikely the case | |
131 // in Chrome. | |
132 // | |
133 // PRIVATE gives you a private connection, that won't be shared with | |
134 // other Bus objects. | |
135 // | |
136 // SHARED gives you a connection shared among other Bus objects, which | |
137 // is unsafe if the connection is shared with multiple threads. | |
138 enum ConnectionType { | |
139 PRIVATE, | |
140 SHARED, | |
141 }; | |
142 | |
143 // Options used to create a Bus object. | |
144 struct Options { | |
145 Options(); | |
146 ~Options(); | |
stevenjb
2011/08/10 19:40:07
nit: a struct shouldn't need a destructor, and I f
satorux1
2011/08/10 21:14:27
I agree with you that it'd be nicer to inline the
stevenjb
2011/08/10 21:31:18
Meh. I didn't realize clang would trigger on numbe
| |
147 | |
148 BusType bus_type; // SESSION by default. | |
149 ConnectionType connection_type; // PRIVATE by default. | |
150 // If the thread is set, the bus object will use the message loop | |
151 // attached to the thread to process asynchronous operations. | |
152 // | |
153 // The thread should meet the following requirements: | |
154 // 1) Already running. | |
155 // 2) Has a MessageLoopForIO. | |
156 // 3) Outlives the bus. | |
157 base::Thread* dbus_thread; // NULL by default. | |
158 }; | |
159 | |
160 // Called when shutdown is done. Used for Shutdown(). | |
161 typedef base::Callback<void ()> OnShutdownCallback; | |
162 | |
163 // Creates a Bus object. The actual connection will be established when | |
164 // Connect() is called. | |
165 explicit Bus(const Options& options); | |
166 | |
167 // Gets the object proxy for the given service name and the object path. | |
168 // The caller must not delete the returned object. The bus will own the | |
169 // object. Never returns NULL. | |
170 // | |
171 // The object proxy is used to call remote methods. | |
172 // | |
173 // |service_name| looks like "org.freedesktop.NetworkManager", and | |
174 // |object_path| looks like "/org/freedesktop/NetworkManager/Devices/0". | |
175 // | |
176 // Must be called in the origin thread. | |
177 virtual ObjectProxy* GetObjectProxy(const std::string& service_name, | |
178 const std::string& object_path); | |
179 | |
180 // Gets the exported object for the given service name and the object | |
181 // path. The caller must not delete the returned object. The bus will | |
182 // own the object. Never returns NULL. | |
183 // | |
184 // The exported object is used to export objects to other D-Bus clients. | |
185 // | |
186 // Must be called in the origin thread. | |
187 virtual ExportedObject* GetExportedObject(const std::string& service_name, | |
188 const std::string& object_path); | |
189 | |
190 // Shutdowns the bus and blocks until it's done. More specifically, this | |
stevenjb
2011/08/10 19:40:07
nit: Shuts down
satorux1
2011/08/10 21:14:27
Done.
| |
191 // function does the followings: | |
stevenjb
2011/08/10 19:40:07
nit: following
satorux1
2011/08/10 21:14:27
Done.
| |
192 // | |
193 // - Unregisters the object paths | |
194 // - Releases the service names | |
195 // - Close the connection to dbus-daemon. | |
stevenjb
2011/08/10 19:40:07
nit: Closes
satorux1
2011/08/10 21:14:27
Done.
| |
196 // | |
197 // BLOCKING CALL. | |
198 virtual void ShutdownAndBlock(); | |
199 | |
200 // Shutdowns the bus in the D-Bus thread. |callback| will be called in | |
stevenjb
2011/08/10 19:40:07
nit: Shuts down
satorux1
2011/08/10 21:14:27
Done.
| |
201 // the origin thread. | |
202 // | |
203 // Must be called in the origin thread. | |
204 virtual void Shutdown(OnShutdownCallback callback); | |
205 | |
206 // | |
207 // The public functions below are not intended to be used in client | |
208 // code. These are used to implement ObjectProxy and ExportedObject. | |
209 // | |
210 | |
211 // Connects the bus to the dbus-daemon. | |
212 // Returns true on success, or the bus is already connected. | |
213 // | |
214 // BLOCKING CALL. | |
215 virtual bool Connect(); | |
216 | |
217 // Requests the ownership of the given service name. | |
218 // Returns true on success, or the the service name is already obtained. | |
219 // | |
220 // BLOCKING CALL. | |
221 virtual bool RequestOwnership(const std::string& service_name); | |
222 | |
223 // Releases the ownership of the given service name. | |
224 // Returns true on success. | |
225 // | |
226 // BLOCKING CALL. | |
227 virtual bool ReleaseOwnership(const std::string& service_name); | |
228 | |
229 // Sets up async operations. | |
230 // Returns true on success, or it's already set up. | |
231 // This function needs to be called before starting async operations. | |
232 // | |
233 // BLOCKING CALL. | |
234 virtual bool SetUpAsyncOperations(); | |
235 | |
236 // Sends a message to the bus and blocks until the response is | |
237 // received. Used to implement synchronous method calls. | |
238 // | |
239 // BLOCKING CALL. | |
240 virtual DBusMessage* SendWithReplyAndBlock(DBusMessage* request, | |
241 int timeout_ms, | |
242 DBusError* error); | |
243 | |
244 // Requests to send a message to the bus. | |
245 // | |
246 // BLOCKING CALL. | |
247 virtual void SendWithReply(DBusMessage* request, | |
248 DBusPendingCall** pending_call, | |
249 int timeout_ms); | |
250 | |
251 // Tries to register the object path. | |
252 // | |
253 // BLOCKING CALL. | |
254 virtual bool TryRegisterObjectPath(const std::string& object_path, | |
255 const DBusObjectPathVTable* vtable, | |
256 void* user_data, | |
257 DBusError* error); | |
258 | |
259 // Unregister the object path. | |
260 // | |
261 // BLOCKING CALL. | |
262 virtual bool UnregisterObjectPath(const std::string& object_path); | |
263 | |
264 // Posts the task to the message loop of the thread that created the bus. | |
265 virtual void PostTaskToOriginThread( | |
266 const tracked_objects::Location& from_here, | |
267 const base::Closure& task); | |
268 | |
269 // Posts the task to the message loop of the D-Bus thread. If D-Bus | |
270 // thread is not supplied, the message loop of the origin thread will be | |
271 // used. | |
272 virtual void PostTaskToDBusThread( | |
273 const tracked_objects::Location& from_here, | |
274 const base::Closure& task); | |
275 | |
276 // Posts the delayed task to the message loop of the D-Bus thread. If | |
277 // D-Bus thread is not supplied, the message loop of the origin thread | |
278 // will be used. | |
279 virtual void PostDelayedTaskToDBusThread( | |
280 const tracked_objects::Location& from_here, | |
281 const base::Closure& task, | |
282 int delay_ms); | |
283 | |
284 // Check whether the current thread is on the origin thread (the thread | |
285 // that created the bus). If not, DCHECK will fail. | |
286 virtual void AssertOnOriginThread(); | |
287 | |
288 // Check whether the current thread is on the D-Bus thread. If not, | |
289 // DCHECK will fail. If the D-Bus thread is not supplied, it calls | |
290 // AssertOnOriginThread(). | |
291 virtual void AssertOnDBusThread(); | |
292 | |
293 // Returns true if the bus has the D-Bus thread. | |
294 virtual bool has_dbus_thread() { return dbus_thread_ != NULL; } | |
295 | |
296 private: | |
297 friend class base::RefCountedThreadSafe<Bus>; | |
298 virtual ~Bus(); | |
299 | |
300 // Helper function used for Shutdown(). | |
301 void ShutdownInternal(OnShutdownCallback callback); | |
302 | |
303 // Processes the all incoming data to the connection, if any. | |
304 // | |
305 // BLOCKING CALL. | |
306 void ProcessAllIncomingDataIfAny(); | |
307 | |
308 // Called when a watch object is added. Used to start monitoring the | |
309 // file descriptor used for D-Bus communication. | |
310 dbus_bool_t OnAddWatch(DBusWatch* raw_watch); | |
311 | |
312 // Called when a watch object is removed. | |
313 void OnRemoveWatch(DBusWatch* raw_watch); | |
314 | |
315 // Called when the "enabled" status of |raw_watch| is toggled. | |
316 void OnToggleWatch(DBusWatch* raw_watch); | |
317 | |
318 // Called when a timeout object is added. Used to start monitoring | |
319 // timeout for method calls. | |
320 dbus_bool_t OnAddTimeout(DBusTimeout* raw_timeout); | |
321 | |
322 // Called when a timeout object is removed. | |
323 void OnRemoveTimeout(DBusTimeout* raw_timeout); | |
324 | |
325 // Called when the "enabled" status of |raw_timeout| is toggled. | |
326 void OnToggleTimeout(DBusTimeout* raw_timeout); | |
327 | |
328 // Called when the dispatch status (i.e. if any incoming data is | |
329 // available) is changed. | |
330 void OnDispatchStatusChanged(DBusConnection* connection, | |
331 DBusDispatchStatus status); | |
332 | |
333 // Callback helper functions. Redirects to the corresponding member function. | |
334 static dbus_bool_t OnAddWatchThunk(DBusWatch* raw_watch, void* data); | |
335 static void OnRemoveWatchThunk(DBusWatch* raw_watch, void* data); | |
336 static void OnToggleWatchThunk(DBusWatch* raw_watch, void* data); | |
337 static dbus_bool_t OnAddTimeoutThunk(DBusTimeout* raw_timeout, void* data); | |
338 static void OnRemoveTimeoutThunk(DBusTimeout* raw_timeout, void* data); | |
339 static void OnToggleTimeoutThunk(DBusTimeout* raw_timeout, void* data); | |
340 static void OnDispatchStatusChangedThunk(DBusConnection* connection, | |
341 DBusDispatchStatus status, | |
342 void* data); | |
stevenjb
2011/08/10 19:40:07
Can these be declared in a local namespace inside
satorux1
2011/08/10 21:14:27
These need to be static member functions, as these
stevenjb
2011/08/10 21:31:18
That makes sense.
| |
343 const BusType bus_type_; | |
344 const ConnectionType connection_type_; | |
345 base::Thread* dbus_thread_; | |
346 DBusConnection* connection_; | |
347 | |
348 MessageLoop* origin_loop_; | |
349 base::PlatformThreadId origin_thread_id_; | |
350 base::PlatformThreadId dbus_thread_id_; | |
351 | |
352 std::set<std::string> owned_service_names_; | |
353 std::vector<dbus::ObjectProxy*> object_proxies_; | |
354 std::vector<dbus::ExportedObject*> exported_objects_; | |
355 | |
356 bool async_operations_are_set_up_; | |
357 | |
358 DISALLOW_COPY_AND_ASSIGN(Bus); | |
359 }; | |
360 | |
361 } // namespace dbus | |
362 | |
363 #endif // DBUS_BUS_H_ | |
OLD | NEW |