1 // Copyright (c) 2009 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/json/json_writer.h"
8 #include "base/scoped_ptr.h"
10 #include "base/values.h"
14 const int kMaxRecursionDepth
= 100;
16 // Value serialization
18 static bool ReadValue(const Message
* m
, void** iter
, Value
** value
,
21 static void WriteValue(Message
* m
, const Value
* value
, int recursion
) {
22 if (recursion
> kMaxRecursionDepth
) {
23 LOG(WARNING
) << "Max recursion depth hit in WriteValue.";
27 m
->WriteInt(value
->GetType());
29 switch (value
->GetType()) {
30 case Value::TYPE_NULL
:
32 case Value::TYPE_BOOLEAN
: {
34 value
->GetAsBoolean(&val
);
38 case Value::TYPE_INTEGER
: {
40 value
->GetAsInteger(&val
);
44 case Value::TYPE_REAL
: {
46 value
->GetAsReal(&val
);
50 case Value::TYPE_STRING
: {
52 value
->GetAsString(&val
);
56 case Value::TYPE_BINARY
: {
57 const BinaryValue
* binary
= static_cast<const BinaryValue
*>(value
);
58 m
->WriteData(binary
->GetBuffer(), binary
->GetSize());
61 case Value::TYPE_DICTIONARY
: {
62 const DictionaryValue
* dict
= static_cast<const DictionaryValue
*>(value
);
64 WriteParam(m
, static_cast<int>(dict
->size()));
66 for (DictionaryValue::key_iterator it
= dict
->begin_keys();
67 it
!= dict
->end_keys(); ++it
) {
69 if (dict
->GetWithoutPathExpansion(*it
, &subval
)) {
71 WriteValue(m
, subval
, recursion
+ 1);
73 NOTREACHED() << "DictionaryValue iterators are filthy liars.";
78 case Value::TYPE_LIST
: {
79 const ListValue
* list
= static_cast<const ListValue
*>(value
);
80 WriteParam(m
, static_cast<int>(list
->GetSize()));
81 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
83 if (list
->Get(i
, &subval
)) {
84 WriteValue(m
, subval
, recursion
+ 1);
86 NOTREACHED() << "ListValue::GetSize is a filthy liar.";
94 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated
96 static bool ReadDictionaryValue(const Message
* m
, void** iter
,
97 DictionaryValue
* value
, int recursion
) {
99 if (!ReadParam(m
, iter
, &size
))
102 for (int i
= 0; i
< size
; ++i
) {
105 if (!ReadParam(m
, iter
, &key
) ||
106 !ReadValue(m
, iter
, &subval
, recursion
+ 1))
108 value
->Set(key
, subval
);
114 // Helper for ReadValue that reads a ReadListValue into a pre-allocated
116 static bool ReadListValue(const Message
* m
, void** iter
,
117 ListValue
* value
, int recursion
) {
119 if (!ReadParam(m
, iter
, &size
))
122 for (int i
= 0; i
< size
; ++i
) {
124 if (!ReadValue(m
, iter
, &subval
, recursion
+ 1))
126 value
->Set(i
, subval
);
132 static bool ReadValue(const Message
* m
, void** iter
, Value
** value
,
134 if (recursion
> kMaxRecursionDepth
) {
135 LOG(WARNING
) << "Max recursion depth hit in ReadValue.";
140 if (!ReadParam(m
, iter
, &type
))
144 case Value::TYPE_NULL
:
145 *value
= Value::CreateNullValue();
147 case Value::TYPE_BOOLEAN
: {
149 if (!ReadParam(m
, iter
, &val
))
151 *value
= Value::CreateBooleanValue(val
);
154 case Value::TYPE_INTEGER
: {
156 if (!ReadParam(m
, iter
, &val
))
158 *value
= Value::CreateIntegerValue(val
);
161 case Value::TYPE_REAL
: {
163 if (!ReadParam(m
, iter
, &val
))
165 *value
= Value::CreateRealValue(val
);
168 case Value::TYPE_STRING
: {
170 if (!ReadParam(m
, iter
, &val
))
172 *value
= Value::CreateStringValue(val
);
175 case Value::TYPE_BINARY
: {
178 if (!m
->ReadData(iter
, &data
, &length
))
180 *value
= BinaryValue::CreateWithCopiedBuffer(data
, length
);
183 case Value::TYPE_DICTIONARY
: {
184 scoped_ptr
<DictionaryValue
> val(new DictionaryValue());
185 if (!ReadDictionaryValue(m
, iter
, val
.get(), recursion
))
187 *value
= val
.release();
190 case Value::TYPE_LIST
: {
191 scoped_ptr
<ListValue
> val(new ListValue());
192 if (!ReadListValue(m
, iter
, val
.get(), recursion
))
194 *value
= val
.release();
204 void ParamTraits
<DictionaryValue
>::Write(Message
* m
, const param_type
& p
) {
205 WriteValue(m
, &p
, 0);
208 bool ParamTraits
<DictionaryValue
>::Read(
209 const Message
* m
, void** iter
, param_type
* r
) {
211 if (!ReadParam(m
, iter
, &type
) || type
!= Value::TYPE_DICTIONARY
)
214 return ReadDictionaryValue(m
, iter
, r
, 0);
217 void ParamTraits
<DictionaryValue
>::Log(const param_type
& p
, std::wstring
* l
) {
219 base::JSONWriter::Write(&p
, false, &json
);
220 l
->append(UTF8ToWide(json
));
223 void ParamTraits
<ListValue
>::Write(Message
* m
, const param_type
& p
) {
224 WriteValue(m
, &p
, 0);
227 bool ParamTraits
<ListValue
>::Read(
228 const Message
* m
, void** iter
, param_type
* r
) {
230 if (!ReadParam(m
, iter
, &type
) || type
!= Value::TYPE_LIST
)
233 return ReadListValue(m
, iter
, r
, 0);
236 void ParamTraits
<ListValue
>::Log(const param_type
& p
, std::wstring
* l
) {
238 base::JSONWriter::Write(&p
, false, &json
);
239 l
->append(UTF8ToWide(json
));