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

Unified Diff: dbus/object_proxy.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.cc ('K') | « dbus/object_proxy.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dbus/object_proxy.cc
diff --git a/dbus/object_proxy.cc b/dbus/object_proxy.cc
new file mode 100644
index 0000000000000000000000000000000000000000..50427a66e299e5be0540e73b3498b9b0d0280452
--- /dev/null
+++ b/dbus/object_proxy.cc
@@ -0,0 +1,207 @@
+// 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/bind.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
+#include "dbus/message.h"
+#include "dbus/object_proxy.h"
+
+namespace dbus {
+
+ObjectProxy::ObjectProxy(Bus* bus,
+ const std::string& service_name,
+ const std::string& object_path)
+ : bus_(bus),
+ service_name_(service_name),
+ object_path_(object_path),
+ origin_thread_id_(base::PlatformThread::CurrentId()) {
+}
+
+ObjectProxy::~ObjectProxy() {
+}
+
+// Originally we tried to make |method_call| a const reference, but we
+// gave up as dbus_connection_send_with_reply_and_block() takes a
+// non-const pointer of DBusMessage as the second parameter.
+bool ObjectProxy::CallMethodAndWait(MethodCall* method_call,
+ Response* response,
+ int timeout_ms) {
+ base::ThreadRestrictions::AssertIOAllowed();
+
+ if (!bus_->Init())
+ return false;
+ method_call->SetServiceName(service_name_);
+ method_call->SetObjectPath(object_path_);
+ DBusMessage* request_message = method_call->raw_message();
+
+ DBusError error = {};
+ dbus_error_init(&error);
+
+ // Send the message synchronously.
+ DBusMessage* response_message = dbus_connection_send_with_reply_and_block(
+ bus_->connection(), request_message, timeout_ms, &error);
+
+ if (!response_message) {
+ if (dbus_error_is_set(&error)) {
+ LOG(ERROR) << error.message;
+ }
+ return false;
+ }
+ response->reset_raw_message(response_message);
+
+ return true;
+}
+
+void ObjectProxy::CallMethod(MethodCall* method_call,
+ ResponseCallback callback,
+ int timeout_ms) {
+ AssertOnOriginThread();
+
+ method_call->SetServiceName(service_name_);
+ method_call->SetObjectPath(object_path_);
+ // This is a bit tricky but increment the reference count of the request
+ // message here so that we can keep using the message even if the
+ // MethodCall object at the caller is gone before the method call is
+ // complete.
+ DBusMessage* request_message = method_call->raw_message();
+ dbus_message_ref(request_message);
+
+ // Bind() won't compile if we pass request_message as-is since
+ // DBusMessage is an opaque struct which Bind() does not like.
+ //
+ // /base/bind_helpers.h:145:
+ // error: invalid use of incomplete type 'struct DBusMessage'
+ //
+ // Hence we cast it to void* to workaround the issue.
+ base::Closure task = base::Bind(&ObjectProxy::StartAsyncMethodCall,
+ base::Unretained(this),
+ timeout_ms,
+ reinterpret_cast<void*>(request_message),
+ MessageLoop::current(),
+ callback);
+ if (bus_->use_io_thread()) {
+ bus_->PostTaskToIoThread(FROM_HERE, task);
+ } else {
+ MessageLoopForIO::current()->PostTask(FROM_HERE, task);
+ }
+}
+
+ObjectProxy::OnPendingCallIsCompleteData::OnPendingCallIsCompleteData(
+ ObjectProxy* in_object_proxy,
+ MessageLoop* in_origin_loop,
+ ResponseCallback in_response_callback)
+ : object_proxy(in_object_proxy),
+ origin_loop(in_origin_loop),
+ response_callback(in_response_callback) {
+}
+
+void ObjectProxy::StartAsyncMethodCall(int timeout_ms,
+ void* in_request_message,
+ MessageLoop* origin_loop,
+ ResponseCallback response_callback) {
+ AssertOnIoThreadIfConfigured();
+
+ DBusMessage* request_message =
+ reinterpret_cast<DBusMessage*>(in_request_message);
+ if (bus_->Init()) {
+ DBusPendingCall* pending_call = NULL;
+ // This returns false only when unable to allocate memory.
+ bool success = false;
+ success = dbus_connection_send_with_reply(
+ bus_->connection(), request_message, &pending_call, timeout_ms);
+ dbus_pending_call_ref(pending_call);
+ DCHECK(success) << "Unable to allocate memory";
+
+ // Prepare the data we'll be passing to OnPendingCallIsCompleteStub().
+ // The data will be deleted in OnPendingCallIsCompleteStub().
+ OnPendingCallIsCompleteData* data =
+ new OnPendingCallIsCompleteData(this,
+ origin_loop,
+ response_callback);
+
+ // This returns false only when unable to allocate memory.
+ success = dbus_pending_call_set_notify(
+ pending_call,
+ &ObjectProxy::OnPendingCallIsCompleteStub,
+ data,
+ NULL);
+ DCHECK(success) << "Unable to allocate memory";
+ } else {
+ Response* response = NULL;
+ base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
+ base::Unretained(this),
+ response_callback,
+ response);
+ origin_loop->PostTask(FROM_HERE, task);
+ }
+ // It's now safe to unref the request message.
+ dbus_message_unref(request_message);
+}
+
+void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
+ Response* response) {
+ AssertOnOriginThread();
+
+ if (!response) {
+ response_callback.Run(NULL);
+ } else {
+ if (response->GetMessageType() == Message::MESSAGE_ERROR) {
+ // Error message should contain the error message as string.
+ LOG(ERROR) << "Method call failed: " << response->ToString();
+ // We don't give the error message to the callback.
+ response_callback.Run(NULL);
+ } else {
+ response_callback.Run(response);
+ }
+ }
+}
+
+void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call,
+ ResponseCallback response_callback,
+ MessageLoop* origin_loop) {
+ AssertOnIoThreadIfConfigured();
+
+ DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call);
+ DCHECK(response_message);
+
+ // This will be deleted in the callback.
+ Response* response = new Response;
+ response->reset_raw_message(response_message);
+ base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
+ base::Unretained(this),
+ response_callback,
+ response);
+ origin_loop->PostTask(FROM_HERE, task);
+}
+
+void ObjectProxy::AssertOnOriginThread() {
+ DCHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId());
+}
+
+void ObjectProxy::AssertOnIoThreadIfConfigured() {
+ if (bus_->use_io_thread()) {
+ DCHECK_EQ(bus_->io_thread()->thread_id(),
+ base::PlatformThread::CurrentId());
+ } else {
+ AssertOnOriginThread();
+ }
+}
+
+void ObjectProxy::OnPendingCallIsCompleteStub(DBusPendingCall* pending_call,
+ void* user_data) {
+ OnPendingCallIsCompleteData* data =
+ reinterpret_cast<OnPendingCallIsCompleteData*>(user_data);
+ ObjectProxy* self = data->object_proxy;
+ self->OnPendingCallIsComplete(pending_call,
+ data->response_callback,
+ data->origin_loop);
+ delete data;
+}
+
+} // namespace dbus
« dbus/bus.cc ('K') | « dbus/object_proxy.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698