message.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/message.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stringprintf.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "dbus/object_path.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_SYSTEM_PROTOBUF)
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <google/protobuf/message_lite.h>
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/protobuf/src/google/protobuf/message_lite.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Appends the header name and the value to |output|, if the value is
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not empty.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppendStringHeader(const std::string& header_name,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const std::string& header_value,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        std::string* output) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!header_value.empty()) {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *output += header_name + ": " + header_value + "\n";
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Appends the header name and the value to |output|, if the value is
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// nonzero.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppendUint32Header(const std::string& header_name,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        uint32 header_value,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        std::string* output) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (header_value != 0) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *output += (header_name + ": " + base::StringPrintf("%u", header_value) +
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "\n");
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace dbus {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsDBusTypeUnixFdSupported() {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int major = 0, minor = 0, micro = 0;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_get_version(&major, &minor, &micro);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return major >= 1 && minor >= 4;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message::Message()
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : raw_message_(NULL) {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message::~Message() {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (raw_message_)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus_message_unref(raw_message_);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Message::Init(DBusMessage* raw_message) {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!raw_message_);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_message_ = raw_message;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message::MessageType Message::GetMessageType() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!raw_message_)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MESSAGE_INVALID;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int type = dbus_message_get_type(raw_message_);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<Message::MessageType>(type);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Message::GetMessageTypeAsString() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (GetMessageType()) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MESSAGE_INVALID:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "MESSAGE_INVALID";
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MESSAGE_METHOD_CALL:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "MESSAGE_METHOD_CALL";
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MESSAGE_METHOD_RETURN:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "MESSAGE_METHOD_RETURN";
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MESSAGE_SIGNAL:
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "MESSAGE_SIGNAL";
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MESSAGE_ERROR:
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return "MESSAGE_ERROR";
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "";
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Message::ToStringInternal(const std::string& indent,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      MessageReader* reader) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* kBrokenMessage = "[broken message]";
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (reader->HasMoreData()) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const DataType type = reader->GetDataType();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (type) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case BYTE: {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint8 value = 0;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopByte(&value))
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "byte " + base::StringPrintf("%d", value) + "\n";
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case BOOL: {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool value = false;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopBool(&value))
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "bool " + (value ? "true" : "false") + "\n";
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case INT16: {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int16 value = 0;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopInt16(&value))
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "int16 " + base::StringPrintf("%d", value) + "\n";
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case UINT16: {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint16 value = 0;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopUint16(&value))
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "uint16 " + base::StringPrintf("%d", value) + "\n";
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case INT32: {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int32 value = 0;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopInt32(&value))
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "int32 " + base::StringPrintf("%d", value) + "\n";
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case UINT32: {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint32 value = 0;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopUint32(&value))
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "uint32 " + base::StringPrintf("%u", value) + "\n";
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case INT64: {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int64 value = 0;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopInt64(&value))
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += (indent + "int64 " +
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::StringPrintf("%" PRId64, value) + "\n");
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case UINT64: {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        uint64 value = 0;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopUint64(&value))
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += (indent + "uint64 " +
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::StringPrintf("%" PRIu64, value) + "\n");
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case DOUBLE: {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        double value = 0;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopDouble(&value))
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "double " + base::StringPrintf("%f", value) + "\n";
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STRING: {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string value;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopString(&value))
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Truncate if the string is longer than the limit.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const size_t kTruncateLength = 100;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (value.size() < kTruncateLength) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output += indent + "string \"" + value + "\"\n";
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          std::string truncated;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          TruncateUTF8ToByteSize(value, kTruncateLength, &truncated);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::StringAppendF(&truncated, "... (%"PRIuS" bytes in total)",
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              value.size());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          output += indent + "string \"" + truncated + "\"\n";
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case OBJECT_PATH: {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ObjectPath value;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopObjectPath(&value))
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "object_path \"" + value.value() + "\"\n";
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case ARRAY: {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MessageReader sub_reader(this);
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopArray(&sub_reader))
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "array [\n";
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += ToStringInternal(indent + "  ", &sub_reader);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "]\n";
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STRUCT: {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MessageReader sub_reader(this);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopStruct(&sub_reader))
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "struct {\n";
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += ToStringInternal(indent + "  ", &sub_reader);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "}\n";
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case DICT_ENTRY: {
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MessageReader sub_reader(this);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopDictEntry(&sub_reader))
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "dict entry {\n";
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += ToStringInternal(indent + "  ", &sub_reader);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "}\n";
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case VARIANT: {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MessageReader sub_reader(this);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopVariant(&sub_reader))
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "variant ";
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += ToStringInternal(indent + "  ", &sub_reader);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case UNIX_FD: {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHECK(IsDBusTypeUnixFdSupported());
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FileDescriptor file_descriptor;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!reader->PopFileDescriptor(&file_descriptor))
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return kBrokenMessage;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output += indent + "fd#" +
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  base::StringPrintf("%d", file_descriptor.value()) + "\n";
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(FATAL) << "Unknown type: " << type;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return output;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The returned string consists of message headers such as
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// destination if any, followed by a blank line, and the message
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// payload. For example, a MethodCall's ToString() will look like:
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// destination: com.example.Service
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// path: /com/example/Object
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// interface: com.example.Interface
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// member: SomeMethod
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// string \"payload\"
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ...
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Message::ToString() {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!raw_message_)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return "";
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate headers first.
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string headers;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendStringHeader("message_type", GetMessageTypeAsString(), &headers);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendStringHeader("destination", GetDestination(), &headers);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendStringHeader("path", GetPath().value(), &headers);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendStringHeader("interface", GetInterface(), &headers);
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendStringHeader("member", GetMember(), &headers);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendStringHeader("error_name", GetErrorName(), &headers);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendStringHeader("sender", GetSender(), &headers);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendStringHeader("signature", GetSignature(), &headers);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendUint32Header("serial", GetSerial(), &headers);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendUint32Header("reply_serial", GetReplySerial(), &headers);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate the payload.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageReader reader(this);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return headers + "\n" + ToStringInternal("", &reader);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Message::SetDestination(const std::string& destination) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dbus_message_set_destination(raw_message_, destination.c_str());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Message::SetPath(const ObjectPath& path) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dbus_message_set_path(raw_message_, path.value().c_str());
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Message::SetInterface(const std::string& interface) {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dbus_message_set_interface(raw_message_, interface.c_str());
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Message::SetMember(const std::string& member) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dbus_message_set_member(raw_message_, member.c_str());
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Message::SetErrorName(const std::string& error_name) {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dbus_message_set_error_name(raw_message_, error_name.c_str());
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Message::SetSender(const std::string& sender) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dbus_message_set_sender(raw_message_, sender.c_str());
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Message::SetSerial(uint32 serial) {
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_message_set_serial(raw_message_, serial);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Message::SetReplySerial(uint32 reply_serial) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_message_set_reply_serial(raw_message_, reply_serial);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Message::GetDestination() {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* destination = dbus_message_get_destination(raw_message_);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return destination ? destination : "";
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObjectPath Message::GetPath() {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* path = dbus_message_get_path(raw_message_);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ObjectPath(path ? path : "");
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Message::GetInterface() {
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* interface = dbus_message_get_interface(raw_message_);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return interface ? interface : "";
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Message::GetMember() {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* member = dbus_message_get_member(raw_message_);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return member ? member : "";
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Message::GetErrorName() {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* error_name = dbus_message_get_error_name(raw_message_);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error_name ? error_name : "";
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Message::GetSender() {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* sender = dbus_message_get_sender(raw_message_);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return sender ? sender : "";
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string Message::GetSignature() {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* signature = dbus_message_get_signature(raw_message_);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return signature ? signature : "";
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 Message::GetSerial() {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dbus_message_get_serial(raw_message_);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 Message::GetReplySerial() {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dbus_message_get_reply_serial(raw_message_);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MethodCall implementation.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MethodCall::MethodCall(const std::string& interface_name,
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& method_name)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Message() {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_CALL));
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(SetInterface(interface_name));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(SetMember(method_name));
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MethodCall::MethodCall() : Message() {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MethodCall* MethodCall::FromRawMessage(DBusMessage* raw_message) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(DBUS_MESSAGE_TYPE_METHOD_CALL, dbus_message_get_type(raw_message));
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MethodCall* method_call = new MethodCall;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  method_call->Init(raw_message);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return method_call;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Signal implementation.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Signal::Signal(const std::string& interface_name,
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               const std::string& method_name)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : Message() {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(dbus_message_new(DBUS_MESSAGE_TYPE_SIGNAL));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(SetInterface(interface_name));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(SetMember(method_name));
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Signal::Signal() : Message() {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Signal* Signal::FromRawMessage(DBusMessage* raw_message) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(DBUS_MESSAGE_TYPE_SIGNAL, dbus_message_get_type(raw_message));
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Signal* signal = new Signal;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  signal->Init(raw_message);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return signal;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Response implementation.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Response::Response() : Message() {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<Response> Response::FromRawMessage(DBusMessage* raw_message) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(DBUS_MESSAGE_TYPE_METHOD_RETURN,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            dbus_message_get_type(raw_message));
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Response> response(new Response);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->Init(raw_message);
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return response.Pass();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<Response> Response::FromMethodCall(MethodCall* method_call) {
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Response> response(new Response);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->Init(dbus_message_new_method_return(method_call->raw_message()));
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return response.Pass();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<Response> Response::CreateEmpty() {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Response> response(new Response);
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->Init(dbus_message_new(DBUS_MESSAGE_TYPE_METHOD_RETURN));
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return response.Pass();
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ErrorResponse implementation.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ErrorResponse::ErrorResponse() : Response() {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<ErrorResponse> ErrorResponse::FromRawMessage(
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DBusMessage* raw_message) {
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(DBUS_MESSAGE_TYPE_ERROR, dbus_message_get_type(raw_message));
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ErrorResponse> response(new ErrorResponse);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->Init(raw_message);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return response.Pass();
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)scoped_ptr<ErrorResponse> ErrorResponse::FromMethodCall(
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MethodCall* method_call,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error_name,
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& error_message) {
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<ErrorResponse> response(new ErrorResponse);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->Init(dbus_message_new_error(method_call->raw_message(),
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        error_name.c_str(),
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        error_message.c_str()));
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return response.Pass();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessageWriter implementation.
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageWriter::MessageWriter(Message* message) :
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    message_(message),
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    container_is_open_(false) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&raw_message_iter_, 0, sizeof(raw_message_iter_));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus_message_iter_init_append(message_->raw_message(), &raw_message_iter_);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageWriter::~MessageWriter() {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendByte(uint8 value) {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_BYTE, &value);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendBool(bool value) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The size of dbus_bool_t and the size of bool are different. The
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // former is always 4 per dbus-types.h, whereas the latter is usually 1.
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dbus_message_iter_append_basic() used in AppendBasic() expects four
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bytes for DBUS_TYPE_BOOLEAN, so we must pass a dbus_bool_t, instead
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of a bool, to AppendBasic().
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_bool_t dbus_value = value;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendInt16(int16 value) {
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_INT16, &value);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendUint16(uint16 value) {
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_UINT16, &value);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendInt32(int32 value) {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_INT32, &value);
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendUint32(uint32 value) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_UINT32, &value);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendInt64(int64 value) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_INT64, &value);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendUint64(uint64 value) {
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_UINT64, &value);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendDouble(double value) {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_DOUBLE, &value);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendString(const std::string& value) {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // D-Bus Specification (0.19) says a string "must be valid UTF-8".
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(IsStringUTF8(value));
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* pointer = value.c_str();
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_STRING, &pointer);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(satorux): It may make sense to return an error here, as the
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // input string can be large. If needed, we could add something like
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bool AppendStringWithErrorChecking().
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendObjectPath(const ObjectPath& value) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(value.IsValid());
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* pointer = value.value().c_str();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_OBJECT_PATH, &pointer);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ideally, client shouldn't need to supply the signature string, but
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the underlying D-Bus library requires us to supply this before
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// appending contents to array and variant. It's technically possible
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for us to design API that doesn't require the signature but it will
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// complicate the implementation so we decided to have the signature
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// parameter. Hopefully, variants are less used in request messages from
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// client side than response message from server side, so this should
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not be a big issue.
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::OpenArray(const std::string& signature,
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              MessageWriter* writer) {
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!container_is_open_);
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_message_iter_open_container(
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &raw_message_iter_,
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DBUS_TYPE_ARRAY,
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      signature.c_str(),
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &writer->raw_message_iter_);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  container_is_open_ = true;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::OpenVariant(const std::string& signature,
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                MessageWriter* writer) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!container_is_open_);
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_message_iter_open_container(
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &raw_message_iter_,
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DBUS_TYPE_VARIANT,
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      signature.c_str(),
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &writer->raw_message_iter_);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  container_is_open_ = true;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::OpenStruct(MessageWriter* writer) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!container_is_open_);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_message_iter_open_container(
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &raw_message_iter_,
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DBUS_TYPE_STRUCT,
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL,  // Signature should be NULL.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &writer->raw_message_iter_);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  container_is_open_ = true;
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::OpenDictEntry(MessageWriter* writer) {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!container_is_open_);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_message_iter_open_container(
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &raw_message_iter_,
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DBUS_TYPE_DICT_ENTRY,
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL,  // Signature should be NULL.
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &writer->raw_message_iter_);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  container_is_open_ = true;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::CloseContainer(MessageWriter* writer) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(container_is_open_);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_message_iter_close_container(
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &raw_message_iter_, &writer->raw_message_iter_);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  container_is_open_ = false;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendArrayOfBytes(const uint8* values, size_t length) {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!container_is_open_);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageWriter array_writer(message_);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenArray("y", &array_writer);
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_message_iter_append_fixed_array(
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &(array_writer.raw_message_iter_),
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DBUS_TYPE_BYTE,
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &values,
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<int>(length));
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseContainer(&array_writer);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendArrayOfStrings(
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<std::string>& strings) {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!container_is_open_);
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageWriter array_writer(message_);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenArray("s", &array_writer);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < strings.size(); ++i) {
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    array_writer.AppendString(strings[i]);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseContainer(&array_writer);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendArrayOfObjectPaths(
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<ObjectPath>& object_paths) {
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!container_is_open_);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageWriter array_writer(message_);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenArray("o", &array_writer);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < object_paths.size(); ++i) {
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    array_writer.AppendObjectPath(object_paths[i]);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseContainer(&array_writer);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageWriter::AppendProtoAsArrayOfBytes(
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const google::protobuf::MessageLite& protobuf) {
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string serialized_proto;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!protobuf.SerializeToString(&serialized_proto)) {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Unable to serialize supplied protocol buffer";
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendArrayOfBytes(reinterpret_cast<const uint8*>(serialized_proto.data()),
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     serialized_proto.size());
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfByte(uint8 value) {
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_BYTE, &value);
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfBool(bool value) {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See the comment at MessageWriter::AppendBool().
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_bool_t dbus_value = value;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfInt16(int16 value) {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_INT16, &value);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfUint16(uint16 value) {
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_UINT16, &value);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfInt32(int32 value) {
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_INT32, &value);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfUint32(uint32 value) {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_UINT32, &value);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfInt64(int64 value) {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_INT64, &value);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfUint64(uint64 value) {
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_UINT64, &value);
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfDouble(double value) {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_DOUBLE, &value);
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfString(const std::string& value) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* pointer = value.c_str();
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_STRING, &pointer);
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfObjectPath(const ObjectPath& value) {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* pointer = value.value().c_str();
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &pointer);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendBasic(int dbus_type, const void* value) {
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!container_is_open_);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = dbus_message_iter_append_basic(
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &raw_message_iter_, dbus_type, value);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dbus_message_iter_append_basic() fails only when there is not enough
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // memory. We don't return this error as there is nothing we can do when
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it fails to allocate memory for a byte etc.
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(success) << "Unable to allocate memory";
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendVariantOfBasic(int dbus_type, const void* value) {
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string signature = base::StringPrintf("%c", dbus_type);
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageWriter variant_writer(message_);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OpenVariant(signature, &variant_writer);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  variant_writer.AppendBasic(dbus_type, value);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloseContainer(&variant_writer);
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessageWriter::AppendFileDescriptor(const FileDescriptor& value) {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(IsDBusTypeUnixFdSupported());
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value.is_valid()) {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // NB: sending a directory potentially enables sandbox escape
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL) << "Attempt to pass invalid file descriptor";
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd = value.value();
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppendBasic(DBUS_TYPE_UNIX_FD, &fd);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessageReader implementation.
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageReader::MessageReader(Message* message)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : message_(message) {
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&raw_message_iter_, 0, sizeof(raw_message_iter_));
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (message)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dbus_message_iter_init(message_->raw_message(), &raw_message_iter_);
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessageReader::~MessageReader() {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::HasMoreData() {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dbus_type != DBUS_TYPE_INVALID;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopByte(uint8* value) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopBasic(DBUS_TYPE_BYTE, value);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopBool(bool* value) {
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Like MessageWriter::AppendBool(), we should copy |value| to
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dbus_bool_t, as dbus_message_iter_get_basic() used in PopBasic()
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // expects four bytes for DBUS_TYPE_BOOLEAN.
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_bool_t dbus_value = FALSE;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = PopBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *value = static_cast<bool>(dbus_value);
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopInt16(int16* value) {
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopBasic(DBUS_TYPE_INT16, value);
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopUint16(uint16* value) {
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopBasic(DBUS_TYPE_UINT16, value);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopInt32(int32* value) {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopBasic(DBUS_TYPE_INT32, value);
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopUint32(uint32* value) {
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopBasic(DBUS_TYPE_UINT32, value);
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopInt64(int64* value) {
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopBasic(DBUS_TYPE_INT64, value);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopUint64(uint64* value) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopBasic(DBUS_TYPE_UINT64, value);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopDouble(double* value) {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopBasic(DBUS_TYPE_DOUBLE, value);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopString(std::string* value) {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* tmp_value = NULL;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = PopBasic(DBUS_TYPE_STRING, &tmp_value);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value->assign(tmp_value);
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopObjectPath(ObjectPath* value) {
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* tmp_value = NULL;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = PopBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *value = ObjectPath(tmp_value);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopArray(MessageReader* sub_reader) {
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopContainer(DBUS_TYPE_ARRAY, sub_reader);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopStruct(MessageReader* sub_reader) {
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopContainer(DBUS_TYPE_STRUCT, sub_reader);
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopDictEntry(MessageReader* sub_reader) {
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopContainer(DBUS_TYPE_DICT_ENTRY, sub_reader);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariant(MessageReader* sub_reader) {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopContainer(DBUS_TYPE_VARIANT, sub_reader);
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopArrayOfBytes(uint8** bytes, size_t* length) {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageReader array_reader(message_);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!PopArray(&array_reader))
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An empty array is allowed.
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!array_reader.HasMoreData()) {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *length = 0;
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *bytes = NULL;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!array_reader.CheckDataType(DBUS_TYPE_BYTE))
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int int_length = 0;
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_message_iter_get_fixed_array(&array_reader.raw_message_iter_,
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    bytes,
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &int_length);
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *length = static_cast<int>(int_length);
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopArrayOfStrings(
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string> *strings) {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageReader array_reader(message_);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!PopArray(&array_reader))
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (array_reader.HasMoreData()) {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string string;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!array_reader.PopString(&string))
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    strings->push_back(string);
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopArrayOfObjectPaths(
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<ObjectPath> *object_paths) {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageReader array_reader(message_);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!PopArray(&array_reader))
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (array_reader.HasMoreData()) {
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ObjectPath object_path;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!array_reader.PopObjectPath(&object_path))
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    object_paths->push_back(object_path);
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopArrayOfBytesAsProto(
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    google::protobuf::MessageLite* protobuf) {
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(protobuf != NULL);
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* serialized_buf = NULL;
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t buf_size = 0;
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!PopArrayOfBytes(reinterpret_cast<uint8**>(&serialized_buf), &buf_size)) {
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Error reading array of bytes";
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!protobuf->ParseFromArray(serialized_buf, buf_size)) {
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to parse protocol buffer from array";
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfByte(uint8* value) {
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopVariantOfBasic(DBUS_TYPE_BYTE, value);
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfBool(bool* value) {
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See the comment at MessageReader::PopBool().
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_bool_t dbus_value = FALSE;
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = PopVariantOfBasic(DBUS_TYPE_BOOLEAN, &dbus_value);
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *value = static_cast<bool>(dbus_value);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfInt16(int16* value) {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopVariantOfBasic(DBUS_TYPE_INT16, value);
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfUint16(uint16* value) {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopVariantOfBasic(DBUS_TYPE_UINT16, value);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfInt32(int32* value) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopVariantOfBasic(DBUS_TYPE_INT32, value);
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfUint32(uint32* value) {
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopVariantOfBasic(DBUS_TYPE_UINT32, value);
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfInt64(int64* value) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopVariantOfBasic(DBUS_TYPE_INT64, value);
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfUint64(uint64* value) {
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopVariantOfBasic(DBUS_TYPE_UINT64, value);
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfDouble(double* value) {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PopVariantOfBasic(DBUS_TYPE_DOUBLE, value);
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfString(std::string* value) {
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* tmp_value = NULL;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = PopVariantOfBasic(DBUS_TYPE_STRING, &tmp_value);
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success)
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value->assign(tmp_value);
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfObjectPath(ObjectPath* value) {
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* tmp_value = NULL;
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = PopVariantOfBasic(DBUS_TYPE_OBJECT_PATH, &tmp_value);
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (success)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *value = ObjectPath(tmp_value);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Message::DataType MessageReader::GetDataType() {
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int dbus_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<Message::DataType>(dbus_type);
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::CheckDataType(int dbus_type) {
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int actual_type = dbus_message_iter_get_arg_type(&raw_message_iter_);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (actual_type != dbus_type) {
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Type " << dbus_type  << " is expected but got "
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << actual_type;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopBasic(int dbus_type, void* value) {
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CheckDataType(dbus_type))
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // dbus_message_iter_get_basic() here should always work, as we have
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already checked the next item's data type in CheckDataType(). Note
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that dbus_message_iter_get_basic() is a void function.
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_message_iter_get_basic(&raw_message_iter_, value);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(value);
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_message_iter_next(&raw_message_iter_);
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopContainer(int dbus_type, MessageReader* sub_reader) {
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(this, sub_reader);
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CheckDataType(dbus_type))
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_message_iter_recurse(&raw_message_iter_,
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &sub_reader->raw_message_iter_);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus_message_iter_next(&raw_message_iter_);
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopVariantOfBasic(int dbus_type, void* value) {
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dbus::MessageReader variant_reader(message_);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!PopVariant(&variant_reader))
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return variant_reader.PopBasic(dbus_type, value);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessageReader::PopFileDescriptor(FileDescriptor* value) {
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(IsDBusTypeUnixFdSupported());
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fd = -1;
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool success = PopBasic(DBUS_TYPE_UNIX_FD, &fd);
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!success)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->PutValue(fd);
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NB: the caller must check validity before using the value
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace dbus
989