blob: 03d326ba159417aa9365d576b4980f82e8219e51 [file] [log] [blame]
amit@chromium.org37290742012-01-24 11:36:05 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +09002// 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
erg@google.come6ffcb52010-08-18 03:38:24 +09007#include "base/file_path.h"
brettw@chromium.org7cd41eb2009-10-24 05:00:20 +09008#include "base/json/json_writer.h"
levin@chromium.org5c528682011-03-28 10:54:15 +09009#include "base/memory/scoped_ptr.h"
erg@google.come6ffcb52010-08-18 03:38:24 +090010#include "base/nullable_string16.h"
erg@google.com8aca7272010-08-19 03:33:57 +090011#include "base/string_number_conversions.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090012#include "base/time.h"
erg@google.com8aca7272010-08-19 03:33:57 +090013#include "base/utf_string_conversions.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090014#include "base/values.h"
erg@google.come6ffcb52010-08-18 03:38:24 +090015#if defined(OS_POSIX)
16#include "ipc/file_descriptor_set_posix.h"
17#endif
18#include "ipc/ipc_channel_handle.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090019
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()) {
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090038 case Value::TYPE_NULL:
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090039 break;
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090040 case Value::TYPE_BOOLEAN: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090041 bool val;
42 value->GetAsBoolean(&val);
43 WriteParam(m, val);
44 break;
45 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090046 case Value::TYPE_INTEGER: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090047 int val;
48 value->GetAsInteger(&val);
49 WriteParam(m, val);
50 break;
51 }
arv@chromium.org13413eb2011-02-01 10:02:07 +090052 case Value::TYPE_DOUBLE: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090053 double val;
arv@chromium.org13413eb2011-02-01 10:02:07 +090054 value->GetAsDouble(&val);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090055 WriteParam(m, val);
56 break;
57 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090058 case Value::TYPE_STRING: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090059 std::string val;
60 value->GetAsString(&val);
61 WriteParam(m, val);
62 break;
63 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090064 case Value::TYPE_BINARY: {
tfarina@chromium.org2e2a9022011-08-06 03:20:05 +090065 const base::BinaryValue* binary =
66 static_cast<const base::BinaryValue*>(value);
thomasvl@google.com9a242072010-07-23 23:18:59 +090067 m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090068 break;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090069 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090070 case Value::TYPE_DICTIONARY: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090071 const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
72
pkasting@chromium.org36515db2009-11-26 05:47:52 +090073 WriteParam(m, static_cast<int>(dict->size()));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090074
75 for (DictionaryValue::key_iterator it = dict->begin_keys();
76 it != dict->end_keys(); ++it) {
77 Value* subval;
pkasting@chromium.org36515db2009-11-26 05:47:52 +090078 if (dict->GetWithoutPathExpansion(*it, &subval)) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090079 WriteParam(m, *it);
80 WriteValue(m, subval, recursion + 1);
81 } else {
82 NOTREACHED() << "DictionaryValue iterators are filthy liars.";
83 }
84 }
85 break;
86 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090087 case Value::TYPE_LIST: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090088 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) {
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900112 std::string key;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900113 Value* subval;
114 if (!ReadParam(m, iter, &key) ||
115 !ReadValue(m, iter, &subval, recursion + 1))
116 return false;
kalman@chromium.org9c8b5732011-08-19 14:59:57 +0900117 value->SetWithoutPathExpansion(key, subval);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900118 }
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) {
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900153 case Value::TYPE_NULL:
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900154 *value = Value::CreateNullValue();
155 break;
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900156 case Value::TYPE_BOOLEAN: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900157 bool val;
158 if (!ReadParam(m, iter, &val))
159 return false;
160 *value = Value::CreateBooleanValue(val);
161 break;
162 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900163 case Value::TYPE_INTEGER: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900164 int val;
165 if (!ReadParam(m, iter, &val))
166 return false;
167 *value = Value::CreateIntegerValue(val);
168 break;
169 }
arv@chromium.org13413eb2011-02-01 10:02:07 +0900170 case Value::TYPE_DOUBLE: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900171 double val;
172 if (!ReadParam(m, iter, &val))
173 return false;
arv@chromium.org13413eb2011-02-01 10:02:07 +0900174 *value = Value::CreateDoubleValue(val);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900175 break;
176 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900177 case Value::TYPE_STRING: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900178 std::string val;
179 if (!ReadParam(m, iter, &val))
180 return false;
181 *value = Value::CreateStringValue(val);
182 break;
183 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900184 case Value::TYPE_BINARY: {
185 const char* data;
186 int length;
187 if (!m->ReadData(iter, &data, &length))
188 return false;
tfarina@chromium.org2e2a9022011-08-06 03:20:05 +0900189 *value = base::BinaryValue::CreateWithCopiedBuffer(data, length);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900190 break;
191 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900192 case Value::TYPE_DICTIONARY: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900193 scoped_ptr<DictionaryValue> val(new DictionaryValue());
194 if (!ReadDictionaryValue(m, iter, val.get(), recursion))
195 return false;
196 *value = val.release();
197 break;
198 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900199 case Value::TYPE_LIST: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900200 scoped_ptr<ListValue> val(new ListValue());
201 if (!ReadListValue(m, iter, val.get(), recursion))
202 return false;
203 *value = val.release();
204 break;
205 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900206 default:
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900207 return false;
208 }
209
210 return true;
211}
212
erg@google.com8aca7272010-08-19 03:33:57 +0900213void 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}
erg@google.come6ffcb52010-08-18 03:38:24 +0900236
brettw@chromium.org1cd2d6d2010-11-13 01:25:01 +0900237void 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
erg@google.come6ffcb52010-08-18 03:38:24 +0900254void 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
erg@google.com8aca7272010-08-19 03:33:57 +0900267void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
erg@google.come6ffcb52010-08-18 03:38:24 +0900268 ParamTraits<int64>::Log(p.ToInternalValue(), l);
269}
270
apatrick@chromium.org519c1c62010-10-22 07:04:52 +0900271void ParamTraits<base::TimeDelta> ::Write(Message* m, const param_type& p) {
isherman@chromium.org9952aaf2011-09-03 05:42:04 +0900272 ParamTraits<int64> ::Write(m, p.ToInternalValue());
apatrick@chromium.org519c1c62010-10-22 07:04:52 +0900273}
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)
isherman@chromium.org9952aaf2011-09-03 05:42:04 +0900281 *r = base::TimeDelta::FromInternalValue(value);
apatrick@chromium.org519c1c62010-10-22 07:04:52 +0900282
283 return ret;
284}
285
286void ParamTraits<base::TimeDelta> ::Log(const param_type& p, std::string* l) {
isherman@chromium.org9952aaf2011-09-03 05:42:04 +0900287 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);
apatrick@chromium.org519c1c62010-10-22 07:04:52 +0900307}
308
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900309void 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
erg@google.com8aca7272010-08-19 03:33:57 +0900322void ParamTraits<DictionaryValue>::Log(const param_type& p, std::string* l) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900323 std::string json;
brettw@chromium.org7cd41eb2009-10-24 05:00:20 +0900324 base::JSONWriter::Write(&p, false, &json);
erg@google.com8aca7272010-08-19 03:33:57 +0900325 l->append(json);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900326}
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
erg@google.com8aca7272010-08-19 03:33:57 +0900341void ParamTraits<ListValue>::Log(const param_type& p, std::string* l) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900342 std::string json;
brettw@chromium.org7cd41eb2009-10-24 05:00:20 +0900343 base::JSONWriter::Write(&p, false, &json);
erg@google.com8aca7272010-08-19 03:33:57 +0900344 l->append(json);
345}
346
347void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
348 l->append(WideToUTF8(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900349}
erg@google.come6ffcb52010-08-18 03:38:24 +0900350
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
erg@google.com8aca7272010-08-19 03:33:57 +0900368void ParamTraits<NullableString16>::Log(const param_type& p, std::string* l) {
369 l->append("(");
erg@google.come6ffcb52010-08-18 03:38:24 +0900370 LogParam(p.string(), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900371 l->append(", ");
erg@google.come6ffcb52010-08-18 03:38:24 +0900372 LogParam(p.is_null(), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900373 l->append(")");
erg@google.come6ffcb52010-08-18 03:38:24 +0900374}
375
erg@google.com8aca7272010-08-19 03:33:57 +0900376#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
erg@google.come6ffcb52010-08-18 03:38:24 +0900383void 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
erg@google.com8aca7272010-08-19 03:33:57 +0900395void ParamTraits<FilePath>::Log(const param_type& p, std::string* l) {
erg@google.come6ffcb52010-08-18 03:38:24 +0900396 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,
erg@google.com8aca7272010-08-19 03:33:57 +0900426 std::string* l) {
erg@google.come6ffcb52010-08-18 03:38:24 +0900427 if (p.auto_close) {
erg@google.com8aca7272010-08-19 03:33:57 +0900428 l->append(StringPrintf("FD(%d auto-close)", p.fd));
erg@google.come6ffcb52010-08-18 03:38:24 +0900429 } else {
erg@google.com8aca7272010-08-19 03:33:57 +0900430 l->append(StringPrintf("FD(%d)", p.fd));
erg@google.come6ffcb52010-08-18 03:38:24 +0900431 }
432}
433#endif // defined(OS_POSIX)
434
435void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
amit@chromium.org37290742012-01-24 11:36:05 +0900436#if defined(OS_WIN)
437 // On Windows marshalling pipe handle is not supported.
438 DCHECK(p.pipe.handle == NULL);
439#endif // defined (OS_WIN)
erg@google.come6ffcb52010-08-18 03:38:24 +0900440 WriteParam(m, p.name);
441#if defined(OS_POSIX)
442 WriteParam(m, p.socket);
443#endif
444}
445
446bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m, void** iter,
447 param_type* r) {
448 return ReadParam(m, iter, &r->name)
449#if defined(OS_POSIX)
450 && ReadParam(m, iter, &r->socket)
451#endif
452 ;
453}
454
455void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
erg@google.com8aca7272010-08-19 03:33:57 +0900456 std::string* l) {
457 l->append(StringPrintf("ChannelHandle(%s", p.name.c_str()));
erg@google.come6ffcb52010-08-18 03:38:24 +0900458#if defined(OS_POSIX)
steveblock@chromium.org7a470312011-09-23 19:32:19 +0900459 l->append(", ");
erg@google.come6ffcb52010-08-18 03:38:24 +0900460 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
461#endif
erg@google.com8aca7272010-08-19 03:33:57 +0900462 l->append(")");
erg@google.come6ffcb52010-08-18 03:38:24 +0900463}
464
finnur@chromium.org5a9b4a92011-03-30 19:19:53 +0900465LogData::LogData()
466 : routing_id(0),
467 type(0),
468 sent(0),
469 receive(0),
470 dispatch(0) {
erg@google.com20b66e32010-10-01 05:06:30 +0900471}
472
473LogData::~LogData() {
474}
475
476void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
477 WriteParam(m, p.channel);
478 WriteParam(m, p.routing_id);
jam@chromium.org1d8d4d12011-10-18 07:15:27 +0900479 WriteParam(m, p.type);
erg@google.com20b66e32010-10-01 05:06:30 +0900480 WriteParam(m, p.flags);
481 WriteParam(m, p.sent);
482 WriteParam(m, p.receive);
483 WriteParam(m, p.dispatch);
484 WriteParam(m, p.params);
485}
486
487bool ParamTraits<LogData>::Read(const Message* m, void** iter, param_type* r) {
jam@chromium.org1d8d4d12011-10-18 07:15:27 +0900488 return
erg@google.com20b66e32010-10-01 05:06:30 +0900489 ReadParam(m, iter, &r->channel) &&
490 ReadParam(m, iter, &r->routing_id) &&
jam@chromium.org1d8d4d12011-10-18 07:15:27 +0900491 ReadParam(m, iter, &r->type) &&
erg@google.com20b66e32010-10-01 05:06:30 +0900492 ReadParam(m, iter, &r->flags) &&
493 ReadParam(m, iter, &r->sent) &&
494 ReadParam(m, iter, &r->receive) &&
495 ReadParam(m, iter, &r->dispatch) &&
496 ReadParam(m, iter, &r->params);
erg@google.com20b66e32010-10-01 05:06:30 +0900497}
498
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900499} // namespace IPC