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

Unified Diff: net/dbus/dbus.cc

Issue 7413004: Uploading for backup... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: backup 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
« no previous file with comments | « net/dbus/dbus.h ('k') | net/dbus/dbus_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/dbus/dbus.cc
diff --git a/net/dbus/dbus.cc b/net/dbus/dbus.cc
new file mode 100644
index 0000000000000000000000000000000000000000..ee7ee699993dc4e010843df6c899645255f4c415
--- /dev/null
+++ b/net/dbus/dbus.cc
@@ -0,0 +1,886 @@
+// 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 "net/dbus/dbus.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "base/stringprintf.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/threading/platform_thread.h"
+
+namespace net {
+namespace dbus {
+
+//
+// Bus implementation.
+//
+
+Bus::Bus(const Options& options)
+ : bus_type_(options.bus_type),
+ connection_type_(options.connection_type),
+ connection_(NULL) {
+}
+
+Bus::~Bus() {
+ // Private connection should be closed.
+ if (connection_ && connection_type_ == PRIVATE) {
+ dbus_connection_close(connection_);
+ }
+}
+
+bool Bus::Init() {
+ // Check if it's already initialized.
+ if (connection_)
+ return true;
+
+ DBusError error = {};
+ dbus_error_init(&error);
+ const DBusBusType dbus_bus_type = static_cast<DBusBusType>(bus_type_);
+ if (connection_type_ == PRIVATE) {
+ connection_ = dbus_bus_get_private(dbus_bus_type, &error);
+ } else {
+ connection_ = dbus_bus_get(dbus_bus_type, &error);
+ }
+ if (!connection_) {
+ if (dbus_error_is_set(&error)) {
+ LOG(ERROR) << error.message;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+void OnDispatchStatus(DBusConnection* connection,
+ DBusDispatchStatus status,
+ void *data) {
+ LOG(ERROR) << "is connected: "
+ << dbus_connection_get_is_connected(connection);
+ LOG(ERROR) << "new status: " << status;
+}
+
+bool Bus::InitForAsync() {
+ if (!Init()) {
+ return false;
+ }
+ LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
+ dbus_connection_set_watch_functions(connection_,
+ &Bus::OnAddWatch,
+ &Bus::OnRemoveWatch,
+ &Bus::OnToggleWatch,
+ this,
+ NULL);
+ dbus_connection_set_timeout_functions(connection_,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ dbus_connection_set_dispatch_status_function(connection_,
+ OnDispatchStatus,
+ connection_,
+ NULL);
+ return true;
+}
+
+ObjectProxy* Bus::GetObjectProxy(const std::string& service_name,
+ const std::string& object_path) {
+ return new ObjectProxy(this, service_name, object_path);
+}
+
+class Bus::IOThread : public base::Thread {
+ public:
+ IOThread() : base::Thread("Bus::IOThread") {
+ }
+
+ ~IOThread() {
+ }
+};
+
+
+void Bus::StartIOThreadIfNeeded() {
+ if (io_thread_.get())
+ return;
+ base::Thread::Options thread_options;
+ thread_options.message_loop_type = MessageLoop::TYPE_IO;
+ io_thread_.reset(new IOThread);
+ io_thread_->StartWithOptions(thread_options);
+}
+
+void Bus::PostTask(const tracked_objects::Location& from_here,
+ const base::Closure& task) {
+ io_thread_->message_loop()->PostTask(from_here, task);
+}
+
+class Watch : public base::MessagePumpLibevent::Watcher {
+ public:
+ Watch(DBusWatch* watch, DBusConnection* connection)
+ : watch_(watch),
+ connection_(connection) {
+ dbus_watch_set_data(watch_, this, NULL);
+ }
+
+ ~Watch() {
+ file_descriptor_watcher_.StopWatchingFileDescriptor();
+ dbus_watch_set_data(watch_, NULL, NULL);
+ }
+
+ // Returns true if ready to watch.
+ bool IsEnabled() {
+ return dbus_watch_get_enabled(watch_);
+ }
+
+ void StartWatching() {
+ LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
+
+ const int fd = dbus_watch_get_unix_fd(watch_);
+ LOG(ERROR) << "fd: " << fd;
+ const int flags = dbus_watch_get_flags(watch_);
+ LOG(ERROR) << "flags: " << flags;
+
+ MessageLoopForIO::Mode mode;
+ if ((flags & DBUS_WATCH_READABLE) && (flags & DBUS_WATCH_WRITABLE))
+ mode = MessageLoopForIO::WATCH_READ_WRITE;
+ if (flags & DBUS_WATCH_READABLE)
+ mode = MessageLoopForIO::WATCH_READ;
+ if (flags & DBUS_WATCH_WRITABLE)
+ mode = MessageLoopForIO::WATCH_WRITE;
+
+ const bool persistent = true; // Watch persistently.
+ const bool success = MessageLoopForIO::current()->WatchFileDescriptor(
+ fd,
+ persistent,
+ mode,
+ &file_descriptor_watcher_,
+ this);
+ DCHECK(success) << "Unable to allocate memory";
+ }
+
+ // Implements MessagePumpLibevent::Watcher::OnFileCanReadWithoutBlocking.
+ virtual void OnFileCanReadWithoutBlocking(int fd) {
+ LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
+
+ int flags = 0;
+ flags |= DBUS_WATCH_READABLE;
+ flags |= DBUS_WATCH_WRITABLE;
+ LOG(ERROR) << "status: " <<
+ dbus_connection_get_dispatch_status(connection_);
+ const bool success = dbus_watch_handle(watch_, flags);
+ LOG(ERROR) << "status: " <<
+ dbus_connection_get_dispatch_status(connection_);
+ while (dbus_connection_dispatch(connection_) == DBUS_DISPATCH_DATA_REMAINS);
+
+ DCHECK(success) << "Unable to allocate memory";
+ }
+
+ // Implements MessagePumpLibevent::Watcher::OnFileCanWriteWithoutBlocking.
+ virtual void OnFileCanWriteWithoutBlocking(int fd) {
+ LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
+
+ const bool success = dbus_watch_handle(watch_, DBUS_WATCH_WRITABLE);
+ DCHECK(success) << "Unable to allocate memory";
+ }
+
+ private:
+ DBusWatch* watch_;
+ DBusConnection* connection_;
+ base::MessagePumpLibevent::FileDescriptorWatcher file_descriptor_watcher_;
+};
+
+dbus_bool_t Bus::OnAddWatch(DBusWatch* raw_watch, void* data) {
+ LOG(ERROR) << "@@ " << "watch: " << raw_watch;
+
+ Bus* self = reinterpret_cast<Bus*>(data);
+ Watch* watch = new Watch(raw_watch, self->connection_);
+ LOG(ERROR) << "flags: " << dbus_watch_get_flags(raw_watch);
+ if (watch->IsEnabled()) {
+ watch->StartWatching();
+ }
+ return true;
+}
+
+void Bus::OnRemoveWatch(DBusWatch* raw_watch, void* data) {
+ LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
+
+ Watch* watch = reinterpret_cast<Watch*>(dbus_watch_get_data(raw_watch));
+ delete watch;
+}
+
+void Bus::OnToggleWatch(DBusWatch* raw_watch, void* data) {
+ LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
+
+ Watch* watch = reinterpret_cast<Watch*>(dbus_watch_get_data(raw_watch));
+ if (watch->IsEnabled()) {
+ OnAddWatch(raw_watch, data);
+ } else {
+ OnRemoveWatch(raw_watch, data);
+ }
+}
+
+//
+// ObjectProxy implementation.
+//
+
+ObjectProxy::ObjectProxy(Bus* bus,
+ const std::string& service_name,
+ const std::string& object_path)
+ : bus_(bus),
+ service_name_(service_name),
+ object_path_(object_path) {
+}
+
+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::CallMethodSync(MethodCall* method_call,
+ Response* response) {
+ 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();
+
+ const int timeout_ms = -1; // Default timeout.
+ 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::CallMethodAsync(MethodCall* method_call,
+ ResponseCallback callback) {
+ bus_->StartIOThreadIfNeeded();
+
+ 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,
+ // Make this a ref-counted class?
+ base::Unretained(this),
+ reinterpret_cast<void*>(request_message),
+ MessageLoop::current(),
+ callback);
+ LOG(ERROR) << "CallMethodAsync: thread id: " << base::PlatformThread::CurrentId();
+ bus_->PostTask(FROM_HERE, task);
+}
+
+void ObjectProxy::StartAsyncMethodCall(void* in_request_message,
+ MessageLoop* origin_loop,
+ ResponseCallback response_callback) {
+ LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
+
+ DBusMessage* request_message =
+ reinterpret_cast<DBusMessage*>(in_request_message);
+ if (bus_->InitForAsync()) {
+ const int timeout_ms = -1; // Default timeout.
+ 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";
+
+ OnPendingCallIsCompleteData* data =
+ new OnPendingCallIsCompleteData(origin_loop, response_callback);
+
+ // This returns false only when unable to allocate memory.
+ success = dbus_pending_call_set_notify(
+ pending_call,
+ &ObjectProxy::OnPendingCallIsComplete,
+ data,
+ NULL);
+ DCHECK(success) << "Unable to allocate memory";
+ } else {
+ Response* response = NULL;
+ base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
+ 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) {
+ LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
+
+ response_callback.Run(response);
+}
+
+ObjectProxy::OnPendingCallIsCompleteData::OnPendingCallIsCompleteData(
+ MessageLoop* in_origin_loop,
+ ResponseCallback in_response_callback)
+ : origin_loop(in_origin_loop),
+ response_callback(in_response_callback) {
+}
+
+void ObjectProxy::OnPendingCallIsComplete(DBusPendingCall* pending_call,
+ void* user_data) {
+ LOG(ERROR) << "@@ " << __PRETTY_FUNCTION__;
+
+ OnPendingCallIsCompleteData* data =
+ reinterpret_cast<OnPendingCallIsCompleteData*>(user_data);
+
+ DBusMessage* response_message = dbus_pending_call_steal_reply(pending_call);
+ CHECK(response_message) << "hoge";
+ // This will be deleted in the callback.
+ Response* response = new Response;
+ response->reset_raw_message(response_message);
+ base::Closure task = base::Bind(&ObjectProxy::RunResponseCallback,
+ data->response_callback,
+ response);
+ data->origin_loop->PostTask(FROM_HERE, task);
+
+ delete data;
+}
+
+//
+// Message implementation.
+//
+
+Message::Message()
+ : raw_message_(NULL) {
+}
+
+Message::~Message() {
+ if (raw_message_)
+ dbus_message_unref(raw_message_);
+}
+
+void Message::reset_raw_message(DBusMessage* raw_message) {
+ if (raw_message_)
+ dbus_message_unref(raw_message_);
+ raw_message_ = raw_message;
+}
+
+std::string Message::ToStringInternal(const std::string& indent,
+ MessageReader* reader) {
+ std::string output;
+ while (reader->HasMore()) {
+ const Type type = reader->GetType();
+ switch (type) {
+ case BYTE: {
+ uint8 value;
+ reader->PopByte(&value);
+ output += indent + "byte " + base::StringPrintf("%d", value) + "\n";
+ break;
+ }
+ case BOOL: {
+ bool value;
+ reader->PopBool(&value);
+ output += indent + "bool " + (value ? "true" : "false") + "\n";
+ break;
+ }
+ case INT16: {
+ int16 value;
+ reader->PopInt16(&value);
+ output += indent + "int16 " + base::StringPrintf("%d", value) + "\n";
+ break;
+ }
+ case UINT16: {
+ uint16 value;
+ reader->PopUint16(&value);
+ output += indent + "uint16 " + base::StringPrintf("%d", value) + "\n";
+ break;
+ }
+ case INT32: {
+ int32 value;
+ reader->PopInt32(&value);
+ output += indent + "int32 " + base::StringPrintf("%d", value) + "\n";
+ break;
+ }
+ case UINT32: {
+ uint32 value;
+ reader->PopUint32(&value);
+ output += indent + "uint32 " + base::StringPrintf("%u", value) + "\n";
+ break;
+ }
+ case INT64: {
+ int64 value;
+ reader->PopInt64(&value);
+ output += indent + "int64 " + base::StringPrintf("%ld", value) + "\n";
+ break;
+ }
+ case UINT64: {
+ uint64 value;
+ reader->PopUint64(&value);
+ output += indent + "uint64 " + base::StringPrintf("%lu", value) + "\n";
+ break;
+ }
+ case DOUBLE: {
+ double value;
+ reader->PopDouble(&value);
+ output += indent + "double " + base::StringPrintf("%f", value) + "\n";
+ break;
+ }
+ case STRING: {
+ std::string value;
+ reader->PopString(&value);
+ output += indent + "string \"" + value + "\"\n";
+ break;
+ }
+ case OBJECT_PATH: {
+ std::string value;
+ reader->PopObjectPath(&value);
+ output += indent + "object_path \"" + value + "\"\n";
+ break;
+ }
+ case ARRAY: {
+ MessageReader sub_reader(this);
+ reader->PopArray(&sub_reader);
+ output += indent + "array [\n";
+ output += ToStringInternal(indent + " ", &sub_reader);
+ output += indent + "]\n";
+ break;
+ }
+ case STRUCT: {
+ MessageReader sub_reader(this);
+ reader->PopStruct(&sub_reader);
+ output += indent + "struct {\n";
+ output += ToStringInternal(indent + " ", &sub_reader);
+ output += indent + "}\n";
+ break;
+ }
+ case DICT_ENTRY: {
+ MessageReader sub_reader(this);
+ reader->PopDictEntry(&sub_reader);
+ output += indent + "dict entry {\n";
+ output += ToStringInternal(indent + " ", &sub_reader);
+ output += indent + "}\n";
+ break;
+ }
+ case VARIANT: {
+ MessageReader sub_reader(this);
+ reader->PopVariant(&sub_reader);
+ output += indent + "variant ";
+ output += ToStringInternal(indent + " ", &sub_reader);
+ break;
+ }
+ default:
+ LOG(FATAL) << "Unknown type: " << type;
+ }
+ }
+ return output;
+}
+
+std::string Message::ToString() {
+ std::string output;
+ MessageReader reader(this);
+ return ToStringInternal("", &reader);
+}
+
+//
+// MethodCall implementation.
+//
+
+MethodCall::MethodCall(const std::string& interface_name,
+ const std::string& method_name)
+ : Message() {
+ reset_raw_message(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL));
+
+ bool success = false;
+ success = dbus_message_set_interface(raw_message(), interface_name.c_str());
+ DCHECK(success) << "Unable to allocate memory";
+
+ success = dbus_message_set_member(raw_message(), method_name.c_str());
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MethodCall::SetServiceName(const std::string& service_name) {
+ const bool success = dbus_message_set_destination(raw_message(),
+ service_name.c_str());
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MethodCall::SetObjectPath(const std::string& object_path) {
+ const bool success = dbus_message_set_path(raw_message(),
+ object_path.c_str());
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+//
+// Response implementation.
+//
+
+Response::Response() : Message() {
+}
+
+//
+// MessageWriter implementation.
+//
+
+MessageWriter::MessageWriter(Message* message) :
+ message_(message) {
+ dbus_message_iter_init_append(message_->raw_message(), &raw_message_iter_);
+}
+
+
+MessageWriter::~MessageWriter() {
+}
+
+void MessageWriter::AppendByte(uint8 value) {
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_BYTE, &value);
+ // dbus_message_iter_append_basic() fails only when there is not enough
+ // memory. We don't return this error as there is nothing we can do when
+ // it fails to allocate memory for a byte.
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::AppendBool(bool value) {
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_BOOLEAN, &value);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::AppendInt16(int16 value) {
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_INT16, &value);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::AppendUint16(uint16 value) {
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_UINT16, &value);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::AppendInt32(int32 value) {
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_INT32, &value);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::AppendUint32(uint32 value) {
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_UINT32, &value);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::AppendInt64(int64 value) {
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_INT64, &value);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::AppendUint64(uint64 value) {
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_UINT64, &value);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::AppendDouble(double value) {
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_DOUBLE, &value);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::AppendString(const std::string& value) {
+ const char* pointer = value.c_str();
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_STRING, &pointer);
+ // It may make sense to return an error here, as the input string can be
+ // large. If needed, we could add something like
+ // bool AppendStringWithErrorChecking().
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::AppendObjectPath(const std::string& value) {
+ const char* pointer = value.c_str();
+ const bool success = dbus_message_iter_append_basic(
+ &raw_message_iter_, DBUS_TYPE_OBJECT_PATH, &pointer);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::OpenArray(const std::string& signature,
+ MessageWriter* writer) {
+ const bool success = dbus_message_iter_open_container(
+ &raw_message_iter_,
+ DBUS_TYPE_ARRAY,
+ signature.c_str(),
+ &writer->raw_message_iter_);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::OpenVariant(const std::string& signature,
+ MessageWriter* writer) {
+ const bool success = dbus_message_iter_open_container(
+ &raw_message_iter_,
+ DBUS_TYPE_VARIANT,
+ signature.c_str(),
+ &writer->raw_message_iter_);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::OpenStruct(MessageWriter* writer) {
+ const bool success = dbus_message_iter_open_container(
+ &raw_message_iter_,
+ DBUS_TYPE_STRUCT,
+ NULL, // Signature should be NULL.
+ &writer->raw_message_iter_);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::OpenDictEntry(MessageWriter* writer) {
+ const bool success = dbus_message_iter_open_container(
+ &raw_message_iter_,
+ DBUS_TYPE_DICT_ENTRY,
+ NULL, // Signature should be NULL.
+ &writer->raw_message_iter_);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+void MessageWriter::CloseContainer(MessageWriter* writer) {
+ const bool success = dbus_message_iter_close_container(
+ &raw_message_iter_, &writer->raw_message_iter_);
+ DCHECK(success) << "Unable to allocate memory";
+}
+
+//
+// MessageReader implementation.
+//
+
+MessageReader::MessageReader(Message* message)
+ : message_(message) {
+ dbus_message_iter_init(message_->raw_message(), &raw_message_iter_);
+}
+
+
+MessageReader::~MessageReader() {
+}
+
+bool MessageReader::HasMore() {
+ const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
+ return dbus_type != DBUS_TYPE_INVALID;
+}
+
+bool MessageReader::PopByte(uint8* value) {
+ return PopBasic(DBUS_TYPE_BYTE, value);
+}
+
+bool MessageReader::PopBool(bool* value) {
+ return PopBasic(DBUS_TYPE_BOOLEAN, value);
+}
+
+bool MessageReader::PopInt16(int16* value) {
+ return PopBasic(DBUS_TYPE_INT16, value);
+}
+
+bool MessageReader::PopUint16(uint16* value) {
+ return PopBasic(DBUS_TYPE_UINT16, value);
+}
+
+bool MessageReader::PopInt32(int32* value) {
+ return PopBasic(DBUS_TYPE_INT32, value);
+}
+
+bool MessageReader::PopUint32(uint32* value) {
+ return PopBasic(DBUS_TYPE_UINT32, value);
+}
+
+bool MessageReader::PopInt64(int64* value) {
+ return PopBasic(DBUS_TYPE_INT64, value);
+}
+
+bool MessageReader::PopUint64(uint64* value) {
+ return PopBasic(DBUS_TYPE_UINT64, value);
+}
+
+bool MessageReader::PopDouble(double* value) {
+ return PopBasic(DBUS_TYPE_DOUBLE, value);
+}
+
+bool MessageReader::PopString(std::string* value) {
+ char* tmp_value = NULL;
+ const bool success = PopBasic(DBUS_TYPE_STRING, &tmp_value);
+ if (success)
+ *value = tmp_value; // Copy the string.
+ return success;
+}
+
+bool MessageReader::PopObjectPath(std::string* value) {
+ char* tmp_value = NULL;
+ const bool success = PopBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
+ if (success)
+ *value = tmp_value; // Copy the string.
+ return success;
+}
+
+bool MessageReader::PopArray(MessageReader* sub_reader) {
+ return PopContainer(DBUS_TYPE_ARRAY, sub_reader);
+}
+
+bool MessageReader::PopStruct(MessageReader* sub_reader) {
+ return PopContainer(DBUS_TYPE_STRUCT, sub_reader);
+}
+
+bool MessageReader::PopDictEntry(MessageReader* sub_reader) {
+ return PopContainer(DBUS_TYPE_DICT_ENTRY, sub_reader);
+}
+
+bool MessageReader::PopVariant(MessageReader* sub_reader) {
+ return PopContainer(DBUS_TYPE_VARIANT, sub_reader);
+}
+
+bool MessageReader::PopArrayOfBytes(
+ std::vector<uint8>* bytes) {
+ MessageReader array_reader(message_);
+ if (!PopArray(&array_reader))
+ return false;
+ if (!array_reader.CheckType(DBUS_TYPE_BYTE))
+ return false;
+ char* values = NULL;
+ int num_values = 0;
+ dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_,
+ &values, &num_values);
+ if (!values)
+ return false;
+
+ bytes->assign(values, values + num_values); // Copy the data.
+ return true;
+}
+
+bool MessageReader::PopArrayOfObjectPaths(
+ std::vector<std::string> *object_paths) {
+ MessageReader array_reader(message_);
+ if (!PopArray(&array_reader))
+ return false;
+ while (array_reader.HasMore()) {
+ std::string object_path;
+ if (!array_reader.PopObjectPath(&object_path))
+ return false;
+ object_paths->push_back(object_path);
+ }
+ return true;
+}
+
+bool MessageReader::PopVariantOfByte(uint8* value) {
+ return PopVariantOfBasic(DBUS_TYPE_BYTE, value);
+}
+
+bool MessageReader::PopVariantOfBool(bool* value) {
+ return PopVariantOfBasic(DBUS_TYPE_BOOLEAN, value);
+}
+
+bool MessageReader::PopVariantOfInt16(int16* value) {
+ return PopVariantOfBasic(DBUS_TYPE_INT16, value);
+}
+
+bool MessageReader::PopVariantOfUint16(uint16* value) {
+ return PopVariantOfBasic(DBUS_TYPE_UINT16, value);
+}
+
+bool MessageReader::PopVariantOfInt32(int32* value) {
+ return PopVariantOfBasic(DBUS_TYPE_INT32, value);
+}
+
+bool MessageReader::PopVariantOfUint32(uint32* value) {
+ return PopVariantOfBasic(DBUS_TYPE_UINT32, value);
+}
+
+bool MessageReader::PopVariantOfInt64(int64* value) {
+ return PopVariantOfBasic(DBUS_TYPE_INT64, value);
+}
+
+bool MessageReader::PopVariantOfUint64(uint64* value) {
+ return PopVariantOfBasic(DBUS_TYPE_UINT64, value);
+}
+
+bool MessageReader::PopVariantOfDouble(double* value) {
+ return PopVariantOfBasic(DBUS_TYPE_DOUBLE, value);
+}
+
+bool MessageReader::PopVariantOfString(std::string* value) {
+ char* tmp_value = NULL;
+ const bool success = PopVariantOfBasic(DBUS_TYPE_STRING, &tmp_value);
+ if (success)
+ *value = tmp_value; // Copy the string.
+ return success;
+}
+
+bool MessageReader::PopVariantOfObjectPath(std::string* value) {
+ char* tmp_value = NULL;
+ const bool success = PopVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
+ if (success)
+ *value = tmp_value; // Copy the string.
+ return success;
+}
+
+Message::Type MessageReader::GetType() {
+ const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
+ return static_cast<Message::Type>(dbus_type);
+}
+
+bool MessageReader::CheckType(int dbus_type) {
+ const int actual_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
+ if (actual_type != dbus_type) {
+ VLOG(1) << "Type " << dbus_type << " is expected but got "
+ << actual_type;
+ return false;
+ }
+ return true;
+}
+
+bool MessageReader::PopBasic(int dbus_type, void* value) {
+ if (!CheckType(dbus_type))
+ return false;
+ dbus_message_iter_get_basic(&raw_message_iter_, value);
+ dbus_message_iter_next(&raw_message_iter_);
+ return true;
+}
+
+bool MessageReader::PopContainer(int dbus_type, MessageReader* sub_reader) {
+ DCHECK_NE(this, sub_reader);
+
+ if (!CheckType(dbus_type))
+ return false;
+ dbus_message_iter_recurse(&raw_message_iter_,
+ &sub_reader->raw_message_iter_);
+ dbus_message_iter_next(&raw_message_iter_);
+ return true;
+}
+
+bool MessageReader::PopVariantOfBasic(int dbus_type, void* value) {
+ net::dbus::MessageReader variant_reader(message_);
+ if (!PopVariant(&variant_reader))
+ return false;
+ return variant_reader.PopBasic(dbus_type, value);
+}
+
+} // namespace dbus
+} // namespace net
« no previous file with comments | « 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