blob: bc5f6459c4f30154bb27cfbfef929acdbde0820f [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: {
[email protected]b59ea312011-08-05 18:20:0565 const base::BinaryValue* binary =
66 static_cast<const base::BinaryValue*>(value);
[email protected]7ee1a44c2010-07-23 14:18:5967 m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
[email protected]e4dad9fb2009-10-06 18:15:5868 break;
[email protected]946d1b22009-07-22 23:57:2169 }
[email protected]e4dad9fb2009-10-06 18:15:5870 case Value::TYPE_DICTIONARY: {
[email protected]946d1b22009-07-22 23:57:2171 const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
72
[email protected]4dad9ad82009-11-25 20:47:5273 WriteParam(m, static_cast<int>(dict->size()));
[email protected]946d1b22009-07-22 23:57:2174
75 for (DictionaryValue::key_iterator it = dict->begin_keys();
76 it != dict->end_keys(); ++it) {
77 Value* subval;
[email protected]4dad9ad82009-11-25 20:47:5278 if (dict->GetWithoutPathExpansion(*it, &subval)) {
[email protected]946d1b22009-07-22 23:57:2179 WriteParam(m, *it);
80 WriteValue(m, subval, recursion + 1);
81 } else {
82 NOTREACHED() << "DictionaryValue iterators are filthy liars.";
83 }
84 }
85 break;
86 }
[email protected]e4dad9fb2009-10-06 18:15:5887 case Value::TYPE_LIST: {
[email protected]946d1b22009-07-22 23:57:2188 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) {
91 Value* subval;
92 if (list->Get(i, &subval)) {
93 WriteValue(m, subval, recursion + 1);
94 } else {
95 NOTREACHED() << "ListValue::GetSize is a filthy liar.";
96 }
97 }
98 break;
99 }
100 }
101}
102
103// Helper for ReadValue that reads a DictionaryValue into a pre-allocated
104// object.
105static bool ReadDictionaryValue(const Message* m, void** iter,
106 DictionaryValue* value, int recursion) {
107 int size;
108 if (!ReadParam(m, iter, &size))
109 return false;
110
111 for (int i = 0; i < size; ++i) {
[email protected]e7b418b2010-07-30 19:47:47112 std::string key;
[email protected]946d1b22009-07-22 23:57:21113 Value* subval;
114 if (!ReadParam(m, iter, &key) ||
115 !ReadValue(m, iter, &subval, recursion + 1))
116 return false;
[email protected]d8b4aa42011-08-19 05:59:57117 value->SetWithoutPathExpansion(key, subval);
[email protected]946d1b22009-07-22 23:57:21118 }
119
120 return true;
121}
122
123// Helper for ReadValue that reads a ReadListValue into a pre-allocated
124// object.
125static bool ReadListValue(const Message* m, void** iter,
126 ListValue* value, int recursion) {
127 int size;
128 if (!ReadParam(m, iter, &size))
129 return false;
130
131 for (int i = 0; i < size; ++i) {
132 Value* subval;
133 if (!ReadValue(m, iter, &subval, recursion + 1))
134 return false;
135 value->Set(i, subval);
136 }
137
138 return true;
139}
140
141static bool ReadValue(const Message* m, void** iter, Value** value,
142 int recursion) {
143 if (recursion > kMaxRecursionDepth) {
144 LOG(WARNING) << "Max recursion depth hit in ReadValue.";
145 return false;
146 }
147
148 int type;
149 if (!ReadParam(m, iter, &type))
150 return false;
151
152 switch (type) {
[email protected]e4dad9fb2009-10-06 18:15:58153 case Value::TYPE_NULL:
[email protected]946d1b22009-07-22 23:57:21154 *value = Value::CreateNullValue();
155 break;
[email protected]e4dad9fb2009-10-06 18:15:58156 case Value::TYPE_BOOLEAN: {
[email protected]946d1b22009-07-22 23:57:21157 bool val;
158 if (!ReadParam(m, iter, &val))
159 return false;
160 *value = Value::CreateBooleanValue(val);
161 break;
162 }
[email protected]e4dad9fb2009-10-06 18:15:58163 case Value::TYPE_INTEGER: {
[email protected]946d1b22009-07-22 23:57:21164 int val;
165 if (!ReadParam(m, iter, &val))
166 return false;
167 *value = Value::CreateIntegerValue(val);
168 break;
169 }
[email protected]fb534c92011-02-01 01:02:07170 case Value::TYPE_DOUBLE: {
[email protected]946d1b22009-07-22 23:57:21171 double val;
172 if (!ReadParam(m, iter, &val))
173 return false;
[email protected]fb534c92011-02-01 01:02:07174 *value = Value::CreateDoubleValue(val);
[email protected]946d1b22009-07-22 23:57:21175 break;
176 }
[email protected]e4dad9fb2009-10-06 18:15:58177 case Value::TYPE_STRING: {
[email protected]946d1b22009-07-22 23:57:21178 std::string val;
179 if (!ReadParam(m, iter, &val))
180 return false;
181 *value = Value::CreateStringValue(val);
182 break;
183 }
[email protected]e4dad9fb2009-10-06 18:15:58184 case Value::TYPE_BINARY: {
185 const char* data;
186 int length;
187 if (!m->ReadData(iter, &data, &length))
188 return false;
[email protected]b59ea312011-08-05 18:20:05189 *value = base::BinaryValue::CreateWithCopiedBuffer(data, length);
[email protected]946d1b22009-07-22 23:57:21190 break;
191 }
[email protected]e4dad9fb2009-10-06 18:15:58192 case Value::TYPE_DICTIONARY: {
[email protected]946d1b22009-07-22 23:57:21193 scoped_ptr<DictionaryValue> val(new DictionaryValue());
194 if (!ReadDictionaryValue(m, iter, val.get(), recursion))
195 return false;
196 *value = val.release();
197 break;
198 }
[email protected]e4dad9fb2009-10-06 18:15:58199 case Value::TYPE_LIST: {
[email protected]946d1b22009-07-22 23:57:21200 scoped_ptr<ListValue> val(new ListValue());
201 if (!ReadListValue(m, iter, val.get(), recursion))
202 return false;
203 *value = val.release();
204 break;
205 }
[email protected]e4dad9fb2009-10-06 18:15:58206 default:
[email protected]946d1b22009-07-22 23:57:21207 return false;
208 }
209
210 return true;
211}
212
[email protected]252cad62010-08-18 18:33:57213void ParamTraits<int>::Log(const param_type& p, std::string* l) {
214 l->append(base::IntToString(p));
215}
216
217void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
218 l->append(base::UintToString(p));
219}
220
221void ParamTraits<long>::Log(const param_type& p, std::string* l) {
222 l->append(base::Int64ToString(static_cast<int64>(p)));
223}
224
225void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
226 l->append(base::Uint64ToString(static_cast<uint64>(p)));
227}
228
229void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
230 l->append(base::Int64ToString(static_cast<int64>(p)));
231}
232
233void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
234 l->append(base::Uint64ToString(p));
235}
[email protected]7a4de7a62010-08-17 18:38:24236
[email protected]43a40202010-11-12 16:25:01237void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) {
238 m->WriteBytes(&p, sizeof(param_type));
239}
240
241bool ParamTraits<unsigned short>::Read(const Message* m, void** iter,
242 param_type* r) {
243 const char* data;
244 if (!m->ReadBytes(iter, &data, sizeof(param_type)))
245 return false;
246 memcpy(r, data, sizeof(param_type));
247 return true;
248}
249
250void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
251 l->append(base::UintToString(p));
252}
253
[email protected]7a4de7a62010-08-17 18:38:24254void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
255 ParamTraits<int64>::Write(m, p.ToInternalValue());
256}
257
258bool ParamTraits<base::Time>::Read(const Message* m, void** iter,
259 param_type* r) {
260 int64 value;
261 if (!ParamTraits<int64>::Read(m, iter, &value))
262 return false;
263 *r = base::Time::FromInternalValue(value);
264 return true;
265}
266
[email protected]252cad62010-08-18 18:33:57267void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
[email protected]7a4de7a62010-08-17 18:38:24268 ParamTraits<int64>::Log(p.ToInternalValue(), l);
269}
270
[email protected]d84e48b2010-10-21 22:04:52271void ParamTraits<base::TimeDelta> ::Write(Message* m, const param_type& p) {
[email protected]1d14f582011-09-02 20:42:04272 ParamTraits<int64> ::Write(m, p.ToInternalValue());
[email protected]d84e48b2010-10-21 22:04:52273}
274
275bool ParamTraits<base::TimeDelta> ::Read(const Message* m,
276 void** iter,
277 param_type* r) {
278 int64 value;
279 bool ret = ParamTraits<int64> ::Read(m, iter, &value);
280 if (ret)
[email protected]1d14f582011-09-02 20:42:04281 *r = base::TimeDelta::FromInternalValue(value);
[email protected]d84e48b2010-10-21 22:04:52282
283 return ret;
284}
285
286void ParamTraits<base::TimeDelta> ::Log(const param_type& p, std::string* l) {
[email protected]1d14f582011-09-02 20:42:04287 ParamTraits<int64> ::Log(p.ToInternalValue(), l);
288}
289
290void ParamTraits<base::TimeTicks> ::Write(Message* m, const param_type& p) {
291 ParamTraits<int64> ::Write(m, p.ToInternalValue());
292}
293
294bool ParamTraits<base::TimeTicks> ::Read(const Message* m,
295 void** iter,
296 param_type* r) {
297 int64 value;
298 bool ret = ParamTraits<int64> ::Read(m, iter, &value);
299 if (ret)
300 *r = base::TimeTicks::FromInternalValue(value);
301
302 return ret;
303}
304
305void ParamTraits<base::TimeTicks> ::Log(const param_type& p, std::string* l) {
306 ParamTraits<int64> ::Log(p.ToInternalValue(), l);
[email protected]d84e48b2010-10-21 22:04:52307}
308
[email protected]946d1b22009-07-22 23:57:21309void ParamTraits<DictionaryValue>::Write(Message* m, const param_type& p) {
310 WriteValue(m, &p, 0);
311}
312
313bool ParamTraits<DictionaryValue>::Read(
314 const Message* m, void** iter, param_type* r) {
315 int type;
316 if (!ReadParam(m, iter, &type) || type != Value::TYPE_DICTIONARY)
317 return false;
318
319 return ReadDictionaryValue(m, iter, r, 0);
320}
321
[email protected]252cad62010-08-18 18:33:57322void ParamTraits<DictionaryValue>::Log(const param_type& p, std::string* l) {
[email protected]946d1b22009-07-22 23:57:21323 std::string json;
[email protected]93d49d72009-10-23 20:00:20324 base::JSONWriter::Write(&p, false, &json);
[email protected]252cad62010-08-18 18:33:57325 l->append(json);
[email protected]946d1b22009-07-22 23:57:21326}
327
328void ParamTraits<ListValue>::Write(Message* m, const param_type& p) {
329 WriteValue(m, &p, 0);
330}
331
332bool ParamTraits<ListValue>::Read(
333 const Message* m, void** iter, param_type* r) {
334 int type;
335 if (!ReadParam(m, iter, &type) || type != Value::TYPE_LIST)
336 return false;
337
338 return ReadListValue(m, iter, r, 0);
339}
340
[email protected]252cad62010-08-18 18:33:57341void ParamTraits<ListValue>::Log(const param_type& p, std::string* l) {
[email protected]946d1b22009-07-22 23:57:21342 std::string json;
[email protected]93d49d72009-10-23 20:00:20343 base::JSONWriter::Write(&p, false, &json);
[email protected]252cad62010-08-18 18:33:57344 l->append(json);
345}
346
347void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
348 l->append(WideToUTF8(p));
[email protected]946d1b22009-07-22 23:57:21349}
[email protected]7a4de7a62010-08-17 18:38:24350
351void ParamTraits<NullableString16>::Write(Message* m, const param_type& p) {
352 WriteParam(m, p.string());
353 WriteParam(m, p.is_null());
354}
355
356bool ParamTraits<NullableString16>::Read(const Message* m, void** iter,
357 param_type* r) {
358 string16 string;
359 if (!ReadParam(m, iter, &string))
360 return false;
361 bool is_null;
362 if (!ReadParam(m, iter, &is_null))
363 return false;
364 *r = NullableString16(string, is_null);
365 return true;
366}
367
[email protected]252cad62010-08-18 18:33:57368void ParamTraits<NullableString16>::Log(const param_type& p, std::string* l) {
369 l->append("(");
[email protected]7a4de7a62010-08-17 18:38:24370 LogParam(p.string(), l);
[email protected]252cad62010-08-18 18:33:57371 l->append(", ");
[email protected]7a4de7a62010-08-17 18:38:24372 LogParam(p.is_null(), l);
[email protected]252cad62010-08-18 18:33:57373 l->append(")");
[email protected]7a4de7a62010-08-17 18:38:24374}
375
[email protected]252cad62010-08-18 18:33:57376#if !defined(WCHAR_T_IS_UTF16)
377void ParamTraits<string16>::Log(const param_type& p, std::string* l) {
378 l->append(UTF16ToUTF8(p));
379}
380#endif
381
382
[email protected]7a4de7a62010-08-17 18:38:24383void ParamTraits<FilePath>::Write(Message* m, const param_type& p) {
384 ParamTraits<FilePath::StringType>::Write(m, p.value());
385}
386
387bool ParamTraits<FilePath>::Read(const Message* m, void** iter, param_type* r) {
388 FilePath::StringType value;
389 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
390 return false;
391 *r = FilePath(value);
392 return true;
393}
394
[email protected]252cad62010-08-18 18:33:57395void ParamTraits<FilePath>::Log(const param_type& p, std::string* l) {
[email protected]7a4de7a62010-08-17 18:38:24396 ParamTraits<FilePath::StringType>::Log(p.value(), l);
397}
398
399#if defined(OS_POSIX)
400void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
401 const bool valid = p.fd >= 0;
402 WriteParam(m, valid);
403
404 if (valid) {
405 if (!m->WriteFileDescriptor(p))
406 NOTREACHED();
407 }
408}
409
410bool ParamTraits<base::FileDescriptor>::Read(const Message* m, void** iter,
411 param_type* r) {
412 bool valid;
413 if (!ReadParam(m, iter, &valid))
414 return false;
415
416 if (!valid) {
417 r->fd = -1;
418 r->auto_close = false;
419 return true;
420 }
421
422 return m->ReadFileDescriptor(iter, r);
423}
424
425void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
[email protected]252cad62010-08-18 18:33:57426 std::string* l) {
[email protected]7a4de7a62010-08-17 18:38:24427 if (p.auto_close) {
[email protected]252cad62010-08-18 18:33:57428 l->append(StringPrintf("FD(%d auto-close)", p.fd));
[email protected]7a4de7a62010-08-17 18:38:24429 } else {
[email protected]252cad62010-08-18 18:33:57430 l->append(StringPrintf("FD(%d)", p.fd));
[email protected]7a4de7a62010-08-17 18:38:24431 }
432}
433#endif // defined(OS_POSIX)
434
435void 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);
439#endif
440}
441
442bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m, void** iter,
443 param_type* r) {
444 return ReadParam(m, iter, &r->name)
445#if defined(OS_POSIX)
446 && ReadParam(m, iter, &r->socket)
447#endif
448 ;
449}
450
451void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
[email protected]252cad62010-08-18 18:33:57452 std::string* l) {
453 l->append(StringPrintf("ChannelHandle(%s", p.name.c_str()));
[email protected]7a4de7a62010-08-17 18:38:24454#if defined(OS_POSIX)
[email protected]3cd3bce2011-09-23 10:32:19455 l->append(", ");
[email protected]7a4de7a62010-08-17 18:38:24456 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
457#endif
[email protected]252cad62010-08-18 18:33:57458 l->append(")");
[email protected]7a4de7a62010-08-17 18:38:24459}
460
[email protected]5c622af2011-03-30 10:19:53461LogData::LogData()
462 : routing_id(0),
463 type(0),
464 sent(0),
465 receive(0),
466 dispatch(0) {
[email protected]20f0487a2010-09-30 20:06:30467}
468
469LogData::~LogData() {
470}
471
472void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
473 WriteParam(m, p.channel);
474 WriteParam(m, p.routing_id);
[email protected]8bf55ca2011-10-17 22:15:27475 WriteParam(m, p.type);
[email protected]20f0487a2010-09-30 20:06:30476 WriteParam(m, p.flags);
477 WriteParam(m, p.sent);
478 WriteParam(m, p.receive);
479 WriteParam(m, p.dispatch);
480 WriteParam(m, p.params);
481}
482
483bool ParamTraits<LogData>::Read(const Message* m, void** iter, param_type* r) {
[email protected]8bf55ca2011-10-17 22:15:27484 return
[email protected]20f0487a2010-09-30 20:06:30485 ReadParam(m, iter, &r->channel) &&
486 ReadParam(m, iter, &r->routing_id) &&
[email protected]8bf55ca2011-10-17 22:15:27487 ReadParam(m, iter, &r->type) &&
[email protected]20f0487a2010-09-30 20:06:30488 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);
[email protected]20f0487a2010-09-30 20:06:30493}
494
[email protected]946d1b22009-07-22 23:57:21495} // namespace IPC