blob: cc10cc272f396ba834d814615b0272e5e8619740 [file] [log] [blame]
pkasting@chromium.org36515db2009-11-26 05:47:52 +09001// Copyright (c) 2009 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"
erg@google.come6ffcb52010-08-18 03:38:24 +09009#include "base/nullable_string16.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090010#include "base/scoped_ptr.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 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090052 case Value::TYPE_REAL: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090053 double val;
54 value->GetAsReal(&val);
55 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: {
65 const BinaryValue* binary = static_cast<const BinaryValue*>(value);
thomasvl@google.com9a242072010-07-23 23:18:59 +090066 m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090067 break;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090068 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090069 case Value::TYPE_DICTIONARY: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090070 const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
71
pkasting@chromium.org36515db2009-11-26 05:47:52 +090072 WriteParam(m, static_cast<int>(dict->size()));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090073
74 for (DictionaryValue::key_iterator it = dict->begin_keys();
75 it != dict->end_keys(); ++it) {
76 Value* subval;
pkasting@chromium.org36515db2009-11-26 05:47:52 +090077 if (dict->GetWithoutPathExpansion(*it, &subval)) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090078 WriteParam(m, *it);
79 WriteValue(m, subval, recursion + 1);
80 } else {
81 NOTREACHED() << "DictionaryValue iterators are filthy liars.";
82 }
83 }
84 break;
85 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +090086 case Value::TYPE_LIST: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090087 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) {
viettrungluu@chromium.org178423d2010-07-31 04:47:47 +0900111 std::string key;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900112 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) {
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900152 case Value::TYPE_NULL:
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900153 *value = Value::CreateNullValue();
154 break;
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900155 case Value::TYPE_BOOLEAN: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900156 bool val;
157 if (!ReadParam(m, iter, &val))
158 return false;
159 *value = Value::CreateBooleanValue(val);
160 break;
161 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900162 case Value::TYPE_INTEGER: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900163 int val;
164 if (!ReadParam(m, iter, &val))
165 return false;
166 *value = Value::CreateIntegerValue(val);
167 break;
168 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900169 case Value::TYPE_REAL: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900170 double val;
171 if (!ReadParam(m, iter, &val))
172 return false;
173 *value = Value::CreateRealValue(val);
174 break;
175 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900176 case Value::TYPE_STRING: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900177 std::string val;
178 if (!ReadParam(m, iter, &val))
179 return false;
180 *value = Value::CreateStringValue(val);
181 break;
182 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900183 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);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900189 break;
190 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900191 case Value::TYPE_DICTIONARY: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900192 scoped_ptr<DictionaryValue> val(new DictionaryValue());
193 if (!ReadDictionaryValue(m, iter, val.get(), recursion))
194 return false;
195 *value = val.release();
196 break;
197 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900198 case Value::TYPE_LIST: {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900199 scoped_ptr<ListValue> val(new ListValue());
200 if (!ReadListValue(m, iter, val.get(), recursion))
201 return false;
202 *value = val.release();
203 break;
204 }
mpcomplete@chromium.org554d4312009-10-07 03:15:58 +0900205 default:
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900206 return false;
207 }
208
209 return true;
210}
211
erg@google.com8aca7272010-08-19 03:33:57 +0900212void 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}
erg@google.come6ffcb52010-08-18 03:38:24 +0900235
236void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
237 ParamTraits<int64>::Write(m, p.ToInternalValue());
238}
239
240bool ParamTraits<base::Time>::Read(const Message* m, void** iter,
241 param_type* r) {
242 int64 value;
243 if (!ParamTraits<int64>::Read(m, iter, &value))
244 return false;
245 *r = base::Time::FromInternalValue(value);
246 return true;
247}
248
erg@google.com8aca7272010-08-19 03:33:57 +0900249void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
erg@google.come6ffcb52010-08-18 03:38:24 +0900250 ParamTraits<int64>::Log(p.ToInternalValue(), l);
251}
252
apatrick@chromium.org519c1c62010-10-22 07:04:52 +0900253void ParamTraits<base::TimeDelta> ::Write(Message* m, const param_type& p) {
254 ParamTraits<int64> ::Write(m, p.InMicroseconds());
255}
256
257bool ParamTraits<base::TimeDelta> ::Read(const Message* m,
258 void** iter,
259 param_type* r) {
260 int64 value;
261 bool ret = ParamTraits<int64> ::Read(m, iter, &value);
262 if (ret)
263 *r = base::TimeDelta::FromMicroseconds(value);
264
265 return ret;
266}
267
268void ParamTraits<base::TimeDelta> ::Log(const param_type& p, std::string* l) {
269 ParamTraits<int64> ::Log(p.InMicroseconds(), l);
270}
271
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900272void ParamTraits<DictionaryValue>::Write(Message* m, const param_type& p) {
273 WriteValue(m, &p, 0);
274}
275
276bool ParamTraits<DictionaryValue>::Read(
277 const Message* m, void** iter, param_type* r) {
278 int type;
279 if (!ReadParam(m, iter, &type) || type != Value::TYPE_DICTIONARY)
280 return false;
281
282 return ReadDictionaryValue(m, iter, r, 0);
283}
284
erg@google.com8aca7272010-08-19 03:33:57 +0900285void ParamTraits<DictionaryValue>::Log(const param_type& p, std::string* l) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900286 std::string json;
brettw@chromium.org7cd41eb2009-10-24 05:00:20 +0900287 base::JSONWriter::Write(&p, false, &json);
erg@google.com8aca7272010-08-19 03:33:57 +0900288 l->append(json);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900289}
290
291void ParamTraits<ListValue>::Write(Message* m, const param_type& p) {
292 WriteValue(m, &p, 0);
293}
294
295bool ParamTraits<ListValue>::Read(
296 const Message* m, void** iter, param_type* r) {
297 int type;
298 if (!ReadParam(m, iter, &type) || type != Value::TYPE_LIST)
299 return false;
300
301 return ReadListValue(m, iter, r, 0);
302}
303
erg@google.com8aca7272010-08-19 03:33:57 +0900304void ParamTraits<ListValue>::Log(const param_type& p, std::string* l) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900305 std::string json;
brettw@chromium.org7cd41eb2009-10-24 05:00:20 +0900306 base::JSONWriter::Write(&p, false, &json);
erg@google.com8aca7272010-08-19 03:33:57 +0900307 l->append(json);
308}
309
310void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
311 l->append(WideToUTF8(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900312}
erg@google.come6ffcb52010-08-18 03:38:24 +0900313
314void ParamTraits<NullableString16>::Write(Message* m, const param_type& p) {
315 WriteParam(m, p.string());
316 WriteParam(m, p.is_null());
317}
318
319bool ParamTraits<NullableString16>::Read(const Message* m, void** iter,
320 param_type* r) {
321 string16 string;
322 if (!ReadParam(m, iter, &string))
323 return false;
324 bool is_null;
325 if (!ReadParam(m, iter, &is_null))
326 return false;
327 *r = NullableString16(string, is_null);
328 return true;
329}
330
erg@google.com8aca7272010-08-19 03:33:57 +0900331void ParamTraits<NullableString16>::Log(const param_type& p, std::string* l) {
332 l->append("(");
erg@google.come6ffcb52010-08-18 03:38:24 +0900333 LogParam(p.string(), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900334 l->append(", ");
erg@google.come6ffcb52010-08-18 03:38:24 +0900335 LogParam(p.is_null(), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900336 l->append(")");
erg@google.come6ffcb52010-08-18 03:38:24 +0900337}
338
erg@google.com8aca7272010-08-19 03:33:57 +0900339#if !defined(WCHAR_T_IS_UTF16)
340void ParamTraits<string16>::Log(const param_type& p, std::string* l) {
341 l->append(UTF16ToUTF8(p));
342}
343#endif
344
345
erg@google.come6ffcb52010-08-18 03:38:24 +0900346void ParamTraits<FilePath>::Write(Message* m, const param_type& p) {
347 ParamTraits<FilePath::StringType>::Write(m, p.value());
348}
349
350bool ParamTraits<FilePath>::Read(const Message* m, void** iter, param_type* r) {
351 FilePath::StringType value;
352 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
353 return false;
354 *r = FilePath(value);
355 return true;
356}
357
erg@google.com8aca7272010-08-19 03:33:57 +0900358void ParamTraits<FilePath>::Log(const param_type& p, std::string* l) {
erg@google.come6ffcb52010-08-18 03:38:24 +0900359 ParamTraits<FilePath::StringType>::Log(p.value(), l);
360}
361
362#if defined(OS_POSIX)
363void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
364 const bool valid = p.fd >= 0;
365 WriteParam(m, valid);
366
367 if (valid) {
368 if (!m->WriteFileDescriptor(p))
369 NOTREACHED();
370 }
371}
372
373bool ParamTraits<base::FileDescriptor>::Read(const Message* m, void** iter,
374 param_type* r) {
375 bool valid;
376 if (!ReadParam(m, iter, &valid))
377 return false;
378
379 if (!valid) {
380 r->fd = -1;
381 r->auto_close = false;
382 return true;
383 }
384
385 return m->ReadFileDescriptor(iter, r);
386}
387
388void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
erg@google.com8aca7272010-08-19 03:33:57 +0900389 std::string* l) {
erg@google.come6ffcb52010-08-18 03:38:24 +0900390 if (p.auto_close) {
erg@google.com8aca7272010-08-19 03:33:57 +0900391 l->append(StringPrintf("FD(%d auto-close)", p.fd));
erg@google.come6ffcb52010-08-18 03:38:24 +0900392 } else {
erg@google.com8aca7272010-08-19 03:33:57 +0900393 l->append(StringPrintf("FD(%d)", p.fd));
erg@google.come6ffcb52010-08-18 03:38:24 +0900394 }
395}
396#endif // defined(OS_POSIX)
397
398void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
399 WriteParam(m, p.name);
400#if defined(OS_POSIX)
401 WriteParam(m, p.socket);
402#endif
403}
404
405bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m, void** iter,
406 param_type* r) {
407 return ReadParam(m, iter, &r->name)
408#if defined(OS_POSIX)
409 && ReadParam(m, iter, &r->socket)
410#endif
411 ;
412}
413
414void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
erg@google.com8aca7272010-08-19 03:33:57 +0900415 std::string* l) {
416 l->append(StringPrintf("ChannelHandle(%s", p.name.c_str()));
erg@google.come6ffcb52010-08-18 03:38:24 +0900417#if defined(OS_POSIX)
418 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
419#endif
erg@google.com8aca7272010-08-19 03:33:57 +0900420 l->append(")");
erg@google.come6ffcb52010-08-18 03:38:24 +0900421}
422
erg@google.com20b66e32010-10-01 05:06:30 +0900423LogData::LogData() {
424}
425
426LogData::~LogData() {
427}
428
429void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
430 WriteParam(m, p.channel);
431 WriteParam(m, p.routing_id);
432 WriteParam(m, static_cast<int>(p.type));
433 WriteParam(m, p.flags);
434 WriteParam(m, p.sent);
435 WriteParam(m, p.receive);
436 WriteParam(m, p.dispatch);
437 WriteParam(m, p.params);
438}
439
440bool ParamTraits<LogData>::Read(const Message* m, void** iter, param_type* r) {
441 int type;
442 bool result =
443 ReadParam(m, iter, &r->channel) &&
444 ReadParam(m, iter, &r->routing_id) &&
445 ReadParam(m, iter, &type) &&
446 ReadParam(m, iter, &r->flags) &&
447 ReadParam(m, iter, &r->sent) &&
448 ReadParam(m, iter, &r->receive) &&
449 ReadParam(m, iter, &r->dispatch) &&
450 ReadParam(m, iter, &r->params);
451 r->type = static_cast<uint16>(type);
452 return result;
453}
454
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900455} // namespace IPC