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

Side by Side Diff: net/dbus/dbus.cc

Issue 7413004: Uploading for backup... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: today's work 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 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 "net/dbus/dbus.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop.h"
10
11 namespace net {
12 namespace dbus {
13
14 //
15 // Bus implementation.
16 //
17
18 Bus::Bus(const Options& options)
19 : bus_type_(options.bus_type),
20 connection_type_(options.connection_type),
21 connection_(NULL) {
22 }
23
24 Bus::~Bus() {
25 // Private connection should be closed.
26 if (connection_ && connection_type_ == PRIVATE) {
27 dbus_connection_close(connection_);
28 }
29 }
30
31 bool Bus::Init() {
32 // Check if it's already initialized.
33 if (connection_)
34 return true;
35
36 DBusError error = {};
37 dbus_error_init(&error);
38 const DBusBusType dbus_bus_type = static_cast<DBusBusType>(bus_type_);
39 if (connection_type_ == PRIVATE) {
40 connection_ = dbus_bus_get_private(dbus_bus_type, &error);
41 } else {
42 connection_ = dbus_bus_get(dbus_bus_type, &error);
43 }
44 if (!connection_) {
45 if (dbus_error_is_set(&error)) {
46 LOG(ERROR) << error.message;
47 }
48 return false;
49 }
50
51 return true;
52 }
53
54 ObjectProxy* Bus::GetObjectProxy(const std::string& service_name,
55 const std::string& object_path) {
56 DCHECK(connection_) << "Connection not yet established";
57 return new ObjectProxy(this, service_name, object_path);
58 }
59
60 //
61 // ObjectProxy implementation.
62 //
63
64 ObjectProxy::ObjectProxy(Bus* bus,
65 const std::string& service_name,
66 const std::string& object_path)
67 : bus_(bus),
68 service_name_(service_name),
69 object_path_(object_path) {
70 }
71
72 ObjectProxy::~ObjectProxy() {
73 }
74
75 // Originally we tried to make |method_call| a const reference, but we
76 // gave up as dbus_connection_send_with_reply_and_block() takes a
77 // non-const pointer of DBusMessage as the second parameter.
78 bool ObjectProxy::CallMethodSync(MethodCall* method_call,
79 Response* response) {
80 if (!bus_->Init())
81 return false;
82 method_call->SetServiceName(service_name_);
83 method_call->SetObjectPath(object_path_);
84 DBusMessage* request_message = method_call->raw_message();
85
86 const int timeout_ms = -1; // Default timeout.
87 DBusError error = {};
88 dbus_error_init(&error);
89
90 // Send the message synchronously.
91 DBusMessage* response_message = dbus_connection_send_with_reply_and_block(
92 bus_->connection(), request_message, timeout_ms, &error);
93
94 if (!response_message) {
95 if (dbus_error_is_set(&error)) {
96 LOG(ERROR) << error.message;
97 }
98 return false;
99 }
100 response->reset_raw_message(response_message);
101
102 return true;
103 }
104
105 void ObjectProxy::CallMethodAsync(MethodCall* method_call,
106 ResponseCallback callback) {
107 method_call->SetServiceName(service_name_);
108 method_call->SetObjectPath(object_path_);
109 // This is a bit tricky but increment the reference count of the request
110 // message here so that we can keep using the message even if the
111 // MethodCall object at the caller is gone before the method call is
112 // complete.
113 DBusMessage* request_message = method_call->raw_message();
114 dbus_message_ref(request_message);
115
116 // Bind() won't compile if we pass request_message as-is since
117 // DBusMessage is an opaque struct which Bind() does not like.
118 //
119 // /base/bind_helpers.h:145:
120 // error: invalid use of incomplete type 'struct DBusMessage'
121 //
122 // Hence we cast it to void* to workaround the issue.
123 base::Closure task = base::Bind(&ObjectProxy::StartAsyncMethodCall,
124 // Make this a ref-counted class?
125 base::Unretained(this),
126 reinterpret_cast<void*>(request_message),
127 MessageLoop::current(),
128 callback);
129 MessageLoopForIO::current()->PostTask(FROM_HERE, task);
130 }
131
132 void ObjectProxy::StartAsyncMethodCall(void* in_request_message,
133 MessageLoop* origin_loop,
134 ResponseCallback response_callback) {
135 LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
136
137 DBusMessage* request_message =
138 reinterpret_cast<DBusMessage*>(in_request_message);
139 if (bus_->Init()) {
140 const int timeout_ms = -1; // Default timeout.
141 DBusPendingCall* pending_call = NULL;
142 // This returns false only when unable to allocate memory.
143 bool success = false;
144 success = dbus_connection_send_with_reply(
145 bus_->connection(), request_message, &pending_call, timeout_ms);
146 DCHECK(success) << "Unable to allocate memory";
147
148 OnPendingCallIsCompleteData* data =
149 new OnPendingCallIsCompleteData(origin_loop, response_callback);
150
151 // This returns false only when unable to allocate memory.
152 success = dbus_pending_call_set_notify(
153 pending_call,
154 &ObjectProxy::OnPendingCallIsComplete,
155 data,
156 NULL);
157 DCHECK(success) << "Unable to allocate memory";
158 } else {
159 Response* response = NULL;
160 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
161 response_callback,
162 response);
163 origin_loop->PostTask(FROM_HERE, task);
164 }
165 // It's now safe to unref the request message.
166 dbus_message_unref(request_message);
167 }
168
169 void ObjectProxy::RunResponseCallback(ResponseCallback response_callback,
170 Response* response) {
171 LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
172
173 response_callback.Run(response);
174 }
175
176 ObjectProxy::OnPendingCallIsCompleteData::OnPendingCallIsCompleteData(
177 MessageLoop* in_origin_loop,
178 ResponseCallback in_response_callback)
179 : origin_loop(in_origin_loop),
180 response_callback(in_response_callback) {
181 }
182
183 void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call,
184 void* user_data) {
185 OnPendingCallIsCompleteData* data =
186 reinterpret_cast<OnPendingCallIsCompleteData*>(user_data);
187
188 DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call);
189 CHECK(response_message) << "hoge";
190 // This will be deleted in the callback.
191 Response* response = new Response;
192 response->reset_raw_message(response_message);
193 base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
194 data->response_callback,
195 response);
196 data->origin_loop->PostTask(FROM_HERE, task);
197
198 delete data;
199 }
200
201 //
202 // Message implementation.
203 //
204
205 Message::Message()
206 : raw_message_(NULL) {
207 }
208
209 Message::~Message() {
210 if (raw_message_)
211 dbus_message_unref(raw_message_);
212 }
213
214 void Message::reset_raw_message(DBusMessage* raw_message) {
215 if (raw_message_)
216 dbus_message_unref(raw_message_);
217 raw_message_ = raw_message;
218 }
219
220 //
221 // MethodCall implementation.
222 //
223
224 MethodCall::MethodCall(const std::string& interface_name,
225 const std::string& method_name)
226 : Message() {
227 reset_raw_message(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL));
228
229 bool success = false;
230 success = dbus_message_set_interface(raw_message(), interface_name.c_str());
231 DCHECK(success) << "Unable to allocate memory";
232
233 success = dbus_message_set_member(raw_message(), method_name.c_str());
234 DCHECK(success) << "Unable to allocate memory";
235 }
236
237 void MethodCall::SetServiceName(const std::string& service_name) {
238 const bool success = dbus_message_set_destination(raw_message(),
239 service_name.c_str());
240 DCHECK(success) << "Unable to allocate memory";
241 }
242
243 void MethodCall::SetObjectPath(const std::string& object_path) {
244 const bool success = dbus_message_set_path(raw_message(),
245 object_path.c_str());
246 DCHECK(success) << "Unable to allocate memory";
247 }
248
249 //
250 // Response implementation.
251 //
252
253 Response::Response() : Message() {
254 }
255
256 //
257 // MessageWriter implementation.
258 //
259
260 MessageWriter::MessageWriter(Message* message) :
261 message_(message) {
262 dbus_message_iter_init_append(message_->raw_message(), &raw_message_iter_);
263 }
264
265
266 MessageWriter::~MessageWriter() {
267 }
268
269 void MessageWriter::AppendByte(uint8 value) {
270 const bool success = dbus_message_iter_append_basic(
271 &raw_message_iter_, DBUS_TYPE_BYTE, &value);
272 // dbus_message_iter_append_basic() fails only when there is not enough
273 // memory. We don't return this error as there is nothing we can do when
274 // it fails to allocate memory for a byte.
275 DCHECK(success) << "Unable to allocate memory";
276 }
277
278 void MessageWriter::AppendBool(bool value) {
279 const bool success = dbus_message_iter_append_basic(
280 &raw_message_iter_, DBUS_TYPE_BOOLEAN, &value);
281 DCHECK(success) << "Unable to allocate memory";
282 }
283
284 void MessageWriter::AppendInt16(int16 value) {
285 const bool success = dbus_message_iter_append_basic(
286 &raw_message_iter_, DBUS_TYPE_INT16, &value);
287 DCHECK(success) << "Unable to allocate memory";
288 }
289
290 void MessageWriter::AppendUint16(uint16 value) {
291 const bool success = dbus_message_iter_append_basic(
292 &raw_message_iter_, DBUS_TYPE_UINT16, &value);
293 DCHECK(success) << "Unable to allocate memory";
294 }
295
296 void MessageWriter::AppendInt32(int32 value) {
297 const bool success = dbus_message_iter_append_basic(
298 &raw_message_iter_, DBUS_TYPE_INT32, &value);
299 DCHECK(success) << "Unable to allocate memory";
300 }
301
302 void MessageWriter::AppendUint32(uint32 value) {
303 const bool success = dbus_message_iter_append_basic(
304 &raw_message_iter_, DBUS_TYPE_UINT32, &value);
305 DCHECK(success) << "Unable to allocate memory";
306 }
307
308 void MessageWriter::AppendInt64(int64 value) {
309 const bool success = dbus_message_iter_append_basic(
310 &raw_message_iter_, DBUS_TYPE_INT64, &value);
311 DCHECK(success) << "Unable to allocate memory";
312 }
313
314 void MessageWriter::AppendUint64(uint64 value) {
315 const bool success = dbus_message_iter_append_basic(
316 &raw_message_iter_, DBUS_TYPE_UINT64, &value);
317 DCHECK(success) << "Unable to allocate memory";
318 }
319
320 void MessageWriter::AppendDouble(double value) {
321 const bool success = dbus_message_iter_append_basic(
322 &raw_message_iter_, DBUS_TYPE_DOUBLE, &value);
323 DCHECK(success) << "Unable to allocate memory";
324 }
325
326 void MessageWriter::AppendString(const std::string& value) {
327 const char* pointer = value.c_str();
328 const bool success = dbus_message_iter_append_basic(
329 &raw_message_iter_, DBUS_TYPE_STRING, &pointer);
330 // It may make sense to return an error here, as the input string can be
331 // large. If needed, we could add something like
332 // bool AppendStringWithErrorChecking().
333 DCHECK(success) << "Unable to allocate memory";
334 }
335
336 void MessageWriter::AppendObjectPath(const std::string& value) {
337 const char* pointer = value.c_str();
338 const bool success = dbus_message_iter_append_basic(
339 &raw_message_iter_, DBUS_TYPE_OBJECT_PATH, &pointer);
340 DCHECK(success) << "Unable to allocate memory";
341 }
342
343 //
344 // MessageReader implementation.
345 //
346
347 MessageReader::MessageReader(Message* message)
348 : message_(message) {
349 dbus_message_iter_init(message_->raw_message(), &raw_message_iter_);
350 }
351
352
353 MessageReader::~MessageReader() {
354 }
355
356 bool MessageReader::HasMore() {
357 const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
358 return dbus_type != DBUS_TYPE_INVALID;
359 }
360
361 bool MessageReader::PopByte(uint8* value) {
362 return PopBasic(DBUS_TYPE_BYTE, value);
363 }
364
365 bool MessageReader::PopBool(bool* value) {
366 return PopBasic(DBUS_TYPE_BOOLEAN, value);
367 }
368
369 bool MessageReader::PopInt16(int16* value) {
370 return PopBasic(DBUS_TYPE_INT16, value);
371 }
372
373 bool MessageReader::PopUint16(uint16* value) {
374 return PopBasic(DBUS_TYPE_UINT16, value);
375 }
376
377 bool MessageReader::PopInt32(int32* value) {
378 return PopBasic(DBUS_TYPE_INT32, value);
379 }
380
381 bool MessageReader::PopUint32(uint32* value) {
382 return PopBasic(DBUS_TYPE_UINT32, value);
383 }
384
385 bool MessageReader::PopInt64(int64* value) {
386 return PopBasic(DBUS_TYPE_INT64, value);
387 }
388
389 bool MessageReader::PopUint64(uint64* value) {
390 return PopBasic(DBUS_TYPE_UINT64, value);
391 }
392
393 bool MessageReader::PopDouble(double* value) {
394 return PopBasic(DBUS_TYPE_DOUBLE, value);
395 }
396
397 bool MessageReader::PopString(std::string* value) {
398 char* tmp_value = NULL;
399 const bool success = PopBasic(DBUS_TYPE_STRING, &tmp_value);
400 if (success)
401 *value = tmp_value; // Copy the string.
402 return success;
403 }
404
405 bool MessageReader::PopObjectPath(std::string* value) {
406 char* tmp_value = NULL;
407 const bool success = PopBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
408 if (success)
409 *value = tmp_value; // Copy the string.
410 return success;
411 }
412
413 bool MessageReader::PopArray(MessageReader* array_reader) {
414 return PopContainer(DBUS_TYPE_ARRAY, array_reader);
415 }
416
417 bool MessageReader::PopStruct(MessageReader* struct_reader) {
418 return PopContainer(DBUS_TYPE_STRUCT, struct_reader);
419 }
420
421 bool MessageReader::PopDictEntry(MessageReader* dict_entry_reader) {
422 return PopContainer(DBUS_TYPE_DICT_ENTRY, dict_entry_reader);
423 }
424
425 bool MessageReader::PopVariant(MessageReader* variant_reader) {
426 return PopContainer(DBUS_TYPE_VARIANT, variant_reader);
427 }
428
429 bool MessageReader::PopArrayOfBytes(
430 std::vector<uint8>* bytes) {
431 MessageReader array_reader(message_);
432 if (!PopArray(&array_reader))
433 return false;
434 if (!array_reader.CheckType(DBUS_TYPE_BYTE))
435 return false;
436 char* values = NULL;
437 int num_values = 0;
438 dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_,
439 &values, &num_values);
440 if (!values)
441 return false;
442
443 bytes->assign(values, values + num_values); // Copy the data.
444 return true;
445 }
446
447 bool MessageReader::PopArrayOfObjectPaths(
448 std::vector<std::string> *object_paths) {
449 MessageReader array_reader(message_);
450 if (!PopArray(&array_reader))
451 return false;
452 while (array_reader.HasMore()) {
453 std::string object_path;
454 if (!array_reader.PopObjectPath(&object_path))
455 return false;
456 object_paths->push_back(object_path);
457 }
458 return true;
459 }
460
461 bool MessageReader::PopVariantOfByte(uint8* value) {
462 return PopVariantOfBasic(DBUS_TYPE_BYTE, value);
463 }
464
465 bool MessageReader::PopVariantOfBool(bool* value) {
466 return PopVariantOfBasic(DBUS_TYPE_BOOLEAN, value);
467 }
468
469 bool MessageReader::PopVariantOfInt16(int16* value) {
470 return PopVariantOfBasic(DBUS_TYPE_INT16, value);
471 }
472
473 bool MessageReader::PopVariantOfUint16(uint16* value) {
474 return PopVariantOfBasic(DBUS_TYPE_UINT16, value);
475 }
476
477 bool MessageReader::PopVariantOfInt32(int32* value) {
478 return PopVariantOfBasic(DBUS_TYPE_INT32, value);
479 }
480
481 bool MessageReader::PopVariantOfUint32(uint32* value) {
482 return PopVariantOfBasic(DBUS_TYPE_UINT32, value);
483 }
484
485 bool MessageReader::PopVariantOfInt64(int64* value) {
486 return PopVariantOfBasic(DBUS_TYPE_INT64, value);
487 }
488
489 bool MessageReader::PopVariantOfUint64(uint64* value) {
490 return PopVariantOfBasic(DBUS_TYPE_UINT64, value);
491 }
492
493 bool MessageReader::PopVariantOfDouble(double* value) {
494 return PopVariantOfBasic(DBUS_TYPE_DOUBLE, value);
495 }
496
497 bool MessageReader::PopVariantOfString(std::string* value) {
498 char* tmp_value = NULL;
499 const bool success = PopVariantOfBasic(DBUS_TYPE_STRING, &tmp_value);
500 if (success)
501 *value = tmp_value; // Copy the string.
502 return success;
503 }
504
505 bool MessageReader::PopVariantOfObjectPath(std::string* value) {
506 char* tmp_value = NULL;
507 const bool success = PopVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
508 if (success)
509 *value = tmp_value; // Copy the string.
510 return success;
511 }
512
513 bool MessageReader::CheckType(int dbus_type) {
514 const int actual_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
515 if (actual_type != dbus_type) {
516 VLOG(1) << "Type " << dbus_type << " is expected but got "
517 << actual_type;
518 return false;
519 }
520 return true;
521 }
522
523 bool MessageReader::PopBasic(int dbus_type, void* value) {
524 if (!CheckType(dbus_type))
525 return false;
526 dbus_message_iter_get_basic(&raw_message_iter_, value);
527 dbus_message_iter_next(&raw_message_iter_);
528 return true;
529 }
530
531 bool MessageReader::PopContainer(int dbus_type, MessageReader* sub_reader) {
532 DCHECK_NE(this, sub_reader);
533
534 if (!CheckType(dbus_type))
535 return false;
536 dbus_message_iter_recurse(&raw_message_iter_,
537 &sub_reader->raw_message_iter_);
538 dbus_message_iter_next(&raw_message_iter_);
539 return true;
540 }
541
542 bool MessageReader::PopVariantOfBasic(int dbus_type, void* value) {
543 net::dbus::MessageReader variant_reader(message_);
544 if (!PopVariant(&variant_reader))
545 return false;
546 return variant_reader.PopBasic(dbus_type, value);
547 }
548
549 } // namespace dbus
550 } // namespace net
OLDNEW
« net/dbus/dbus.h ('K') | « net/dbus/dbus.h ('k') | net/dbus/dbus_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698