blob: d5df42f35b02577803520679301d158c4272a263 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]946d1b22009-07-22 23:57:212// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ipc/ipc_message_utils.h"
6
[email protected]7a4de7a62010-08-17 18:38:247#include "base/file_path.h"
[email protected]93d49d72009-10-23 20:00:208#include "base/json/json_writer.h"
[email protected]3b63f8f42011-03-28 01:54:159#include "base/memory/scoped_ptr.h"
[email protected]7a4de7a62010-08-17 18:38:2410#include "base/nullable_string16.h"
[email protected]252cad62010-08-18 18:33:5711#include "base/string_number_conversions.h"
[email protected]946d1b22009-07-22 23:57:2112#include "base/time.h"
[email protected]252cad62010-08-18 18:33:5713#include "base/utf_string_conversions.h"
[email protected]946d1b22009-07-22 23:57:2114#include "base/values.h"
[email protected]7a4de7a62010-08-17 18:38:2415#if defined(OS_POSIX)
16#include "ipc/file_descriptor_set_posix.h"
17#endif
18#include "ipc/ipc_channel_handle.h"
[email protected]946d1b22009-07-22 23:57:2119
20namespace IPC {
21
22const int kMaxRecursionDepth = 100;
23
24// Value serialization
25
26static bool ReadValue(const Message* m, void** iter, Value** value,
27 int recursion);
28
29static void WriteValue(Message* m, const Value* value, int recursion) {
30 if (recursion > kMaxRecursionDepth) {
31 LOG(WARNING) << "Max recursion depth hit in WriteValue.";
32 return;
33 }
34
35 m->WriteInt(value->GetType());
36
37 switch (value->GetType()) {
[email protected]e4dad9fb2009-10-06 18:15:5838 case Value::TYPE_NULL:
[email protected]946d1b22009-07-22 23:57:2139 break;
[email protected]e4dad9fb2009-10-06 18:15:5840 case Value::TYPE_BOOLEAN: {
[email protected]946d1b22009-07-22 23:57:2141 bool val;
42 value->GetAsBoolean(&val);
43 WriteParam(m, val);
44 break;
45 }
[email protected]e4dad9fb2009-10-06 18:15:5846 case Value::TYPE_INTEGER: {
[email protected]946d1b22009-07-22 23:57:2147 int val;
48 value->GetAsInteger(&val);
49 WriteParam(m, val);
50 break;
51 }
[email protected]fb534c92011-02-01 01:02:0752 case Value::TYPE_DOUBLE: {
[email protected]946d1b22009-07-22 23:57:2153 double val;
[email protected]fb534c92011-02-01 01:02:0754 value->GetAsDouble(&val);
[email protected]946d1b22009-07-22 23:57:2155 WriteParam(m, val);
56 break;
57 }
[email protected]e4dad9fb2009-10-06 18:15:5858 case Value::TYPE_STRING: {
[email protected]946d1b22009-07-22 23:57:2159 std::string val;
60 value->GetAsString(&val);
61 WriteParam(m, val);
62 break;
63 }
[email protected]e4dad9fb2009-10-06 18:15:5864 case Value::TYPE_BINARY: {
65 const BinaryValue* binary = static_cast<const BinaryValue*>(value);
[email protected]7ee1a44c2010-07-23 14:18:5966 m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
[email protected]e4dad9fb2009-10-06 18:15:5867 break;
[email protected]946d1b22009-07-22 23:57:2168 }
[email protected]e4dad9fb2009-10-06 18:15:5869 case Value::TYPE_DICTIONARY: {
[email protected]946d1b22009-07-22 23:57:2170 const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
71
[email protected]4dad9ad82009-11-25 20:47:5272 WriteParam(m, static_cast<int>(dict->size()));
[email protected]946d1b22009-07-22 23:57:2173
74 for (DictionaryValue::key_iterator it = dict->begin_keys();
75 it != dict->end_keys(); ++it) {
76 Value* subval;
[email protected]4dad9ad82009-11-25 20:47:5277 if (dict->GetWithoutPathExpansion(*it, &subval)) {
[email protected]946d1b22009-07-22 23:57:2178 WriteParam(m, *it);
79 WriteValue(m, subval, recursion + 1);
80 } else {
81 NOTREACHED() << "DictionaryValue iterators are filthy liars.";
82 }
83 }
84 break;
85 }
[email protected]e4dad9fb2009-10-06 18:15:5886 case Value::TYPE_LIST: {
[email protected]946d1b22009-07-22 23:57:2187 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) {
90 Value* subval;
91 if (list->Get(i, &subval)) {
92 WriteValue(m, subval, recursion + 1);
93 } else {
94 NOTREACHED() << "ListValue::GetSize is a filthy liar.";
95 }
96 }
97 break;
98 }
99 }
100}
101
102// Helper for ReadValue that reads a DictionaryValue into a pre-allocated
103// object.
104static bool ReadDictionaryValue(const Message* m, void** iter,
105 DictionaryValue* value, int recursion) {
106 int size;
107 if (!ReadParam(m, iter, &size))
108 return false;
109
110 for (int i = 0; i < size; ++i) {
[email protected]e7b418b2010-07-30 19:47:47111 std::string key;
[email protected]946d1b22009-07-22 23:57:21112 Value* subval;
113 if (!ReadParam(m, iter, &key) ||
114 !ReadValue(m, iter, &subval, recursion + 1))
115 return false;
116 value->Set(key, subval);
117 }
118
119 return true;
120}
121
122// Helper for ReadValue that reads a ReadListValue into a pre-allocated
123// object.
124static bool ReadListValue(const Message* m, void** iter,
125 ListValue* value, int recursion) {
126 int size;
127 if (!ReadParam(m, iter, &size))
128 return false;
129
130 for (int i = 0; i < size; ++i) {
131 Value* subval;
132 if (!ReadValue(m, iter, &subval, recursion + 1))
133 return false;
134 value->Set(i, subval);
135 }
136
137 return true;
138}
139
140static bool ReadValue(const Message* m, void** iter, Value** value,
141 int recursion) {
142 if (recursion > kMaxRecursionDepth) {
143 LOG(WARNING) << "Max recursion depth hit in ReadValue.";
144 return false;
145 }
146
147 int type;
148 if (!ReadParam(m, iter, &type))
149 return false;
150
151 switch (type) {
[email protected]e4dad9fb2009-10-06 18:15:58152 case Value::TYPE_NULL:
[email protected]946d1b22009-07-22 23:57:21153 *value = Value::CreateNullValue();
154 break;
[email protected]e4dad9fb2009-10-06 18:15:58155 case Value::TYPE_BOOLEAN: {
[email protected]946d1b22009-07-22 23:57:21156 bool val;
157 if (!ReadParam(m, iter, &val))
158 return false;
159 *value = Value::CreateBooleanValue(val);
160 break;
161 }
[email protected]e4dad9fb2009-10-06 18:15:58162 case Value::TYPE_INTEGER: {
[email protected]946d1b22009-07-22 23:57:21163 int val;
164 if (!ReadParam(m, iter, &val))
165 return false;
166 *value = Value::CreateIntegerValue(val);
167 break;
168 }
[email protected]fb534c92011-02-01 01:02:07169 case Value::TYPE_DOUBLE: {
[email protected]946d1b22009-07-22 23:57:21170 double val;
171 if (!ReadParam(m, iter, &val))
172 return false;
[email protected]fb534c92011-02-01 01:02:07173 *value = Value::CreateDoubleValue(val);
[email protected]946d1b22009-07-22 23:57:21174 break;
175 }
[email protected]e4dad9fb2009-10-06 18:15:58176 case Value::TYPE_STRING: {
[email protected]946d1b22009-07-22 23:57:21177 std::string val;
178 if (!ReadParam(m, iter, &val))
179 return false;
180 *value = Value::CreateStringValue(val);
181 break;
182 }
[email protected]e4dad9fb2009-10-06 18:15:58183 case Value::TYPE_BINARY: {
184 const char* data;
185 int length;
186 if (!m->ReadData(iter, &data, &length))
187 return false;
188 *value = BinaryValue::CreateWithCopiedBuffer(data, length);
[email protected]946d1b22009-07-22 23:57:21189 break;
190 }
[email protected]e4dad9fb2009-10-06 18:15:58191 case Value::TYPE_DICTIONARY: {
[email protected]946d1b22009-07-22 23:57:21192 scoped_ptr<DictionaryValue> val(new DictionaryValue());
193 if (!ReadDictionaryValue(m, iter, val.get(), recursion))
194 return false;
195 *value = val.release();
196 break;
197 }
[email protected]e4dad9fb2009-10-06 18:15:58198 case Value::TYPE_LIST: {
[email protected]946d1b22009-07-22 23:57:21199 scoped_ptr<ListValue> val(new ListValue());
200 if (!ReadListValue(m, iter, val.get(), recursion))
201 return false;
202 *value = val.release();
203 break;
204 }
[email protected]e4dad9fb2009-10-06 18:15:58205 default:
[email protected]946d1b22009-07-22 23:57:21206 return false;
207 }
208
209 return true;
210}
211
[email protected]252cad62010-08-18 18:33:57212void ParamTraits<int>::Log(const param_type& p, std::string* l) {
213 l->append(base::IntToString(p));
214}
215
216void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
217 l->append(base::UintToString(p));
218}
219
220void ParamTraits<long>::Log(const param_type& p, std::string* l) {
221 l->append(base::Int64ToString(static_cast<int64>(p)));
222}
223
224void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
225 l->append(base::Uint64ToString(static_cast<uint64>(p)));
226}
227
228void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
229 l->append(base::Int64ToString(static_cast<int64>(p)));
230}
231
232void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
233 l->append(base::Uint64ToString(p));
234}
[email protected]7a4de7a62010-08-17 18:38:24235
[email protected]43a40202010-11-12 16:25:01236void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) {
237 m->WriteBytes(&p, sizeof(param_type));
238}
239
240bool ParamTraits<unsigned short>::Read(const Message* m, void** iter,
241 param_type* r) {
242 const char* data;
243 if (!m->ReadBytes(iter, &data, sizeof(param_type)))
244 return false;
245 memcpy(r, data, sizeof(param_type));
246 return true;
247}
248
249void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
250 l->append(base::UintToString(p));
251}
252
[email protected]7a4de7a62010-08-17 18:38:24253void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
254 ParamTraits<int64>::Write(m, p.ToInternalValue());
255}
256
257bool ParamTraits<base::Time>::Read(const Message* m, void** iter,
258 param_type* r) {
259 int64 value;
260 if (!ParamTraits<int64>::Read(m, iter, &value))
261 return false;
262 *r = base::Time::FromInternalValue(value);
263 return true;
264}
265
[email protected]252cad62010-08-18 18:33:57266void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
[email protected]7a4de7a62010-08-17 18:38:24267 ParamTraits<int64>::Log(p.ToInternalValue(), l);
268}
269
[email protected]d84e48b2010-10-21 22:04:52270void ParamTraits<base::TimeDelta> ::Write(Message* m, const param_type& p) {
271 ParamTraits<int64> ::Write(m, p.InMicroseconds());
272}
273
274bool ParamTraits<base::TimeDelta> ::Read(const Message* m,
275 void** iter,
276 param_type* r) {
277 int64 value;
278 bool ret = ParamTraits<int64> ::Read(m, iter, &value);
279 if (ret)
280 *r = base::TimeDelta::FromMicroseconds(value);
281
282 return ret;
283}
284
285void ParamTraits<base::TimeDelta> ::Log(const param_type& p, std::string* l) {
286 ParamTraits<int64> ::Log(p.InMicroseconds(), l);
287}
288
[email protected]946d1b22009-07-22 23:57:21289void ParamTraits<DictionaryValue>::Write(Message* m, const param_type& p) {
290 WriteValue(m, &p, 0);
291}
292
293bool ParamTraits<DictionaryValue>::Read(
294 const Message* m, void** iter, param_type* r) {
295 int type;
296 if (!ReadParam(m, iter, &type) || type != Value::TYPE_DICTIONARY)
297 return false;
298
299 return ReadDictionaryValue(m, iter, r, 0);
300}
301
[email protected]252cad62010-08-18 18:33:57302void ParamTraits<DictionaryValue>::Log(const param_type& p, std::string* l) {
[email protected]946d1b22009-07-22 23:57:21303 std::string json;
[email protected]93d49d72009-10-23 20:00:20304 base::JSONWriter::Write(&p, false, &json);
[email protected]252cad62010-08-18 18:33:57305 l->append(json);
[email protected]946d1b22009-07-22 23:57:21306}
307
308void ParamTraits<ListValue>::Write(Message* m, const param_type& p) {
309 WriteValue(m, &p, 0);
310}
311
312bool ParamTraits<ListValue>::Read(
313 const Message* m, void** iter, param_type* r) {
314 int type;
315 if (!ReadParam(m, iter, &type) || type != Value::TYPE_LIST)
316 return false;
317
318 return ReadListValue(m, iter, r, 0);
319}
320
[email protected]252cad62010-08-18 18:33:57321void ParamTraits<ListValue>::Log(const param_type& p, std::string* l) {
[email protected]946d1b22009-07-22 23:57:21322 std::string json;
[email protected]93d49d72009-10-23 20:00:20323 base::JSONWriter::Write(&p, false, &json);
[email protected]252cad62010-08-18 18:33:57324 l->append(json);
325}
326
327void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
328 l->append(WideToUTF8(p));
[email protected]946d1b22009-07-22 23:57:21329}
[email protected]7a4de7a62010-08-17 18:38:24330
331void ParamTraits<NullableString16>::Write(Message* m, const param_type& p) {
332 WriteParam(m, p.string());
333 WriteParam(m, p.is_null());
334}
335
336bool ParamTraits<NullableString16>::Read(const Message* m, void** iter,
337 param_type* r) {
338 string16 string;
339 if (!ReadParam(m, iter, &string))
340 return false;
341 bool is_null;
342 if (!ReadParam(m, iter, &is_null))
343 return false;
344 *r = NullableString16(string, is_null);
345 return true;
346}
347
[email protected]252cad62010-08-18 18:33:57348void ParamTraits<NullableString16>::Log(const param_type& p, std::string* l) {
349 l->append("(");
[email protected]7a4de7a62010-08-17 18:38:24350 LogParam(p.string(), l);
[email protected]252cad62010-08-18 18:33:57351 l->append(", ");
[email protected]7a4de7a62010-08-17 18:38:24352 LogParam(p.is_null(), l);
[email protected]252cad62010-08-18 18:33:57353 l->append(")");
[email protected]7a4de7a62010-08-17 18:38:24354}
355
[email protected]252cad62010-08-18 18:33:57356#if !defined(WCHAR_T_IS_UTF16)
357void ParamTraits<string16>::Log(const param_type& p, std::string* l) {
358 l->append(UTF16ToUTF8(p));
359}
360#endif
361
362
[email protected]7a4de7a62010-08-17 18:38:24363void ParamTraits<FilePath>::Write(Message* m, const param_type& p) {
364 ParamTraits<FilePath::StringType>::Write(m, p.value());
365}
366
367bool ParamTraits<FilePath>::Read(const Message* m, void** iter, param_type* r) {
368 FilePath::StringType value;
369 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
370 return false;
371 *r = FilePath(value);
372 return true;
373}
374
[email protected]252cad62010-08-18 18:33:57375void ParamTraits<FilePath>::Log(const param_type& p, std::string* l) {
[email protected]7a4de7a62010-08-17 18:38:24376 ParamTraits<FilePath::StringType>::Log(p.value(), l);
377}
378
379#if defined(OS_POSIX)
380void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
381 const bool valid = p.fd >= 0;
382 WriteParam(m, valid);
383
384 if (valid) {
385 if (!m->WriteFileDescriptor(p))
386 NOTREACHED();
387 }
388}
389
390bool ParamTraits<base::FileDescriptor>::Read(const Message* m, void** iter,
391 param_type* r) {
392 bool valid;
393 if (!ReadParam(m, iter, &valid))
394 return false;
395
396 if (!valid) {
397 r->fd = -1;
398 r->auto_close = false;
399 return true;
400 }
401
402 return m->ReadFileDescriptor(iter, r);
403}
404
405void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
[email protected]252cad62010-08-18 18:33:57406 std::string* l) {
[email protected]7a4de7a62010-08-17 18:38:24407 if (p.auto_close) {
[email protected]252cad62010-08-18 18:33:57408 l->append(StringPrintf("FD(%d auto-close)", p.fd));
[email protected]7a4de7a62010-08-17 18:38:24409 } else {
[email protected]252cad62010-08-18 18:33:57410 l->append(StringPrintf("FD(%d)", p.fd));
[email protected]7a4de7a62010-08-17 18:38:24411 }
412}
413#endif // defined(OS_POSIX)
414
415void 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);
419#endif
420}
421
422bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m, void** iter,
423 param_type* r) {
424 return ReadParam(m, iter, &r->name)
425#if defined(OS_POSIX)
426 && ReadParam(m, iter, &r->socket)
427#endif
428 ;
429}
430
431void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
[email protected]252cad62010-08-18 18:33:57432 std::string* l) {
433 l->append(StringPrintf("ChannelHandle(%s", p.name.c_str()));
[email protected]7a4de7a62010-08-17 18:38:24434#if defined(OS_POSIX)
435 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
436#endif
[email protected]252cad62010-08-18 18:33:57437 l->append(")");
[email protected]7a4de7a62010-08-17 18:38:24438}
439
[email protected]20f0487a2010-09-30 20:06:30440LogData::LogData() {
441}
442
443LogData::~LogData() {
444}
445
446void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
447 WriteParam(m, p.channel);
448 WriteParam(m, p.routing_id);
449 WriteParam(m, static_cast<int>(p.type));
450 WriteParam(m, p.flags);
451 WriteParam(m, p.sent);
452 WriteParam(m, p.receive);
453 WriteParam(m, p.dispatch);
454 WriteParam(m, p.params);
455}
456
457bool ParamTraits<LogData>::Read(const Message* m, void** iter, param_type* r) {
458 int type;
459 bool result =
460 ReadParam(m, iter, &r->channel) &&
461 ReadParam(m, iter, &r->routing_id) &&
462 ReadParam(m, iter, &type) &&
463 ReadParam(m, iter, &r->flags) &&
464 ReadParam(m, iter, &r->sent) &&
465 ReadParam(m, iter, &r->receive) &&
466 ReadParam(m, iter, &r->dispatch) &&
467 ReadParam(m, iter, &r->params);
468 r->type = static_cast<uint16>(type);
469 return result;
470}
471
[email protected]946d1b22009-07-22 23:57:21472} // namespace IPC