Chromium Code Reviews| Index: net/dbus/dbus.cc |
| diff --git a/net/dbus/dbus.cc b/net/dbus/dbus.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..09ad1f938c17dbf0f6b23c8413ecbcdbb9d9d07b |
| --- /dev/null |
| +++ b/net/dbus/dbus.cc |
| @@ -0,0 +1,384 @@ |
| +// 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/logging.h" |
| + |
| +namespace net { |
| +namespace dbus { |
| + |
| +// |
| +// Bus implementation. |
| +// |
| + |
| +Bus::Bus(Type type) |
| + : type_(type), |
| + connection_(NULL) { |
| +} |
| + |
| +Bus::~Bus() { |
| +} |
| + |
| +bool Bus::Init() { |
| + // Check if it's already initialized. |
| + if (connection_) |
| + return true; |
| + |
| + DBusError error = {}; |
| + dbus_error_init(&error); |
| + |
| + // If returning a newly-created connection, this function will block |
| + // until authentication and bus registration are complete. |
| + connection_ = dbus_bus_get(static_cast<DBusBusType>(type_), &error); |
|
John Knottenbelt
2011/07/19 09:34:01
Reading the docs for bus, this will return an exis
satorux1
2011/07/19 16:45:06
That's a good point. I'm going to provide an optio
|
| + if (!connection_) { |
| + if (dbus_error_is_set(&error)) { |
| + LOG(ERROR) << error.message; |
| + } |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| +ObjectProxy* Bus::GetObjectProxy(const std::string& service_name, |
| + const std::string& object_path) { |
| + return new ObjectProxy(this, service_name, object_path); |
| +} |
| + |
| +// |
| +// Message implementation. |
| +// |
| + |
| +Message::Message() |
| + : raw_message_(NULL) { |
| +} |
| + |
| +Message::~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; |
| +} |
| + |
| +MethodCall::MethodCall() : Message() { |
| + reset_raw_message(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL)); |
| +} |
| + |
| +Response::Response() : Message() { |
| +} |
| + |
| +// |
| +// MessageBuilder implementation. |
| +// |
| + |
| +MessageBuilder::MessageBuilder(Message* message) : |
| + message_(message) { |
| + dbus_message_iter_init_append(message_->raw_message(), &raw_message_iter_); |
| +} |
| + |
| + |
| +MessageBuilder::~MessageBuilder() { |
| +} |
| + |
| +void MessageBuilder::AppendByte(uint8 value) { |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_BYTE, &value); |
| +} |
| + |
| +void MessageBuilder::AppendBool(bool value) { |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_BOOLEAN, &value); |
| +} |
| + |
| +void MessageBuilder::AppendInt16(int16 value) { |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_INT16, &value); |
| +} |
| + |
| +void MessageBuilder::AppendUint16(uint16 value) { |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_UINT16, &value); |
| +} |
| + |
| +void MessageBuilder::AppendInt32(int32 value) { |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_INT32, &value); |
| +} |
| + |
| +void MessageBuilder::AppendUint32(uint32 value) { |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_UINT32, &value); |
| +} |
| + |
| +void MessageBuilder::AppendInt64(int64 value) { |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_INT64, &value); |
| +} |
| + |
| +void MessageBuilder::AppendUint64(uint64 value) { |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_UINT64, &value); |
| +} |
| + |
| +void MessageBuilder::AppendDouble(double value) { |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_DOUBLE, &value); |
| +} |
| + |
| +void MessageBuilder::AppendString(const std::string& value) { |
| + const char* pointer = value.c_str(); |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_STRING, &pointer); |
| +} |
| + |
| +void MessageBuilder::AppendObjectPath(const std::string& value) { |
| + const char* pointer = value.c_str(); |
| + dbus_message_iter_append_basic( |
| + &raw_message_iter_, DBUS_TYPE_OBJECT_PATH, &pointer); |
| +} |
| + |
| +// |
| +// 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::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; |
| +} |
| + |
| +bool MessageReader::CheckType(int dbus_type) { |
| + const int actual_type = dbus_message_iter_get_arg_type(&raw_message_iter_); |
| + if (actual_type != dbus_type) { |
| + LOG(ERROR) << "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) { |
| + CHECK_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); |
| +} |
| + |
| +// |
| +// 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() { |
| +} |
| + |
| +bool ObjectProxy::CallMethodSync(const std::string interface_name, |
| + const std::string method_name, |
| + MethodCall* request, |
| + Response* response) { |
| + if (!bus_->Init()) |
| + return false; |
| + |
| + DBusMessage* request_message = request->raw_message(); |
| + if (!dbus_message_set_destination(request_message, service_name_.c_str())) |
| + return false; |
| + if (!dbus_message_set_path(request_message, object_path_.c_str())) |
| + return false; |
| + if (!dbus_message_set_interface(request_message, interface_name.c_str())) |
| + return false; |
| + if (!dbus_message_set_member(request_message, method_name.c_str())) |
| + return false; |
| + |
| + 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; |
| +} |
| + |
| +} // namespace dbus |
| +} // namespace net |