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 base::BinaryValue
* binary
=
66 static_cast<const base::BinaryValue
*>(value
);
67 m
->WriteData(binary
->GetBuffer(), static_cast<int>(binary
->GetSize()));
70 case Value::TYPE_DICTIONARY
: {
71 const DictionaryValue
* dict
= static_cast<const DictionaryValue
*>(value
);
73 WriteParam(m
, static_cast<int>(dict
->size()));
75 for (DictionaryValue::key_iterator it
= dict
->begin_keys();
76 it
!= dict
->end_keys(); ++it
) {
78 if (dict
->GetWithoutPathExpansion(*it
, &subval
)) {
80 WriteValue(m
, subval
, recursion
+ 1);
82 NOTREACHED() << "DictionaryValue iterators are filthy liars.";
87 case Value::TYPE_LIST
: {
88 const ListValue
* list
= static_cast<const ListValue
*>(value
);
89 WriteParam(m
, static_cast<int>(list
->GetSize()));
90 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
92 if (list
->Get(i
, &subval
)) {
93 WriteValue(m
, subval
, recursion
+ 1);
95 NOTREACHED() << "ListValue::GetSize is a filthy liar.";
103 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated
105 static bool ReadDictionaryValue(const Message
* m
, void** iter
,
106 DictionaryValue
* value
, int recursion
) {
108 if (!ReadParam(m
, iter
, &size
))
111 for (int i
= 0; i
< size
; ++i
) {
114 if (!ReadParam(m
, iter
, &key
) ||
115 !ReadValue(m
, iter
, &subval
, recursion
+ 1))
117 value
->SetWithoutPathExpansion(key
, subval
);
123 // Helper for ReadValue that reads a ReadListValue into a pre-allocated
125 static bool ReadListValue(const Message
* m
, void** iter
,
126 ListValue
* value
, int recursion
) {
128 if (!ReadParam(m
, iter
, &size
))
131 for (int i
= 0; i
< size
; ++i
) {
133 if (!ReadValue(m
, iter
, &subval
, recursion
+ 1))
135 value
->Set(i
, subval
);
141 static bool ReadValue(const Message
* m
, void** iter
, Value
** value
,
143 if (recursion
> kMaxRecursionDepth
) {
144 LOG(WARNING
) << "Max recursion depth hit in ReadValue.";
149 if (!ReadParam(m
, iter
, &type
))
153 case Value::TYPE_NULL
:
154 *value
= Value::CreateNullValue();
156 case Value::TYPE_BOOLEAN
: {
158 if (!ReadParam(m
, iter
, &val
))
160 *value
= Value::CreateBooleanValue(val
);
163 case Value::TYPE_INTEGER
: {
165 if (!ReadParam(m
, iter
, &val
))
167 *value
= Value::CreateIntegerValue(val
);
170 case Value::TYPE_DOUBLE
: {
172 if (!ReadParam(m
, iter
, &val
))
174 *value
= Value::CreateDoubleValue(val
);
177 case Value::TYPE_STRING
: {
179 if (!ReadParam(m
, iter
, &val
))
181 *value
= Value::CreateStringValue(val
);
184 case Value::TYPE_BINARY
: {
187 if (!m
->ReadData(iter
, &data
, &length
))
189 *value
= base::BinaryValue::CreateWithCopiedBuffer(data
, length
);
192 case Value::TYPE_DICTIONARY
: {
193 scoped_ptr
<DictionaryValue
> val(new DictionaryValue());
194 if (!ReadDictionaryValue(m
, iter
, val
.get(), recursion
))
196 *value
= val
.release();
199 case Value::TYPE_LIST
: {
200 scoped_ptr
<ListValue
> val(new ListValue());
201 if (!ReadListValue(m
, iter
, val
.get(), recursion
))
203 *value
= val
.release();
213 void ParamTraits
<int>::Log(const param_type
& p
, std::string
* l
) {
214 l
->append(base::IntToString(p
));
217 void ParamTraits
<unsigned int>::Log(const param_type
& p
, std::string
* l
) {
218 l
->append(base::UintToString(p
));
221 void ParamTraits
<long>::Log(const param_type
& p
, std::string
* l
) {
222 l
->append(base::Int64ToString(static_cast<int64
>(p
)));
225 void ParamTraits
<unsigned long>::Log(const param_type
& p
, std::string
* l
) {
226 l
->append(base::Uint64ToString(static_cast<uint64
>(p
)));
229 void ParamTraits
<long long>::Log(const param_type
& p
, std::string
* l
) {
230 l
->append(base::Int64ToString(static_cast<int64
>(p
)));
233 void ParamTraits
<unsigned long long>::Log(const param_type
& p
, std::string
* l
) {
234 l
->append(base::Uint64ToString(p
));
237 void ParamTraits
<unsigned short>::Write(Message
* m
, const param_type
& p
) {
238 m
->WriteBytes(&p
, sizeof(param_type
));
241 bool ParamTraits
<unsigned short>::Read(const Message
* m
, void** iter
,
244 if (!m
->ReadBytes(iter
, &data
, sizeof(param_type
)))
246 memcpy(r
, data
, sizeof(param_type
));
250 void ParamTraits
<unsigned short>::Log(const param_type
& p
, std::string
* l
) {
251 l
->append(base::UintToString(p
));
254 void ParamTraits
<base::Time
>::Write(Message
* m
, const param_type
& p
) {
255 ParamTraits
<int64
>::Write(m
, p
.ToInternalValue());
258 bool ParamTraits
<base::Time
>::Read(const Message
* m
, void** iter
,
261 if (!ParamTraits
<int64
>::Read(m
, iter
, &value
))
263 *r
= base::Time::FromInternalValue(value
);
267 void ParamTraits
<base::Time
>::Log(const param_type
& p
, std::string
* l
) {
268 ParamTraits
<int64
>::Log(p
.ToInternalValue(), l
);
271 void ParamTraits
<base::TimeDelta
> ::Write(Message
* m
, const param_type
& p
) {
272 ParamTraits
<int64
> ::Write(m
, p
.ToInternalValue());
275 bool ParamTraits
<base::TimeDelta
> ::Read(const Message
* m
,
279 bool ret
= ParamTraits
<int64
> ::Read(m
, iter
, &value
);
281 *r
= base::TimeDelta::FromInternalValue(value
);
286 void ParamTraits
<base::TimeDelta
> ::Log(const param_type
& p
, std::string
* l
) {
287 ParamTraits
<int64
> ::Log(p
.ToInternalValue(), l
);
290 void ParamTraits
<base::TimeTicks
> ::Write(Message
* m
, const param_type
& p
) {
291 ParamTraits
<int64
> ::Write(m
, p
.ToInternalValue());
294 bool ParamTraits
<base::TimeTicks
> ::Read(const Message
* m
,
298 bool ret
= ParamTraits
<int64
> ::Read(m
, iter
, &value
);
300 *r
= base::TimeTicks::FromInternalValue(value
);
305 void ParamTraits
<base::TimeTicks
> ::Log(const param_type
& p
, std::string
* l
) {
306 ParamTraits
<int64
> ::Log(p
.ToInternalValue(), l
);
309 void ParamTraits
<DictionaryValue
>::Write(Message
* m
, const param_type
& p
) {
310 WriteValue(m
, &p
, 0);
313 bool ParamTraits
<DictionaryValue
>::Read(
314 const Message
* m
, void** iter
, param_type
* r
) {
316 if (!ReadParam(m
, iter
, &type
) || type
!= Value::TYPE_DICTIONARY
)
319 return ReadDictionaryValue(m
, iter
, r
, 0);
322 void ParamTraits
<DictionaryValue
>::Log(const param_type
& p
, std::string
* l
) {
324 base::JSONWriter::Write(&p
, false, &json
);
328 void ParamTraits
<ListValue
>::Write(Message
* m
, const param_type
& p
) {
329 WriteValue(m
, &p
, 0);
332 bool ParamTraits
<ListValue
>::Read(
333 const Message
* m
, void** iter
, param_type
* r
) {
335 if (!ReadParam(m
, iter
, &type
) || type
!= Value::TYPE_LIST
)
338 return ReadListValue(m
, iter
, r
, 0);
341 void ParamTraits
<ListValue
>::Log(const param_type
& p
, std::string
* l
) {
343 base::JSONWriter::Write(&p
, false, &json
);
347 void ParamTraits
<std::wstring
>::Log(const param_type
& p
, std::string
* l
) {
348 l
->append(WideToUTF8(p
));
351 void ParamTraits
<NullableString16
>::Write(Message
* m
, const param_type
& p
) {
352 WriteParam(m
, p
.string());
353 WriteParam(m
, p
.is_null());
356 bool ParamTraits
<NullableString16
>::Read(const Message
* m
, void** iter
,
359 if (!ReadParam(m
, iter
, &string
))
362 if (!ReadParam(m
, iter
, &is_null
))
364 *r
= NullableString16(string
, is_null
);
368 void ParamTraits
<NullableString16
>::Log(const param_type
& p
, std::string
* l
) {
370 LogParam(p
.string(), l
);
372 LogParam(p
.is_null(), l
);
376 #if !defined(WCHAR_T_IS_UTF16)
377 void ParamTraits
<string16
>::Log(const param_type
& p
, std::string
* l
) {
378 l
->append(UTF16ToUTF8(p
));
383 void ParamTraits
<FilePath
>::Write(Message
* m
, const param_type
& p
) {
384 ParamTraits
<FilePath::StringType
>::Write(m
, p
.value());
387 bool ParamTraits
<FilePath
>::Read(const Message
* m
, void** iter
, param_type
* r
) {
388 FilePath::StringType value
;
389 if (!ParamTraits
<FilePath::StringType
>::Read(m
, iter
, &value
))
391 *r
= FilePath(value
);
395 void ParamTraits
<FilePath
>::Log(const param_type
& p
, std::string
* l
) {
396 ParamTraits
<FilePath::StringType
>::Log(p
.value(), l
);
399 #if defined(OS_POSIX)
400 void ParamTraits
<base::FileDescriptor
>::Write(Message
* m
, const param_type
& p
) {
401 const bool valid
= p
.fd
>= 0;
402 WriteParam(m
, valid
);
405 if (!m
->WriteFileDescriptor(p
))
410 bool ParamTraits
<base::FileDescriptor
>::Read(const Message
* m
, void** iter
,
413 if (!ReadParam(m
, iter
, &valid
))
418 r
->auto_close
= false;
422 return m
->ReadFileDescriptor(iter
, r
);
425 void ParamTraits
<base::FileDescriptor
>::Log(const param_type
& p
,
428 l
->append(StringPrintf("FD(%d auto-close)", p
.fd
));
430 l
->append(StringPrintf("FD(%d)", p
.fd
));
433 #endif // defined(OS_POSIX)
435 void ParamTraits
<IPC::ChannelHandle
>::Write(Message
* m
, const param_type
& p
) {
436 WriteParam(m
, p
.name
);
437 #if defined(OS_POSIX)
438 WriteParam(m
, p
.socket
);
442 bool ParamTraits
<IPC::ChannelHandle
>::Read(const Message
* m
, void** iter
,
444 return ReadParam(m
, iter
, &r
->name
)
445 #if defined(OS_POSIX)
446 && ReadParam(m
, iter
, &r
->socket
)
451 void ParamTraits
<IPC::ChannelHandle
>::Log(const param_type
& p
,
453 l
->append(StringPrintf("ChannelHandle(%s", p
.name
.c_str()));
454 #if defined(OS_POSIX)
456 ParamTraits
<base::FileDescriptor
>::Log(p
.socket
, l
);
469 LogData::~LogData() {
472 void ParamTraits
<LogData
>::Write(Message
* m
, const param_type
& p
) {
473 WriteParam(m
, p
.channel
);
474 WriteParam(m
, p
.routing_id
);
475 WriteParam(m
, p
.type
);
476 WriteParam(m
, p
.flags
);
477 WriteParam(m
, p
.sent
);
478 WriteParam(m
, p
.receive
);
479 WriteParam(m
, p
.dispatch
);
480 WriteParam(m
, p
.params
);
483 bool ParamTraits
<LogData
>::Read(const Message
* m
, void** iter
, param_type
* r
) {
485 ReadParam(m
, iter
, &r
->channel
) &&
486 ReadParam(m
, iter
, &r
->routing_id
) &&
487 ReadParam(m
, iter
, &r
->type
) &&
488 ReadParam(m
, iter
, &r
->flags
) &&
489 ReadParam(m
, iter
, &r
->sent
) &&
490 ReadParam(m
, iter
, &r
->receive
) &&
491 ReadParam(m
, iter
, &r
->dispatch
) &&
492 ReadParam(m
, iter
, &r
->params
);