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
27 static bool ReadValue(const Message* m, void** iter, Value** value,
30 static void WriteValue(Message* m, const Value* value, int recursion) {
31 if (recursion > kMaxRecursionDepth) {
32 LOG(WARNING) << "Max recursion depth hit in WriteValue.";
36 m->WriteInt(value->GetType());
38 switch (value->GetType()) {
39 case Value::TYPE_NULL:
41 case Value::TYPE_BOOLEAN: {
43 value->GetAsBoolean(&val);
47 case Value::TYPE_INTEGER: {
49 value->GetAsInteger(&val);
53 case Value::TYPE_DOUBLE: {
55 value->GetAsDouble(&val);
59 case Value::TYPE_STRING: {
61 value->GetAsString(&val);
65 case Value::TYPE_BINARY: {
66 const base::BinaryValue* binary =
67 static_cast<const base::BinaryValue*>(value);
68 m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
71 case Value::TYPE_DICTIONARY: {
72 const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
74 WriteParam(m, static_cast<int>(dict->size()));
76 for (DictionaryValue::key_iterator it = dict->begin_keys();
77 it != dict->end_keys(); ++it) {
79 if (dict->GetWithoutPathExpansion(*it, &subval)) {
81 WriteValue(m, subval, recursion + 1);
83 NOTREACHED() << "DictionaryValue iterators are filthy liars.";
88 case Value::TYPE_LIST: {
89 const ListValue* list = static_cast<const ListValue*>(value);
90 WriteParam(m, static_cast<int>(list->GetSize()));
91 for (size_t i = 0; i < list->GetSize(); ++i) {
93 if (list->Get(i, &subval)) {
94 WriteValue(m, subval, recursion + 1);
96 NOTREACHED() << "ListValue::GetSize is a filthy liar.";
104 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated
106 static bool ReadDictionaryValue(const Message* m, void** iter,
107 DictionaryValue* value, int recursion) {
109 if (!ReadParam(m, iter, &size))
112 for (int i = 0; i < size; ++i) {
115 if (!ReadParam(m, iter, &key) ||
116 !ReadValue(m, iter, &subval, recursion + 1))
118 value->Set(key, subval);
124 // Helper for ReadValue that reads a ReadListValue into a pre-allocated
126 static bool ReadListValue(const Message* m, void** iter,
127 ListValue* value, int recursion) {
129 if (!ReadParam(m, iter, &size))
132 for (int i = 0; i < size; ++i) {
134 if (!ReadValue(m, iter, &subval, recursion + 1))
136 value->Set(i, subval);
142 static bool ReadValue(const Message* m, void** iter, Value** value,
144 if (recursion > kMaxRecursionDepth) {
145 LOG(WARNING) << "Max recursion depth hit in ReadValue.";
150 if (!ReadParam(m, iter, &type))
154 case Value::TYPE_NULL:
155 *value = Value::CreateNullValue();
157 case Value::TYPE_BOOLEAN: {
159 if (!ReadParam(m, iter, &val))
161 *value = Value::CreateBooleanValue(val);
164 case Value::TYPE_INTEGER: {
166 if (!ReadParam(m, iter, &val))
168 *value = Value::CreateIntegerValue(val);
171 case Value::TYPE_DOUBLE: {
173 if (!ReadParam(m, iter, &val))
175 *value = Value::CreateDoubleValue(val);
178 case Value::TYPE_STRING: {
180 if (!ReadParam(m, iter, &val))
182 *value = Value::CreateStringValue(val);
185 case Value::TYPE_BINARY: {
188 if (!m->ReadData(iter, &data, &length))
190 *value = base::BinaryValue::CreateWithCopiedBuffer(data, length);
193 case Value::TYPE_DICTIONARY: {
194 scoped_ptr<DictionaryValue> val(new DictionaryValue());
195 if (!ReadDictionaryValue(m, iter, val.get(), recursion))
197 *value = val.release();
200 case Value::TYPE_LIST: {
201 scoped_ptr<ListValue> val(new ListValue());
202 if (!ReadListValue(m, iter, val.get(), recursion))
204 *value = val.release();
215 void ParamTraits<int>::Log(const param_type& p, std::string* l) {
216 //l->append(base::IntToString(p));
219 void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
220 //l->append(base::UintToString(p));
223 void ParamTraits<long>::Log(const param_type& p, std::string* l) {
224 //l->append(base::Int64ToString(static_cast<int64>(p)));
227 void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
228 //l->append(base::Uint64ToString(static_cast<uint64>(p)));
231 void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
232 //l->append(base::Int64ToString(static_cast<int64>(p)));
235 void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
236 //l->append(base::Uint64ToString(p));
240 void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) {
241 m->WriteBytes(&p, sizeof(param_type));
244 bool ParamTraits<unsigned short>::Read(const Message* m, void** iter,
247 if (!m->ReadBytes(iter, &data, sizeof(param_type)))
249 memcpy(r, data, sizeof(param_type));
254 void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
255 l->append(base::UintToString(p));
259 void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
260 ParamTraits<int64>::Write(m, p.ToInternalValue());
263 bool ParamTraits<base::Time>::Read(const Message* m, void** iter,
266 if (!ParamTraits<int64>::Read(m, iter, &value))
268 *r = base::Time::FromInternalValue(value);
272 void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
273 ParamTraits<int64>::Log(p.ToInternalValue(), l);
276 void ParamTraits<base::TimeDelta> ::Write(Message* m, const param_type& p) {
277 ParamTraits<int64> ::Write(m, p.InMicroseconds());
280 bool ParamTraits<base::TimeDelta> ::Read(const Message* m,
284 bool ret = ParamTraits<int64> ::Read(m, iter, &value);
286 *r = base::TimeDelta::FromMicroseconds(value);
291 void ParamTraits<base::TimeDelta> ::Log(const param_type& p, std::string* l) {
292 ParamTraits<int64> ::Log(p.InMicroseconds(), l);
295 void ParamTraits<DictionaryValue>::Write(Message* m, const param_type& p) {
296 WriteValue(m, &p, 0);
299 bool ParamTraits<DictionaryValue>::Read(
300 const Message* m, void** iter, param_type* r) {
302 if (!ReadParam(m, iter, &type) || type != Value::TYPE_DICTIONARY)
305 return ReadDictionaryValue(m, iter, r, 0);
308 void ParamTraits<DictionaryValue>::Log(const param_type& p, std::string* l) {
310 base::JSONWriter::Write(&p, false, &json);
314 void ParamTraits<ListValue>::Write(Message* m, const param_type& p) {
315 WriteValue(m, &p, 0);
318 bool ParamTraits<ListValue>::Read(
319 const Message* m, void** iter, param_type* r) {
321 if (!ReadParam(m, iter, &type) || type != Value::TYPE_LIST)
324 return ReadListValue(m, iter, r, 0);
327 void ParamTraits<ListValue>::Log(const param_type& p, std::string* l) {
329 base::JSONWriter::Write(&p, false, &json);
333 void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
334 l->append(WideToUTF8(p));
337 void ParamTraits<NullableString16>::Write(Message* m, const param_type& p) {
338 WriteParam(m, p.string());
339 WriteParam(m, p.is_null());
342 bool ParamTraits<NullableString16>::Read(const Message* m, void** iter,
345 if (!ReadParam(m, iter, &string))
348 if (!ReadParam(m, iter, &is_null))
350 *r = NullableString16(string, is_null);
354 void ParamTraits<NullableString16>::Log(const param_type& p, std::string* l) {
356 LogParam(p.string(), l);
358 LogParam(p.is_null(), l);
362 #if !defined(WCHAR_T_IS_UTF16)
363 void ParamTraits<string16>::Log(const param_type& p, std::string* l) {
364 l->append(UTF16ToUTF8(p));
371 void ParamTraits<FilePath>::Write(Message* m, const param_type& p) {
372 ParamTraits<FilePath::StringType>::Write(m, p.value());
375 bool ParamTraits<FilePath>::Read(const Message* m, void** iter, param_type* r) {
376 FilePath::StringType value;
377 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
379 *r = FilePath(value);
383 void ParamTraits<FilePath>::Log(const param_type& p, std::string* l) {
384 ParamTraits<FilePath::StringType>::Log(p.value(), l);
387 #if defined(OS_POSIX)
388 void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
389 const bool valid = p.fd >= 0;
390 WriteParam(m, valid);
393 if (!m->WriteFileDescriptor(p))
398 bool ParamTraits<base::FileDescriptor>::Read(const Message* m, void** iter,
401 if (!ReadParam(m, iter, &valid))
406 r->auto_close = false;
410 return m->ReadFileDescriptor(iter, r);
413 void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
416 l->append(StringPrintf("FD(%d auto-close)", p.fd));
418 l->append(StringPrintf("FD(%d)", p.fd));
421 #endif // defined(OS_POSIX)
423 void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
424 WriteParam(m, p.name);
425 #if defined(OS_POSIX)
426 WriteParam(m, p.socket);
430 bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m, void** iter,
432 return ReadParam(m, iter, &r->name)
433 #if defined(OS_POSIX)
434 && ReadParam(m, iter, &r->socket)
439 void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
441 l->append(StringPrintf("ChannelHandle(%s", p.name.c_str()));
442 #if defined(OS_POSIX)
443 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
456 LogData::~LogData() {
459 void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
460 WriteParam(m, p.channel);
461 WriteParam(m, p.routing_id);
462 WriteParam(m, static_cast<int>(p.type));
463 WriteParam(m, p.flags);
464 WriteParam(m, p.sent);
465 WriteParam(m, p.receive);
466 WriteParam(m, p.dispatch);
467 WriteParam(m, p.params);
470 bool ParamTraits<LogData>::Read(const Message* m, void** iter, param_type* r) {
473 ReadParam(m, iter, &r->channel) &&
474 ReadParam(m, iter, &r->routing_id) &&
475 ReadParam(m, iter, &type) &&
476 ReadParam(m, iter, &r->flags) &&
477 ReadParam(m, iter, &r->sent) &&
478 ReadParam(m, iter, &r->receive) &&
479 ReadParam(m, iter, &r->dispatch) &&
480 ReadParam(m, iter, &r->params);
481 r->type = static_cast<uint16>(type);