summaryrefslogtreecommitdiffstats
path: root/dbus/bus.h
diff options
context:
space:
mode:
authorsatorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-17 20:58:12 +0000
committersatorux@chromium.org <satorux@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-17 20:58:12 +0000
commita510761104333ec7da3943399f059ff693839856 (patch)
tree2a9f81a60bccf4db3367ad1b8f71e9ea130efb7d /dbus/bus.h
parent07f93af15169ee054552a376ac4953abd1346cb2 (diff)
downloadchromium_src-a510761104333ec7da3943399f059ff693839856.zip
chromium_src-a510761104333ec7da3943399f059ff693839856.tar.gz
chromium_src-a510761104333ec7da3943399f059ff693839856.tar.bz2
Implement Bus and ObjectProxy classes for our D-Bus library.
ObjectProxy is used to access remote objects. ExportedObject is used to export objects to other D-Bus BUG=90036 TEST=run unit tests. The code is not yet used in Chrome. Review URL: http://codereview.chromium.org/7491029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97204 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'dbus/bus.h')
-rw-r--r--dbus/bus.h367
1 files changed, 367 insertions, 0 deletions
diff --git a/dbus/bus.h b/dbus/bus.h
new file mode 100644
index 0000000..4796c65
--- /dev/null
+++ b/dbus/bus.h
@@ -0,0 +1,367 @@
+
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DBUS_BUS_H_
+#define DBUS_BUS_H_
+#pragma once
+
+#include <set>
+#include <string>
+#include <dbus/dbus.h>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/tracked_objects.h"
+
+class MessageLoop;
+
+namespace base {
+class Thread;
+}
+
+namespace dbus {
+
+class ExportedObject;
+class ObjectProxy;
+
+// Bus is used to establish a connection with D-Bus, create object
+// proxies, and export objects.
+//
+// For asynchronous operations such as an asynchronous method call, the
+// bus object will use a message loop to monitor the underlying file
+// descriptor used for D-Bus communication. By default, the bus will use
+// the current thread's MessageLoopForIO. If |dbus_thread| option is
+// specified, the bus will use the D-Bus thread's message loop.
+//
+// THREADING
+//
+// In the D-Bus library, we use the two threads:
+//
+// - The origin thread: the thread that created the Bus object.
+// - The D-Bus thread: the thread supplifed by |dbus_thread| option.
+//
+// The origin thread is usually Chrome's UI thread. The D-Bus thread is
+// usually a dedicated thread for the D-Bus library.
+//
+// BLOCKING CALLS
+//
+// Functions that issue blocking calls are marked "BLOCKING CALL" and
+// these functions should be called in the D-Bus thread (if
+// supplied). AssertOnDBusThread() is placed in these functions.
+//
+// Note that it's hard to tell if a libdbus function is actually blocking
+// or not (ex. dbus_bus_request_name() internally calls
+// dbus_connection_send_with_reply_and_block(), which is a blocking
+// call). To err on the side, we consider all libdbus functions that deal
+// with the connection to dbus-damoen to be blocking.
+//
+// EXAMPLE USAGE:
+//
+// Synchronous method call:
+//
+// dbus::Bus::Options options;
+// // Set up the bus options here.
+// ...
+// dbus::Bus bus(options);
+//
+// dbus::ObjectProxy* object_proxy =
+// bus.GetObjectProxy(service_name, object_path);
+//
+// dbus::MethodCall method_call(interface_name, method_name);
+// dbus::Response response;
+// bool success =
+// object_proxy.CallMethodAndBlock(&method_call, timeout_ms, &response);
+//
+// Asynchronous method call:
+//
+// void OnResponse(dbus::Response* response) {
+// // response is NULL if the method call failed.
+// if (!response)
+// return;
+// }
+//
+// ...
+// object_proxy.CallMethod(&method_call, timeout_ms,
+// base::Bind(&OnResponse));
+//
+// Exporting a method:
+//
+// Response* Echo(dbus::MethodCall* method_call) {
+// // Do something with method_call.
+// Response* response = Response::FromMethodCall(method_call);
+// // Build response here.
+// return response;
+// }
+//
+// void OnExported(const std::string& interface_name,
+// const std::string& object_path,
+// bool success) {
+// // success is true if the method was exported successfully.
+// }
+//
+// ...
+// dbus::ExportedObject* exported_object =
+// bus.GetExportedObject(service_name, object_path);
+// exported_object.ExportMethod(interface_name, method_name,
+// base::Bind(&Echo),
+// base::Bind(&OnExported));
+//
+// WHY IS THIS A REF COUNTED OBJECT?
+//
+// Bus is a ref counted object, to ensure that |this| of the object is
+// alive when callbacks referencing |this| are called. However, after
+// Shutdown() is called, |connection_| can be NULL. Hence, calbacks should
+// not rely on that |connection_| is alive.
+class Bus : public base::RefCountedThreadSafe<Bus> {
+ public:
+ // Specifies the bus type. SESSION is used to communicate with per-user
+ // services like GNOME applications. SYSTEM is used to communicate with
+ // system-wide services like NetworkManager.
+ enum BusType {
+ SESSION = DBUS_BUS_SESSION,
+ SYSTEM = DBUS_BUS_SYSTEM,
+ };
+
+ // Specifies the connection type. PRIVATE should usually be used unless
+ // you are sure that SHARED is safe for you, which is unlikely the case
+ // in Chrome.
+ //
+ // PRIVATE gives you a private connection, that won't be shared with
+ // other Bus objects.
+ //
+ // SHARED gives you a connection shared among other Bus objects, which
+ // is unsafe if the connection is shared with multiple threads.
+ enum ConnectionType {
+ PRIVATE,
+ SHARED,
+ };
+
+ // Options used to create a Bus object.
+ struct Options {
+ Options();
+ ~Options();
+
+ BusType bus_type; // SESSION by default.
+ ConnectionType connection_type; // PRIVATE by default.
+ // If the thread is set, the bus object will use the message loop
+ // attached to the thread to process asynchronous operations.
+ //
+ // The thread should meet the following requirements:
+ // 1) Already running.
+ // 2) Has a MessageLoopForIO.
+ // 3) Outlives the bus.
+ base::Thread* dbus_thread; // NULL by default.
+ };
+
+ // Called when shutdown is done. Used for Shutdown().
+ typedef base::Callback<void ()> OnShutdownCallback;
+
+ // Creates a Bus object. The actual connection will be established when
+ // Connect() is called.
+ explicit Bus(const Options& options);
+
+ // Gets the object proxy for the given service name and the object path.
+ // The caller must not delete the returned object. The bus will own the
+ // object. Never returns NULL.
+ //
+ // The object proxy is used to call remote methods.
+ //
+ // |service_name| looks like "org.freedesktop.NetworkManager", and
+ // |object_path| looks like "/org/freedesktop/NetworkManager/Devices/0".
+ //
+ // Must be called in the origin thread.
+ virtual ObjectProxy* GetObjectProxy(const std::string& service_name,
+ const std::string& object_path);
+
+ // Gets the exported object for the given service name and the object
+ // path. The caller must not delete the returned object. The bus will
+ // own the object. Never returns NULL.
+ //
+ // The exported object is used to export objects to other D-Bus clients.
+ //
+ // Must be called in the origin thread.
+ virtual ExportedObject* GetExportedObject(const std::string& service_name,
+ const std::string& object_path);
+
+ // Shuts down the bus and blocks until it's done. More specifically, this
+ // function does the following:
+ //
+ // - Unregisters the object paths
+ // - Releases the service names
+ // - Closes the connection to dbus-daemon.
+ //
+ // BLOCKING CALL.
+ virtual void ShutdownAndBlock();
+
+ // Shuts down the bus in the D-Bus thread. |callback| will be called in
+ // the origin thread.
+ //
+ // Must be called in the origin thread.
+ virtual void Shutdown(OnShutdownCallback callback);
+
+ //
+ // The public functions below are not intended to be used in client
+ // code. These are used to implement ObjectProxy and ExportedObject.
+ //
+
+ // Connects the bus to the dbus-daemon.
+ // Returns true on success, or the bus is already connected.
+ //
+ // BLOCKING CALL.
+ virtual bool Connect();
+
+ // Requests the ownership of the given service name.
+ // Returns true on success, or the the service name is already obtained.
+ //
+ // BLOCKING CALL.
+ virtual bool RequestOwnership(const std::string& service_name);
+
+ // Releases the ownership of the given service name.
+ // Returns true on success.
+ //
+ // BLOCKING CALL.
+ virtual bool ReleaseOwnership(const std::string& service_name);
+
+ // Sets up async operations.
+ // Returns true on success, or it's already set up.
+ // This function needs to be called before starting async operations.
+ //
+ // BLOCKING CALL.
+ virtual bool SetUpAsyncOperations();
+
+ // Sends a message to the bus and blocks until the response is
+ // received. Used to implement synchronous method calls.
+ //
+ // BLOCKING CALL.
+ virtual DBusMessage* SendWithReplyAndBlock(DBusMessage* request,
+ int timeout_ms,
+ DBusError* error);
+
+ // Requests to send a message to the bus.
+ //
+ // BLOCKING CALL.
+ virtual void SendWithReply(DBusMessage* request,
+ DBusPendingCall** pending_call,
+ int timeout_ms);
+
+ // Tries to register the object path.
+ //
+ // BLOCKING CALL.
+ virtual bool TryRegisterObjectPath(const std::string& object_path,
+ const DBusObjectPathVTable* vtable,
+ void* user_data,
+ DBusError* error);
+
+ // Unregister the object path.
+ //
+ // BLOCKING CALL.
+ virtual void UnregisterObjectPath(const std::string& object_path);
+
+ // Posts the task to the message loop of the thread that created the bus.
+ virtual void PostTaskToOriginThread(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task);
+
+ // Posts the task to the message loop of the D-Bus thread. If D-Bus
+ // thread is not supplied, the message loop of the origin thread will be
+ // used.
+ virtual void PostTaskToDBusThread(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task);
+
+ // Posts the delayed task to the message loop of the D-Bus thread. If
+ // D-Bus thread is not supplied, the message loop of the origin thread
+ // will be used.
+ virtual void PostDelayedTaskToDBusThread(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ int delay_ms);
+
+ // Returns true if the bus has the D-Bus thread.
+ virtual bool HasDBusThread();
+
+ // Check whether the current thread is on the origin thread (the thread
+ // that created the bus). If not, DCHECK will fail.
+ virtual void AssertOnOriginThread();
+
+ // Check whether the current thread is on the D-Bus thread. If not,
+ // DCHECK will fail. If the D-Bus thread is not supplied, it calls
+ // AssertOnOriginThread().
+ virtual void AssertOnDBusThread();
+
+ private:
+ friend class base::RefCountedThreadSafe<Bus>;
+ virtual ~Bus();
+
+ // Helper function used for Shutdown().
+ void ShutdownInternal(OnShutdownCallback callback);
+
+ // Processes the all incoming data to the connection, if any.
+ //
+ // BLOCKING CALL.
+ void ProcessAllIncomingDataIfAny();
+
+ // Called when a watch object is added. Used to start monitoring the
+ // file descriptor used for D-Bus communication.
+ dbus_bool_t OnAddWatch(DBusWatch* raw_watch);
+
+ // Called when a watch object is removed.
+ void OnRemoveWatch(DBusWatch* raw_watch);
+
+ // Called when the "enabled" status of |raw_watch| is toggled.
+ void OnToggleWatch(DBusWatch* raw_watch);
+
+ // Called when a timeout object is added. Used to start monitoring
+ // timeout for method calls.
+ dbus_bool_t OnAddTimeout(DBusTimeout* raw_timeout);
+
+ // Called when a timeout object is removed.
+ void OnRemoveTimeout(DBusTimeout* raw_timeout);
+
+ // Called when the "enabled" status of |raw_timeout| is toggled.
+ void OnToggleTimeout(DBusTimeout* raw_timeout);
+
+ // Called when the dispatch status (i.e. if any incoming data is
+ // available) is changed.
+ void OnDispatchStatusChanged(DBusConnection* connection,
+ DBusDispatchStatus status);
+
+ // Callback helper functions. Redirects to the corresponding member function.
+ static dbus_bool_t OnAddWatchThunk(DBusWatch* raw_watch, void* data);
+ static void OnRemoveWatchThunk(DBusWatch* raw_watch, void* data);
+ static void OnToggleWatchThunk(DBusWatch* raw_watch, void* data);
+ static dbus_bool_t OnAddTimeoutThunk(DBusTimeout* raw_timeout, void* data);
+ static void OnRemoveTimeoutThunk(DBusTimeout* raw_timeout, void* data);
+ static void OnToggleTimeoutThunk(DBusTimeout* raw_timeout, void* data);
+ static void OnDispatchStatusChangedThunk(DBusConnection* connection,
+ DBusDispatchStatus status,
+ void* data);
+ const BusType bus_type_;
+ const ConnectionType connection_type_;
+ base::Thread* dbus_thread_;
+ DBusConnection* connection_;
+
+ MessageLoop* origin_loop_;
+ base::PlatformThreadId origin_thread_id_;
+ base::PlatformThreadId dbus_thread_id_;
+
+ std::set<std::string> owned_service_names_;
+ std::vector<scoped_refptr<dbus::ObjectProxy> > object_proxies_;
+ std::vector<scoped_refptr<dbus::ExportedObject> > exported_objects_;
+
+ bool async_operations_are_set_up_;
+
+ // Counters to make sure that OnAddWatch()/OnRemoveWatch() and
+ // OnAddTimeout()/OnRemoveTimeou() are balanced.
+ int num_pending_watches_;
+ int num_pending_timeouts_;
+
+ DISALLOW_COPY_AND_ASSIGN(Bus);
+};
+
+} // namespace dbus
+
+#endif // DBUS_BUS_H_