| Index: dbus/bus.h
|
| diff --git a/dbus/bus.h b/dbus/bus.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..4796c65fc3fd04d09c0dcfababc313e6233e455a
|
| --- /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_
|
|
|