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