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

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: another clang challenge 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
« no previous file with comments | « dbus/object_proxy.h ('k') | dbus/scoped_dbus_error.h » ('j') | 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 #include "dbus/scoped_dbus_error.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()) {
101 // In case of a failure, run the callback with NULL response, that
102 // indicates a failure.
103 Response* response = NULL;
104 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
105 this,
106 response_callback,
107 response);
108 bus_->PostTaskToOriginThread(FROM_HERE, task);
109 return;
110 }
111
112 DBusMessage* request_message =
113 static_cast<DBusMessage*>(in_request_message);
114 DBusPendingCall* pending_call = NULL;
115
116 bus_->SendWithReply(request_message, &pending_call, timeout_ms);
117
118 // Prepare the data we'll be passing to OnPendingCallIsCompleteThunk().
119 // The data will be deleted in OnPendingCallIsCompleteThunk().
120 OnPendingCallIsCompleteData* data =
121 new OnPendingCallIsCompleteData(this, response_callback);
122
123 // This returns false only when unable to allocate memory.
124 const bool success = dbus_pending_call_set_notify(
125 pending_call,
126 &ObjectProxy::OnPendingCallIsCompleteThunk,
127 data,
128 NULL);
129 CHECK(success) << "Unable to allocate memory";
130 dbus_pending_call_unref(pending_call);
131
132 // It's now safe to unref the request message.
133 dbus_message_unref(request_message);
134 }
135
136 void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call,
137 ResponseCallback response_callback) {
138 bus_->AssertOnDBusThread();
139
140 DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call);
141
142 if (!response_message) {
143 // This shouldn't happen but just in case.
144 LOG(ERROR) << "The response message is not received for some reason";
145 Response* response = NULL;
146 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
147 this,
148 response_callback,
149 response);
150 bus_->PostTaskToOriginThread(FROM_HERE, task);
151 return;
152 }
153
154 // The response message will be deleted in RunResponseCallback().
155 Response* response = new Response;
156 response->reset_raw_message(response_message);
157 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
158 this,
159 response_callback,
160 response);
161 bus_->PostTaskToOriginThread(FROM_HERE, task);
162 }
163
164 void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
165 Response* response) {
166 bus_->AssertOnOriginThread();
167
168 if (!response) {
169 // The response is not received.
170 response_callback.Run(NULL);
171 } else if (response->GetMessageType() == Message::MESSAGE_ERROR) {
172 // Error message may contain the error message as string.
173 dbus::MessageReader reader(response);
174 std::string error_message;
175 reader.PopString(&error_message);
176 LOG(ERROR) << "Failed to call method: " << response->GetErrorName()
177 << ": " << error_message;
178 // We don't give the error message to the callback.
179 response_callback.Run(NULL);
180 } else {
181 // The response is successfuly received.
182 response_callback.Run(response);
183 }
184 delete response; // It's ok to delete NULL.
185 }
186
187 void ObjectProxy::OnPendingCallIsCompleteThunk(DBusPendingCall* pending_call,
188 void* user_data) {
189 OnPendingCallIsCompleteData* data =
190 reinterpret_cast<OnPendingCallIsCompleteData*>(user_data);
191 ObjectProxy* self = data->object_proxy;
192 self->OnPendingCallIsComplete(pending_call,
193 data->response_callback);
194 delete data;
195 }
196
197 } // namespace dbus
OLDNEW
« no previous file with comments | « dbus/object_proxy.h ('k') | dbus/scoped_dbus_error.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698