Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2908)

Unified Diff: dbus/bus.cc

Issue 7491029: Implement Bus and ObjectProxy classes for our D-Bus library. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: work-in-progress Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« dbus/bus.h ('K') | « dbus/bus.h ('k') | dbus/dbus.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dbus/bus.cc
diff --git a/dbus/bus.cc b/dbus/bus.cc
new file mode 100644
index 0000000000000000000000000000000000000000..b71ce5ad086e4870939bd2c51bfd0261e8c27c88
--- /dev/null
+++ b/dbus/bus.cc
@@ -0,0 +1,234 @@
+// 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.
+
+#include "dbus/bus.h"
+
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
+#include "dbus/object_proxy.h"
+
+namespace dbus {
+
+namespace {
+
+// The class is used for watching the file descriptor used for D-Bus
+// communication.
+class Watch : public base::MessagePumpLibevent::Watcher {
+ public:
+ Watch(DBusWatch* watch)
+ : raw_watch_(watch) {
+ dbus_watch_set_data(raw_watch_, this, NULL);
+ }
+
+ ~Watch() {
+ dbus_watch_set_data(raw_watch_, NULL, NULL);
+ }
+
+ // Returns true if the underlying file descriptor is ready to be watched.
+ bool IsReadyToBeWatched() {
+ return dbus_watch_get_enabled(raw_watch_);
+ }
+
+ // Starts watching the underlying file descriptor.
+ void StartWatching() {
+ const int fd = dbus_watch_get_unix_fd(raw_watch_);
+ const int flags = dbus_watch_get_flags(raw_watch_);
+
+ MessageLoopForIO::Mode mode;
+ if ((flags & DBUS_WATCH_READABLE) && (flags & DBUS_WATCH_WRITABLE))
+ mode = MessageLoopForIO::WATCH_READ_WRITE;
+ if (flags & DBUS_WATCH_READABLE)
stevenjb 2011/07/29 21:54:17 else if
satorux1 2011/08/01 19:56:41 Done.
+ mode = MessageLoopForIO::WATCH_READ;
+ if (flags & DBUS_WATCH_WRITABLE)
stevenjb 2011/07/29 21:54:17 else if
satorux1 2011/08/01 19:56:41 Done.
+ mode = MessageLoopForIO::WATCH_WRITE;
stevenjb 2011/07/29 21:54:17 else NOTREACHED()
satorux1 2011/08/01 19:56:41 Done.
+
+ const bool persistent = true; // Watch persistently.
+ const bool success = MessageLoopForIO::current()->WatchFileDescriptor(
+ fd,
+ persistent,
+ mode,
+ &file_descriptor_watcher_,
+ this);
+ DCHECK(success) << "Unable to allocate memory";
+ }
+
+ // Stops watching the underlying file descriptor.
+ void StopWatching() {
+ file_descriptor_watcher_->StopWatchingFileDescriptor();
+ }
+
+ private:
+ // Implement MessagePumpLibevent::Watcher.
+ virtual void OnFileCanReadWithoutBlocking(int fd) {
+ const bool success = dbus_watch_handle(raw_watch_, DBUS_WATCH_READABLE);
+ DCHECK(success) << "Unable to allocate memory";
+ }
+
+ // Implement MessagePumpLibevent::Watcher.
+ virtual void OnFileCanWriteWithoutBlocking(int fd) {
+ const bool success = dbus_watch_handle(raw_watch_, DBUS_WATCH_WRITABLE);
+ DCHECK(success) << "Unable to allocate memory";
+ }
+
+ DBusWatch* raw_watch_;
+ base::MessagePumpLibevent::FileDescriptorWatcher file_descriptor_watcher_;
+};
+
+} // namespace
+
+Bus::Options::Options()
+ : bus_type(SESSION),
+ connection_type(PRIVATE),
+ io_thread(NULL) {
+}
+
+Bus::Bus(const Options& options)
+ : bus_type_(options.bus_type),
+ connection_type_(options.connection_type),
+ io_thread_(options.io_thread),
+ connection_(NULL) {
+ if (io_thread_) {
+ DCHECK(io_thread_->IsRunning())
+ << "The IO thread should be running";
+ DCHECK_EQ(MessageLoop::TYPE_IO,
+ io_thread_->message_loop()->type())
+ << "The IO thread should have an MessageLoopForIO attached";
+ }
+}
+
+Bus::~Bus() {
+ // Private connection should be closed.
+ if (connection_ && connection_type_ == PRIVATE) {
+ dbus_connection_close(connection_);
+ }
+}
+
+ObjectProxy* Bus::GetObjectProxy(const std::string& service_name,
+ const std::string& object_path) {
+ return new ObjectProxy(this, service_name, object_path);
+}
+
+bool Bus::Init() {
+ // dbus_bus_get_private() and dbus_bus_get() are blocking calls.
+ base::ThreadRestrictions::AssertIOAllowed();
+
+ // Check if it's already initialized.
+ if (connection_)
+ return true;
+
+ DBusError error = {};
stevenjb 2011/07/29 21:54:17 nit: don't need to initialize error (and better no
satorux1 2011/08/01 19:56:41 Done.
+ dbus_error_init(&error);
+ const DBusBusType dbus_bus_type = static_cast<DBusBusType>(bus_type_);
+ if (connection_type_ == PRIVATE) {
+ connection_ = dbus_bus_get_private(dbus_bus_type, &error);
+ } else {
+ connection_ = dbus_bus_get(dbus_bus_type, &error);
+ }
+ if (!connection_) {
+ if (dbus_error_is_set(&error)) {
+ LOG(ERROR) << error.message;
+ }
+ return false;
+ }
+
+ // This is unnecessary if client only uses synchronous APIs, but it
+ // won't hurt.
+ SetUpAsyncOperations();
+
+ return true;
+}
+
+void Bus::SetUpAsyncOperations() {
+ // Process all the incoming data if any, so that OnDispatchStatus() will
+ // be called when the incoming data is ready.
+ ProcessAllIncomingDataIfAny(connection_);
+
+ dbus_connection_set_watch_functions(connection_,
+ &Bus::OnAddWatchStub,
+ &Bus::OnRemoveWatchStub,
+ &Bus::OnToggleWatchStub,
+ this,
+ NULL);
+ // TODO(satorux): Timeout is not yet implemented.
+ dbus_connection_set_timeout_functions(connection_,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ dbus_connection_set_dispatch_status_function(
+ connection_,
+ &Bus::OnDispatchStatusChangedStub,
+ connection_,
+ NULL);
+}
+
+void Bus::ProcessAllIncomingDataIfAny(DBusConnection* connection) {
+ if (dbus_connection_get_dispatch_status(connection) ==
+ DBUS_DISPATCH_DATA_REMAINS) {
+ while (dbus_connection_dispatch(connection) ==
+ DBUS_DISPATCH_DATA_REMAINS);
+ }
+}
+
+void Bus::PostTaskToIoThread(const tracked_objects::Location& from_here,
+ const base::Closure& task) {
+ DCHECK(io_thread_);
+ io_thread_->message_loop()->PostTask(from_here, task);
+}
+
+dbus_bool_t Bus::OnAddWatch(DBusWatch* raw_watch) {
+ Watch* watch = new Watch(raw_watch);
stevenjb 2011/07/29 21:54:17 This confused me for a while re: when Watch gets d
satorux1 2011/08/01 19:56:41 Good point. I think adding a comment is sufficient
+ if (watch->IsReadyToBeWatched()) {
+ watch->StartWatching();
+ }
+ return true;
+}
+
+void Bus::OnRemoveWatch(DBusWatch* raw_watch) {
+ Watch* watch = reinterpret_cast<Watch*>(dbus_watch_get_data(raw_watch));
stevenjb 2011/07/29 21:54:17 dbus_watch_get_data should return a void*, so stat
satorux1 2011/08/01 19:56:41 You are right. Done.
+ delete watch;
+}
+
+void Bus::OnToggleWatch(DBusWatch* raw_watch) {
+ Watch* watch = reinterpret_cast<Watch*>(dbus_watch_get_data(raw_watch));
+ if (watch->IsReadyToBeWatched()) {
+ watch->StartWatching();
+ } else {
+ watch->StopWatching();
stevenjb 2011/07/29 21:54:17 Is it safe to call this if StartWatching() was nev
satorux1 2011/08/01 19:56:41 Good point. Yes it's safe. Added a comment about i
+ }
+}
+
+void Bus::OnDispatchStatusChanged(DBusConnection* connection,
+ DBusDispatchStatus status) {
+ if (!dbus_connection_get_is_connected(connection))
+ return;
+ ProcessAllIncomingDataIfAny(connection);
+}
+
+dbus_bool_t Bus::OnAddWatchStub(DBusWatch* raw_watch, void* data) {
stevenjb 2011/07/29 21:54:17 These could be local functions instead of class st
satorux1 2011/08/01 19:56:41 Here, we need to call self->OnAddWatch(), which is
+ Bus* self = reinterpret_cast<Bus*>(data);
+ return self->OnAddWatch(raw_watch);
+}
+
+void Bus::OnRemoveWatchStub(DBusWatch* raw_watch, void* data) {
+ Bus* self = reinterpret_cast<Bus*>(data);
+ return self->OnRemoveWatch(raw_watch);
+}
+
+void Bus::OnToggleWatchStub(DBusWatch* raw_watch, void* data) {
+ Bus* self = reinterpret_cast<Bus*>(data);
+ return self->OnToggleWatch(raw_watch);
+}
+
+void Bus::OnDispatchStatusChangedStub(DBusConnection* connection,
+ DBusDispatchStatus status,
+ void* data) {
+ Bus* self = reinterpret_cast<Bus*>(data);
+ return self->OnDispatchStatusChanged(connection, status);
+}
+
+} // namespace dbus
« dbus/bus.h ('K') | « dbus/bus.h ('k') | dbus/dbus.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698