blob: 830cab63150fa6d452790ac2b91c0a9fdd5bc54f [file] [log] [blame]
// Copyright (c) 2009 The Chromium OS 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 "debugd/src/dbus_utils.h"
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/values.h>
#include <dbus/dbus.h>
#include <dbus-c++/dbus.h>
using base::DictionaryValue;
using base::FundamentalValue;
using base::ListValue;
using base::StringValue;
using base::Value;
namespace {
bool DBusMessageIterToValue(DBus::MessageIter* iter, Value** result);
bool DBusMessageIterToPrimitiveValue(DBus::MessageIter* iter, Value** result) {
DBus::MessageIter subiter;
switch (iter->type()) {
case DBUS_TYPE_BYTE:
*result = new FundamentalValue(iter->get_byte());
return true;
case DBUS_TYPE_BOOLEAN:
*result = new FundamentalValue(iter->get_bool());
return true;
case DBUS_TYPE_INT16:
*result = new FundamentalValue(iter->get_int16());
return true;
case DBUS_TYPE_UINT16:
*result = new FundamentalValue(iter->get_uint16());
return true;
case DBUS_TYPE_INT32:
*result = new FundamentalValue(iter->get_int32());
return true;
case DBUS_TYPE_UINT32:
*result = new StringValue(base::UintToString(iter->get_uint32()));
return true;
case DBUS_TYPE_INT64:
*result = new StringValue(base::Int64ToString(iter->get_int64()));
return true;
case DBUS_TYPE_UINT64:
*result = new StringValue(base::Uint64ToString(iter->get_uint64()));
return true;
case DBUS_TYPE_DOUBLE:
*result = new FundamentalValue(iter->get_double());
return true;
case DBUS_TYPE_STRING:
*result = new StringValue(iter->get_string());
return true;
case DBUS_TYPE_OBJECT_PATH:
*result = new StringValue(iter->get_path());
return true;
case DBUS_TYPE_SIGNATURE:
*result = new StringValue(iter->get_signature());
return true;
case DBUS_TYPE_UNIX_FD:
*result = new FundamentalValue(iter->get_int32());
return true;
case DBUS_TYPE_VARIANT:
subiter = iter->recurse();
return DBusMessageIterToValue(&subiter, result);
default:
LOG(ERROR) << "Unhandled primitive type: " << iter->type();
return false;
}
}
bool DBusMessageIterToArrayValue(DBus::MessageIter* iter, Value** result) {
// For an array, create an empty ListValue, then recurse into it.
ListValue* lv = new ListValue();
while (!iter->at_end()) {
Value* subvalue = NULL;
bool r = DBusMessageIterToValue(iter, &subvalue);
if (!r) {
delete lv;
return false;
}
lv->Append(subvalue);
(*iter)++;
}
*result = lv;
return true;
}
bool DBusMessageIterToDictValue(DBus::MessageIter* iter, Value** result) {
// For a dict, create an empty DictionaryValue, then walk the subcontainers
// with the key-value pairs, adding them to the dict.
DictionaryValue* dv = new DictionaryValue();
while (!iter->at_end()) {
DBus::MessageIter subiter = iter->recurse();
Value* key = NULL;
Value* value = NULL;
bool r = DBusMessageIterToValue(&subiter, &key);
if (!r || key->GetType() != Value::TYPE_STRING) {
delete dv;
return false;
}
subiter++;
r = DBusMessageIterToValue(&subiter, &value);
if (!r) {
delete key;
delete dv;
return false;
}
std::string keystr;
key->GetAsString(&keystr);
dv->Set(keystr, value);
delete key;
(*iter)++;
}
*result = dv;
return true;
}
bool DBusMessageIterToValue(DBus::MessageIter* iter, Value** result) {
if (iter->at_end()) {
*result = NULL;
return true;
}
if (!iter->is_array() && !iter->is_dict()) {
// Primitive type. Stash it in result directly and return.
return DBusMessageIterToPrimitiveValue(iter, result);
}
if (iter->is_dict()) {
DBus::MessageIter subiter = iter->recurse();
return DBusMessageIterToDictValue(&subiter, result);
}
if (iter->is_array()) {
DBus::MessageIter subiter = iter->recurse();
return DBusMessageIterToArrayValue(&subiter, result);
}
return false;
}
} // namespace
bool debugd::DBusMessageToValue(const DBus::Message& message, Value** v) {
DBus::MessageIter r = message.reader();
return DBusMessageIterToArrayValue(&r, v);
}
bool debugd::DBusPropertyMapToValue(
const std::map<std::string, DBus::Variant>& properties, Value** v) {
DictionaryValue* dv = new DictionaryValue();
std::map<std::string, DBus::Variant>::const_iterator it;
for (it = properties.begin(); it != properties.end(); ++it) {
Value* v = NULL;
// make a copy so we can take a reference to the MessageIter
DBus::MessageIter reader = it->second.reader();
bool r = DBusMessageIterToValue(&reader, &v);
if (!r) {
delete dv;
return false;
}
dv->Set(it->first, v);
}
*v = dv;
return true;
}