1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ipc/ipc_message_utils.h"
7 #include "base/file_path.h"
8 #include "base/json/json_writer.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/nullable_string16.h"
11 #include "base/string_number_conversions.h"
12 #include "base/time.h"
13 #include "base/utf_string_conversions.h"
14 #include "base/values.h"
16 #include "ipc/file_descriptor_set_posix.h"
18 #include "ipc/ipc_channel_handle.h"
22 const int kMaxRecursionDepth
= 100;
24 // Value serialization
26 static bool ReadValue(const Message
* m
, void** iter
, Value
** value
,
29 static void WriteValue(Message
* m
, const Value
* value
, int recursion
) {
30 if (recursion
> kMaxRecursionDepth
) {
31 LOG(WARNING
) << "Max recursion depth hit in WriteValue.";
35 m
->WriteInt(value
->GetType());
37 switch (value
->GetType()) {
38 case Value::TYPE_NULL
:
40 case Value::TYPE_BOOLEAN
: {
42 value
->GetAsBoolean(&val
);
46 case Value::TYPE_INTEGER
: {
48 value
->GetAsInteger(&val
);
52 case Value::TYPE_DOUBLE
: {
54 value
->GetAsDouble(&val
);
58 case Value::TYPE_STRING
: {
60 value
->GetAsString(&val
);
64 case Value::TYPE_BINARY
: {
65 const BinaryValue
* binary
= static_cast<const BinaryValue
*>(value
);
66 m
->WriteData(binary
->GetBuffer(), static_cast<int>(binary
->GetSize()));
69 case Value::TYPE_DICTIONARY
: {
70 const DictionaryValue
* dict
= static_cast<const DictionaryValue
*>(value
);
72 WriteParam(m
, static_cast<int>(dict
->size()));
74 for (DictionaryValue::key_iterator it
= dict
->begin_keys();
75 it
!= dict
->end_keys(); ++it
) {
77 if (dict
->GetWithoutPathExpansion(*it
, &subval
)) {
79 WriteValue(m
, subval
, recursion
+ 1);
81 NOTREACHED() << "DictionaryValue iterators are filthy liars.";
86 case Value::TYPE_LIST
: {
87 const ListValue
* list
= static_cast<const ListValue
*>(value
);
88 WriteParam(m
, static_cast<int>(list
->GetSize()));
89 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
91 if (list
->Get(i
, &subval
)) {
92 WriteValue(m
, subval
, recursion
+ 1);
94 NOTREACHED() << "ListValue::GetSize is a filthy liar.";
102 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated
104 static bool ReadDictionaryValue(const Message
* m
, void** iter
,
105 DictionaryValue
* value
, int recursion
) {
107 if (!ReadParam(m
, iter
, &size
))
110 for (int i
= 0; i
< size
; ++i
) {
113 if (!ReadParam(m
, iter
, &key
) ||
114 !ReadValue(m
, iter
, &subval
, recursion
+ 1))
116 value
->Set(key
, subval
);
122 // Helper for ReadValue that reads a ReadListValue into a pre-allocated
124 static bool ReadListValue(const Message
* m
, void** iter
,
125 ListValue
* value
, int recursion
) {
127 if (!ReadParam(m
, iter
, &size
))
130 for (int i
= 0; i
< size
; ++i
) {
132 if (!ReadValue(m
, iter
, &subval
, recursion
+ 1))
134 value
->Set(i
, subval
);
140 static bool ReadValue(const Message
* m
, void** iter
, Value
** value
,
142 if (recursion
> kMaxRecursionDepth
) {
143 LOG(WARNING
) << "Max recursion depth hit in ReadValue.";
148 if (!ReadParam(m
, iter
, &type
))
152 case Value::TYPE_NULL
:
153 *value
= Value::CreateNullValue();
155 case Value::TYPE_BOOLEAN
: {
157 if (!ReadParam(m
, iter
, &val
))
159 *value
= Value::CreateBooleanValue(val
);
162 case Value::TYPE_INTEGER
: {
164 if (!ReadParam(m
, iter
, &val
))
166 *value
= Value::CreateIntegerValue(val
);
169 case Value::TYPE_DOUBLE
: {
171 if (!ReadParam(m
, iter
, &val
))
173 *value
= Value::CreateDoubleValue(val
);
176 case Value::TYPE_STRING
: {
178 if (!ReadParam(m
, iter
, &val
))
180 *value
= Value::CreateStringValue(val
);
183 case Value::TYPE_BINARY
: {
186 if (!m
->ReadData(iter
, &data
, &length
))
188 *value
= BinaryValue::CreateWithCopiedBuffer(data
, length
);
191 case Value::TYPE_DICTIONARY
: {
192 scoped_ptr
<DictionaryValue
> val(new DictionaryValue());
193 if (!ReadDictionaryValue(m
, iter
, val
.get(), recursion
))
195 *value
= val
.release();
198 case Value::TYPE_LIST
: {
199 scoped_ptr
<ListValue
> val(new ListValue());
200 if (!ReadListValue(m
, iter
, val
.get(), recursion
))
202 *value
= val
.release();
212 void ParamTraits
<int>::Log(const param_type
& p
, std::string
* l
) {
213 l
->append(base::IntToString(p
));
216 void ParamTraits
<unsigned int>::Log(const param_type
& p
, std::string
* l
) {
217 l
->append(base::UintToString(p
));
220 void ParamTraits
<long>::Log(const param_type
& p
, std::string
* l
) {
221 l
->append(base::Int64ToString(static_cast<int64
>(p
)));
224 void ParamTraits
<unsigned long>::Log(const param_type
& p
, std::string
* l
) {
225 l
->append(base::Uint64ToString(static_cast<uint64
>(p
)));
228 void ParamTraits
<long long>::Log(const param_type
& p
, std::string
* l
) {
229 l
->append(base::Int64ToString(static_cast<int64
>(p
)));
232 void ParamTraits
<unsigned long long>::Log(const param_type
& p
, std::string
* l
) {
233 l
->append(base::Uint64ToString(p
));
236 void ParamTraits
<unsigned short>::Write(Message
* m
, const param_type
& p
) {
237 m
->WriteBytes(&p
, sizeof(param_type
));
240 bool ParamTraits
<unsigned short>::Read(const Message
* m
, void** iter
,
243 if (!m
->ReadBytes(iter
, &data
, sizeof(param_type
)))
245 memcpy(r
, data
, sizeof(param_type
));
249 void ParamTraits
<unsigned short>::Log(const param_type
& p
, std::string
* l
) {
250 l
->append(base::UintToString(p
));
253 void ParamTraits
<base::Time
>::Write(Message
* m
, const param_type
& p
) {
254 ParamTraits
<int64
>::Write(m
, p
.ToInternalValue());
257 bool ParamTraits
<base::Time
>::Read(const Message
* m
, void** iter
,
260 if (!ParamTraits
<int64
>::Read(m
, iter
, &value
))
262 *r
= base::Time::FromInternalValue(value
);
266 void ParamTraits
<base::Time
>::Log(const param_type
& p
, std::string
* l
) {
267 ParamTraits
<int64
>::Log(p
.ToInternalValue(), l
);
270 void ParamTraits
<base::TimeDelta
> ::Write(Message
* m
, const param_type
& p
) {
271 ParamTraits
<int64
> ::Write(m
, p
.InMicroseconds());
274 bool ParamTraits
<base::TimeDelta
> ::Read(const Message
* m
,
278 bool ret
= ParamTraits
<int64
> ::Read(m
, iter
, &value
);
280 *r
= base::TimeDelta::FromMicroseconds(value
);
285 void ParamTraits
<base::TimeDelta
> ::Log(const param_type
& p
, std::string
* l
) {
286 ParamTraits
<int64
> ::Log(p
.InMicroseconds(), l
);
289 void ParamTraits
<DictionaryValue
>::Write(Message
* m
, const param_type
& p
) {
290 WriteValue(m
, &p
, 0);
293 bool ParamTraits
<DictionaryValue
>::Read(
294 const Message
* m
, void** iter
, param_type
* r
) {
296 if (!ReadParam(m
, iter
, &type
) || type
!= Value::TYPE_DICTIONARY
)
299 return ReadDictionaryValue(m
, iter
, r
, 0);
302 void ParamTraits
<DictionaryValue
>::Log(const param_type
& p
, std::string
* l
) {
304 base::JSONWriter::Write(&p
, false, &json
);
308 void ParamTraits
<ListValue
>::Write(Message
* m
, const param_type
& p
) {
309 WriteValue(m
, &p
, 0);
312 bool ParamTraits
<ListValue
>::Read(
313 const Message
* m
, void** iter
, param_type
* r
) {
315 if (!ReadParam(m
, iter
, &type
) || type
!= Value::TYPE_LIST
)
318 return ReadListValue(m
, iter
, r
, 0);
321 void ParamTraits
<ListValue
>::Log(const param_type
& p
, std::string
* l
) {
323 base::JSONWriter::Write(&p
, false, &json
);
327 void ParamTraits
<std::wstring
>::Log(const param_type
& p
, std::string
* l
) {
328 l
->append(WideToUTF8(p
));
331 void ParamTraits
<NullableString16
>::Write(Message
* m
, const param_type
& p
) {
332 WriteParam(m
, p
.string());
333 WriteParam(m
, p
.is_null());
336 bool ParamTraits
<NullableString16
>::Read(const Message
* m
, void** iter
,
339 if (!ReadParam(m
, iter
, &string
))
342 if (!ReadParam(m
, iter
, &is_null
))
344 *r
= NullableString16(string
, is_null
);
348 void ParamTraits
<NullableString16
>::Log(const param_type
& p
, std::string
* l
) {
350 LogParam(p
.string(), l
);
352 LogParam(p
.is_null(), l
);
356 #if !defined(WCHAR_T_IS_UTF16)
357 void ParamTraits
<string16
>::Log(const param_type
& p
, std::string
* l
) {
358 l
->append(UTF16ToUTF8(p
));
363 void ParamTraits
<FilePath
>::Write(Message
* m
, const param_type
& p
) {
364 ParamTraits
<FilePath::StringType
>::Write(m
, p
.value());
367 bool ParamTraits
<FilePath
>::Read(const Message
* m
, void** iter
, param_type
* r
) {
368 FilePath::StringType value
;
369 if (!ParamTraits
<FilePath::StringType
>::Read(m
, iter
, &value
))
371 *r
= FilePath(value
);
375 void ParamTraits
<FilePath
>::Log(const param_type
& p
, std::string
* l
) {
376 ParamTraits
<FilePath::StringType
>::Log(p
.value(), l
);
379 #if defined(OS_POSIX)
380 void ParamTraits
<base::FileDescriptor
>::Write(Message
* m
, const param_type
& p
) {
381 const bool valid
= p
.fd
>= 0;
382 WriteParam(m
, valid
);
385 if (!m
->WriteFileDescriptor(p
))
390 bool ParamTraits
<base::FileDescriptor
>::Read(const Message
* m
, void** iter
,
393 if (!ReadParam(m
, iter
, &valid
))
398 r
->auto_close
= false;
402 return m
->ReadFileDescriptor(iter
, r
);
405 void ParamTraits
<base::FileDescriptor
>::Log(const param_type
& p
,
408 l
->append(StringPrintf("FD(%d auto-close)", p
.fd
));
410 l
->append(StringPrintf("FD(%d)", p
.fd
));
413 #endif // defined(OS_POSIX)
415 void ParamTraits
<IPC::ChannelHandle
>::Write(Message
* m
, const param_type
& p
) {
416 WriteParam(m
, p
.name
);
417 #if defined(OS_POSIX)
418 WriteParam(m
, p
.socket
);
422 bool ParamTraits
<IPC::ChannelHandle
>::Read(const Message
* m
, void** iter
,
424 return ReadParam(m
, iter
, &r
->name
)
425 #if defined(OS_POSIX)
426 && ReadParam(m
, iter
, &r
->socket
)
431 void ParamTraits
<IPC::ChannelHandle
>::Log(const param_type
& p
,
433 l
->append(StringPrintf("ChannelHandle(%s", p
.name
.c_str()));
434 #if defined(OS_POSIX)
435 ParamTraits
<base::FileDescriptor
>::Log(p
.socket
, l
);
448 LogData::~LogData() {
451 void ParamTraits
<LogData
>::Write(Message
* m
, const param_type
& p
) {
452 WriteParam(m
, p
.channel
);
453 WriteParam(m
, p
.routing_id
);
454 WriteParam(m
, static_cast<int>(p
.type
));
455 WriteParam(m
, p
.flags
);
456 WriteParam(m
, p
.sent
);
457 WriteParam(m
, p
.receive
);
458 WriteParam(m
, p
.dispatch
);
459 WriteParam(m
, p
.params
);
462 bool ParamTraits
<LogData
>::Read(const Message
* m
, void** iter
, param_type
* r
) {
465 ReadParam(m
, iter
, &r
->channel
) &&
466 ReadParam(m
, iter
, &r
->routing_id
) &&
467 ReadParam(m
, iter
, &type
) &&
468 ReadParam(m
, iter
, &r
->flags
) &&
469 ReadParam(m
, iter
, &r
->sent
) &&
470 ReadParam(m
, iter
, &r
->receive
) &&
471 ReadParam(m
, iter
, &r
->dispatch
) &&
472 ReadParam(m
, iter
, &r
->params
);
473 r
->type
= static_cast<uint16
>(type
);