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

Side by Side 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, 4 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 unified diff | Download patch | Annotate | Revision Log
« dbus/bus.cc ('K') | « dbus/object_proxy.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "dbus/bus.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop.h"
10 #include "base/threading/thread.h"
11 #include "base/threading/thread_restrictions.h"
12 #include "dbus/message.h"
13 #include "dbus/object_proxy.h"
14
15 namespace dbus {
16
17 ObjectProxy::ObjectProxy(Bus* bus,
18 const std::string& service_name,
19 const std::string& object_path)
20 : bus_(bus),
21 service_name_(service_name),
22 object_path_(object_path),
23 origin_thread_id_(base::PlatformThread::CurrentId()) {
24 }
25
26 ObjectProxy::~ObjectProxy() {
27 }
28
29 // Originally we tried to make |method_call| a const reference, but we
30 // gave up as dbus_connection_send_with_reply_and_block() takes a
31 // non-const pointer of DBusMessage as the second parameter.
32 bool ObjectProxy::CallMethodAndWait(MethodCall* method_call,
33 Response* response,
34 int timeout_ms) {
35 base::ThreadRestrictions::AssertIOAllowed();
36
37 if (!bus_->Init())
38 return false;
39 method_call->SetServiceName(service_name_);
40 method_call->SetObjectPath(object_path_);
41 DBusMessage* request_message = method_call->raw_message();
42
43 DBusError error = {};
44 dbus_error_init(&error);
45
46 // Send the message synchronously.
47 DBusMessage* response_message = dbus_connection_send_with_reply_and_block(
48 bus_->connection(), request_message, timeout_ms, &error);
49
50 if (!response_message) {
51 if (dbus_error_is_set(&error)) {
52 LOG(ERROR) << error.message;
53 }
54 return false;
55 }
56 response->reset_raw_message(response_message);
57
58 return true;
59 }
60
61 void ObjectProxy::CallMethod(MethodCall* method_call,
62 ResponseCallback callback,
63 int timeout_ms) {
64 AssertOnOriginThread();
65
66 method_call->SetServiceName(service_name_);
67 method_call->SetObjectPath(object_path_);
68 // This is a bit tricky but increment the reference count of the request
69 // message here so that we can keep using the message even if the
70 // MethodCall object at the caller is gone before the method call is
71 // complete.
72 DBusMessage* request_message = method_call->raw_message();
73 dbus_message_ref(request_message);
74
75 // Bind() won't compile if we pass request_message as-is since
76 // DBusMessage is an opaque struct which Bind() does not like.
77 //
78 // /base/bind_helpers.h:145:
79 // error: invalid use of incomplete type 'struct DBusMessage'
80 //
81 // Hence we cast it to void* to workaround the issue.
82 base::Closure task = base::Bind(&ObjectProxy::StartAsyncMethodCall,
83 base::Unretained(this),
84 timeout_ms,
85 reinterpret_cast<void*>(request_message),
86 MessageLoop::current(),
87 callback);
88 if (bus_->use_io_thread()) {
89 bus_->PostTaskToIoThread(FROM_HERE, task);
90 } else {
91 MessageLoopForIO::current()->PostTask(FROM_HERE, task);
92 }
93 }
94
95 ObjectProxy::OnPendingCallIsCompleteData::OnPendingCallIsCompleteData(
96 ObjectProxy* in_object_proxy,
97 MessageLoop* in_origin_loop,
98 ResponseCallback in_response_callback)
99 : object_proxy(in_object_proxy),
100 origin_loop(in_origin_loop),
101 response_callback(in_response_callback) {
102 }
103
104 void ObjectProxy::StartAsyncMethodCall(int timeout_ms,
105 void* in_request_message,
106 MessageLoop* origin_loop,
107 ResponseCallback response_callback) {
108 AssertOnIoThreadIfConfigured();
109
110 DBusMessage* request_message =
111 reinterpret_cast<DBusMessage*>(in_request_message);
112 if (bus_->Init()) {
113 DBusPendingCall* pending_call = NULL;
114 // This returns false only when unable to allocate memory.
115 bool success = false;
116 success = dbus_connection_send_with_reply(
117 bus_->connection(), request_message, &pending_call, timeout_ms);
118 dbus_pending_call_ref(pending_call);
119 DCHECK(success) << "Unable to allocate memory";
120
121 // Prepare the data we'll be passing to OnPendingCallIsCompleteStub().
122 // The data will be deleted in OnPendingCallIsCompleteStub().
123 OnPendingCallIsCompleteData* data =
124 new OnPendingCallIsCompleteData(this,
125 origin_loop,
126 response_callback);
127
128 // This returns false only when unable to allocate memory.
129 success = dbus_pending_call_set_notify(
130 pending_call,
131 &ObjectProxy::OnPendingCallIsCompleteStub,
132 data,
133 NULL);
134 DCHECK(success) << "Unable to allocate memory";
135 } else {
136 Response* response = NULL;
137 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
138 base::Unretained(this),
139 response_callback,
140 response);
141 origin_loop->PostTask(FROM_HERE, task);
142 }
143 // It's now safe to unref the request message.
144 dbus_message_unref(request_message);
145 }
146
147 void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
148 Response* response) {
149 AssertOnOriginThread();
150
151 if (!response) {
152 response_callback.Run(NULL);
153 } else {
154 if (response->GetMessageType() == Message::MESSAGE_ERROR) {
155 // Error message should contain the error message as string.
156 LOG(ERROR) << "Method call failed: " << response->ToString();
157 // We don't give the error message to the callback.
158 response_callback.Run(NULL);
159 } else {
160 response_callback.Run(response);
161 }
162 }
163 }
164
165 void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call,
166 ResponseCallback response_callback,
167 MessageLoop* origin_loop) {
168 AssertOnIoThreadIfConfigured();
169
170 DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call);
171 DCHECK(response_message);
172
173 // This will be deleted in the callback.
174 Response* response = new Response;
175 response->reset_raw_message(response_message);
176 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
177 base::Unretained(this),
178 response_callback,
179 response);
180 origin_loop->PostTask(FROM_HERE, task);
181 }
182
183 void ObjectProxy::AssertOnOriginThread() {
184 DCHECK_EQ(origin_thread_id_, base::PlatformThread::CurrentId());
185 }
186
187 void ObjectProxy::AssertOnIoThreadIfConfigured() {
188 if (bus_->use_io_thread()) {
189 DCHECK_EQ(bus_->io_thread()->thread_id(),
190 base::PlatformThread::CurrentId());
191 } else {
192 AssertOnOriginThread();
193 }
194 }
195
196 void ObjectProxy::OnPendingCallIsCompleteStub(DBusPendingCall* pending_call,
197 void* user_data) {
198 OnPendingCallIsCompleteData* data =
199 reinterpret_cast<OnPendingCallIsCompleteData*>(user_data);
200 ObjectProxy* self = data->object_proxy;
201 self->OnPendingCallIsComplete(pending_call,
202 data->response_callback,
203 data->origin_loop);
204 delete data;
205 }
206
207 } // namespace dbus
OLDNEW
« 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