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

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: Fix wrong comments 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
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/error.h"
13 #include "dbus/message.h"
14 #include "dbus/object_proxy.h"
15
16 namespace dbus {
17
18 ObjectProxy::ObjectProxy(Bus* bus,
19 const std::string& service_name,
20 const std::string& object_path)
21 : bus_(bus),
22 service_name_(service_name),
23 object_path_(object_path) {
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::CallMethodAndBlock(MethodCall* method_call,
33 int timeout_ms,
34 Response* response) {
35 bus_->AssertOnDBusThread();
36
37 if (!bus_->Connect())
38 return false;
39
40 method_call->SetDestination(service_name_);
41 method_call->SetPath(object_path_);
42 DBusMessage* request_message = method_call->raw_message();
43
44 ScopedDBusError error;
45
46 // Send the message synchronously.
47 DBusMessage* response_message =
48 bus_->SendWithReplyAndBlock(request_message, timeout_ms, error.get());
49
50 if (!response_message) {
51 LOG(ERROR) << "Failed to call method: "
52 << (error.is_set() ? error.message() : "");
53 return false;
54 }
55 response->reset_raw_message(response_message);
56
57 return true;
58 }
59
60 void ObjectProxy::CallMethod(MethodCall* method_call,
61 int timeout_ms,
62 ResponseCallback callback) {
63 bus_->AssertOnOriginThread();
64
65 method_call->SetDestination(service_name_);
66 method_call->SetPath(object_path_);
67 // Increment the reference count so we can safely reference the
68 // underlying request message until the method call is complete. This
69 // will be unref'ed in StartAsyncMethodCall().
70 DBusMessage* request_message = method_call->raw_message();
71 dbus_message_ref(request_message);
72
73 // Bind() won't compile if we pass request_message as-is since
74 // DBusMessage is an opaque struct which Bind() cannot handle.
75 // Hence we cast it to void* to workaround the issue.
76 base::Closure task = base::Bind(&ObjectProxy::StartAsyncMethodCall,
77 this,
78 timeout_ms,
79 static_cast<void*>(request_message),
80 callback);
81 // Wait for the response in the D-Bus thread.
82 bus_->PostTaskToDBusThread(FROM_HERE, task);
83 }
84
85 ObjectProxy::OnPendingCallIsCompleteData::OnPendingCallIsCompleteData(
86 ObjectProxy* in_object_proxy,
87 ResponseCallback in_response_callback)
88 : object_proxy(in_object_proxy),
89 response_callback(in_response_callback) {
90 }
91
92 ObjectProxy::OnPendingCallIsCompleteData::~OnPendingCallIsCompleteData() {
93 }
94
95 void ObjectProxy::StartAsyncMethodCall(int timeout_ms,
96 void* in_request_message,
97 ResponseCallback response_callback) {
98 bus_->AssertOnDBusThread();
99
100 if (!bus_->Connect() || !bus_->SetUpAsyncOperations()) {
stevenjb 2011/08/15 21:42:04 Comment describing this case? Is this an error? Is
satorux1 2011/08/16 22:25:37 Yes. Added a comment about it.
101 Response* response = NULL;
102 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
103 this,
104 response_callback,
105 response);
106 bus_->PostTaskToOriginThread(FROM_HERE, task);
107 return;
108 }
109
110 DBusMessage* request_message =
111 static_cast<DBusMessage*>(in_request_message);
112 DBusPendingCall* pending_call = NULL;
113
114 bus_->SendWithReply(request_message, &pending_call, timeout_ms);
115
116 // Prepare the data we'll be passing to OnPendingCallIsCompleteThunk().
117 // The data will be deleted in OnPendingCallIsCompleteThunk().
118 OnPendingCallIsCompleteData* data =
119 new OnPendingCallIsCompleteData(this, response_callback);
120
121 // This returns false only when unable to allocate memory.
122 const bool success = dbus_pending_call_set_notify(
123 pending_call,
124 &ObjectProxy::OnPendingCallIsCompleteThunk,
125 data,
126 NULL);
127 CHECK(success) << "Unable to allocate memory";
128 dbus_pending_call_unref(pending_call);
129
130 // It's now safe to unref the request message.
131 dbus_message_unref(request_message);
132 }
133
134 void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call,
135 ResponseCallback response_callback) {
136 bus_->AssertOnDBusThread();
137
138 DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call);
139
140 if (!response_message) {
141 // This shouldn't happen but just in case.
142 LOG(ERROR) << "The response message is not received for some reason";
143 Response* response = NULL;
144 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
145 this,
146 response_callback,
147 response);
148 bus_->PostTaskToOriginThread(FROM_HERE, task);
149 return;
150 }
151
152 // The response message will be deleted in RunResponseCallback().
153 Response* response = new Response;
154 response->reset_raw_message(response_message);
155 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
156 this,
157 response_callback,
158 response);
159 bus_->PostTaskToOriginThread(FROM_HERE, task);
160 }
161
162 void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
163 Response* response) {
164 bus_->AssertOnOriginThread();
165
166 if (!response) {
167 // The response is not received.
168 response_callback.Run(NULL);
169 } else if (response->GetMessageType() == Message::MESSAGE_ERROR) {
170 // Error message may contain the error message as string.
171 dbus::MessageReader reader(response);
172 std::string error_message;
173 reader.PopString(&error_message);
174 LOG(ERROR) << "Failed to call method: " << response->GetErrorName()
175 << ": " << error_message;
176 // We don't give the error message to the callback.
177 response_callback.Run(NULL);
178 } else {
179 // The response is successfuly received.
180 response_callback.Run(response);
181 }
182 delete response; // It's ok to delete NULL.
183 }
184
185 void ObjectProxy::OnPendingCallIsCompleteThunk(DBusPendingCall* pending_call,
186 void* user_data) {
187 OnPendingCallIsCompleteData* data =
188 reinterpret_cast<OnPendingCallIsCompleteData*>(user_data);
189 ObjectProxy* self = data->object_proxy;
190 self->OnPendingCallIsComplete(pending_call,
191 data->response_callback);
192 delete data;
193 }
194
195 } // namespace dbus
OLDNEW
« dbus/exported_object.cc ('K') | « dbus/object_proxy.h ('k') | dbus/test_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698