blob: bf8daa5d9741189df50bdac48f7b39cf5744e5a2 [file] [log] [blame]
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001// Copyright (c) 2012 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.
4
5#include "ipc/ipc_message_utils.h"
6
7#include <stddef.h>
8#include <stdint.h>
9
10#include "base/files/file_path.h"
11#include "base/json/json_writer.h"
12#include "base/strings/nullable_string16.h"
13#include "base/strings/string_number_conversions.h"
14#include "base/strings/utf_string_conversions.h"
15#include "base/time/time.h"
Jay Civellicfc1eaa2017-08-21 17:18:10 -070016#include "base/unguessable_token.h"
Luis Hector Chavez645501c2016-12-28 10:56:26 -080017#include "base/values.h"
18#include "build/build_config.h"
19#include "ipc/ipc_channel_handle.h"
20#include "ipc/ipc_message_attachment.h"
21#include "ipc/ipc_message_attachment_set.h"
22#include "ipc/ipc_mojo_param_traits.h"
23
24#if defined(OS_POSIX)
Jay Civellicfc1eaa2017-08-21 17:18:10 -070025#include "base/file_descriptor_posix.h"
Luis Hector Chavez645501c2016-12-28 10:56:26 -080026#include "ipc/ipc_platform_file_attachment_posix.h"
27#endif
28
29#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
30#include "base/memory/shared_memory_handle.h"
31#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
32
33#if defined(OS_MACOSX) && !defined(OS_IOS)
34#include "ipc/mach_port_mac.h"
35#endif
36
37#if defined(OS_WIN)
38#include <tchar.h>
39#include "ipc/handle_win.h"
40#endif
41
42namespace IPC {
43
44namespace {
45
Jay Civellicfc1eaa2017-08-21 17:18:10 -070046const int kMaxRecursionDepth = 200;
Luis Hector Chavez645501c2016-12-28 10:56:26 -080047
48template<typename CharType>
49void LogBytes(const std::vector<CharType>& data, std::string* out) {
50#if defined(OS_WIN)
51 // Windows has a GUI for logging, which can handle arbitrary binary data.
52 for (size_t i = 0; i < data.size(); ++i)
53 out->push_back(data[i]);
54#else
55 // On POSIX, we log to stdout, which we assume can display ASCII.
56 static const size_t kMaxBytesToLog = 100;
57 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
58 if (isprint(data[i]))
59 out->push_back(data[i]);
60 else
61 out->append(
62 base::StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
63 }
64 if (data.size() > kMaxBytesToLog) {
65 out->append(base::StringPrintf(
66 " and %u more bytes",
67 static_cast<unsigned>(data.size() - kMaxBytesToLog)));
68 }
69#endif
70}
71
72bool ReadValue(const base::Pickle* m,
73 base::PickleIterator* iter,
74 base::Value** value,
75 int recursion);
76
77void GetValueSize(base::PickleSizer* sizer,
78 const base::Value* value,
79 int recursion) {
80 if (recursion > kMaxRecursionDepth) {
Jay Civellicfc1eaa2017-08-21 17:18:10 -070081 LOG(ERROR) << "Max recursion depth hit in GetValueSize.";
Luis Hector Chavez645501c2016-12-28 10:56:26 -080082 return;
83 }
84
85 sizer->AddInt();
86 switch (value->GetType()) {
Jay Civellicfc1eaa2017-08-21 17:18:10 -070087 case base::Value::Type::NONE:
Luis Hector Chavez645501c2016-12-28 10:56:26 -080088 break;
Jay Civellicfc1eaa2017-08-21 17:18:10 -070089 case base::Value::Type::BOOLEAN:
Luis Hector Chavez645501c2016-12-28 10:56:26 -080090 sizer->AddBool();
91 break;
Jay Civellicfc1eaa2017-08-21 17:18:10 -070092 case base::Value::Type::INTEGER:
Luis Hector Chavez645501c2016-12-28 10:56:26 -080093 sizer->AddInt();
94 break;
Jay Civellicfc1eaa2017-08-21 17:18:10 -070095 case base::Value::Type::DOUBLE:
Luis Hector Chavez645501c2016-12-28 10:56:26 -080096 sizer->AddDouble();
97 break;
Jay Civellicfc1eaa2017-08-21 17:18:10 -070098 case base::Value::Type::STRING: {
99 const base::Value* result;
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800100 value->GetAsString(&result);
101 if (value->GetAsString(&result)) {
102 DCHECK(result);
103 GetParamSize(sizer, result->GetString());
104 } else {
105 std::string str;
106 bool as_string_result = value->GetAsString(&str);
107 DCHECK(as_string_result);
108 GetParamSize(sizer, str);
109 }
110 break;
111 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700112 case base::Value::Type::BINARY: {
113 sizer->AddData(static_cast<int>(value->GetSize()));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800114 break;
115 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700116 case base::Value::Type::DICTIONARY: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800117 sizer->AddInt();
118 const base::DictionaryValue* dict =
119 static_cast<const base::DictionaryValue*>(value);
120 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
121 it.Advance()) {
122 GetParamSize(sizer, it.key());
123 GetValueSize(sizer, &it.value(), recursion + 1);
124 }
125 break;
126 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700127 case base::Value::Type::LIST: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800128 sizer->AddInt();
129 const base::ListValue* list = static_cast<const base::ListValue*>(value);
130 for (const auto& entry : *list) {
131 GetValueSize(sizer, entry.get(), recursion + 1);
132 }
133 break;
134 }
135 default:
136 NOTREACHED() << "Invalid base::Value type.";
137 }
138}
139
140void WriteValue(base::Pickle* m, const base::Value* value, int recursion) {
141 bool result;
142 if (recursion > kMaxRecursionDepth) {
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700143 LOG(ERROR) << "Max recursion depth hit in WriteValue.";
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800144 return;
145 }
146
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700147 m->WriteInt(static_cast<int>(value->GetType()));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800148
149 switch (value->GetType()) {
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700150 case base::Value::Type::NONE:
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800151 break;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700152 case base::Value::Type::BOOLEAN: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800153 bool val;
154 result = value->GetAsBoolean(&val);
155 DCHECK(result);
156 WriteParam(m, val);
157 break;
158 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700159 case base::Value::Type::INTEGER: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800160 int val;
161 result = value->GetAsInteger(&val);
162 DCHECK(result);
163 WriteParam(m, val);
164 break;
165 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700166 case base::Value::Type::DOUBLE: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800167 double val;
168 result = value->GetAsDouble(&val);
169 DCHECK(result);
170 WriteParam(m, val);
171 break;
172 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700173 case base::Value::Type::STRING: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800174 std::string val;
175 result = value->GetAsString(&val);
176 DCHECK(result);
177 WriteParam(m, val);
178 break;
179 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700180 case base::Value::Type::BINARY: {
181 m->WriteData(value->GetBuffer(), static_cast<int>(value->GetSize()));
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800182 break;
183 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700184 case base::Value::Type::DICTIONARY: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800185 const base::DictionaryValue* dict =
186 static_cast<const base::DictionaryValue*>(value);
187
188 WriteParam(m, static_cast<int>(dict->size()));
189
190 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
191 it.Advance()) {
192 WriteParam(m, it.key());
193 WriteValue(m, &it.value(), recursion + 1);
194 }
195 break;
196 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700197 case base::Value::Type::LIST: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800198 const base::ListValue* list = static_cast<const base::ListValue*>(value);
199 WriteParam(m, static_cast<int>(list->GetSize()));
200 for (const auto& entry : *list) {
201 WriteValue(m, entry.get(), recursion + 1);
202 }
203 break;
204 }
205 }
206}
207
208// Helper for ReadValue that reads a DictionaryValue into a pre-allocated
209// object.
210bool ReadDictionaryValue(const base::Pickle* m,
211 base::PickleIterator* iter,
212 base::DictionaryValue* value,
213 int recursion) {
214 int size;
215 if (!ReadParam(m, iter, &size))
216 return false;
217
218 for (int i = 0; i < size; ++i) {
219 std::string key;
220 base::Value* subval;
221 if (!ReadParam(m, iter, &key) ||
222 !ReadValue(m, iter, &subval, recursion + 1))
223 return false;
224 value->SetWithoutPathExpansion(key, subval);
225 }
226
227 return true;
228}
229
230// Helper for ReadValue that reads a ReadListValue into a pre-allocated
231// object.
232bool ReadListValue(const base::Pickle* m,
233 base::PickleIterator* iter,
234 base::ListValue* value,
235 int recursion) {
236 int size;
237 if (!ReadParam(m, iter, &size))
238 return false;
239
240 for (int i = 0; i < size; ++i) {
241 base::Value* subval;
242 if (!ReadValue(m, iter, &subval, recursion + 1))
243 return false;
244 value->Set(i, subval);
245 }
246
247 return true;
248}
249
250bool ReadValue(const base::Pickle* m,
251 base::PickleIterator* iter,
252 base::Value** value,
253 int recursion) {
254 if (recursion > kMaxRecursionDepth) {
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700255 LOG(ERROR) << "Max recursion depth hit in ReadValue.";
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800256 return false;
257 }
258
259 int type;
260 if (!ReadParam(m, iter, &type))
261 return false;
262
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700263 switch (static_cast<base::Value::Type>(type)) {
264 case base::Value::Type::NONE:
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800265 *value = base::Value::CreateNullValue().release();
266 break;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700267 case base::Value::Type::BOOLEAN: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800268 bool val;
269 if (!ReadParam(m, iter, &val))
270 return false;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700271 *value = new base::Value(val);
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800272 break;
273 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700274 case base::Value::Type::INTEGER: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800275 int val;
276 if (!ReadParam(m, iter, &val))
277 return false;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700278 *value = new base::Value(val);
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800279 break;
280 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700281 case base::Value::Type::DOUBLE: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800282 double val;
283 if (!ReadParam(m, iter, &val))
284 return false;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700285 *value = new base::Value(val);
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800286 break;
287 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700288 case base::Value::Type::STRING: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800289 std::string val;
290 if (!ReadParam(m, iter, &val))
291 return false;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700292 *value = new base::Value(val);
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800293 break;
294 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700295 case base::Value::Type::BINARY: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800296 const char* data;
297 int length;
298 if (!iter->ReadData(&data, &length))
299 return false;
300 std::unique_ptr<base::BinaryValue> val =
301 base::BinaryValue::CreateWithCopiedBuffer(data, length);
302 *value = val.release();
303 break;
304 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700305 case base::Value::Type::DICTIONARY: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800306 std::unique_ptr<base::DictionaryValue> val(new base::DictionaryValue());
307 if (!ReadDictionaryValue(m, iter, val.get(), recursion))
308 return false;
309 *value = val.release();
310 break;
311 }
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700312 case base::Value::Type::LIST: {
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800313 std::unique_ptr<base::ListValue> val(new base::ListValue());
314 if (!ReadListValue(m, iter, val.get(), recursion))
315 return false;
316 *value = val.release();
317 break;
318 }
319 default:
320 return false;
321 }
322
323 return true;
324}
325
326} // namespace
327
328// -----------------------------------------------------------------------------
329
330LogData::LogData()
331 : routing_id(0),
332 type(0),
333 sent(0),
334 receive(0),
335 dispatch(0) {
336}
337
338LogData::LogData(const LogData& other) = default;
339
340LogData::~LogData() {
341}
342
343void ParamTraits<bool>::Log(const param_type& p, std::string* l) {
344 l->append(p ? "true" : "false");
345}
346
347void ParamTraits<signed char>::GetSize(base::PickleSizer* sizer,
348 const param_type& p) {
349 sizer->AddBytes(sizeof(param_type));
350}
351
352void ParamTraits<signed char>::Write(base::Pickle* m, const param_type& p) {
353 m->WriteBytes(&p, sizeof(param_type));
354}
355
356bool ParamTraits<signed char>::Read(const base::Pickle* m,
357 base::PickleIterator* iter,
358 param_type* r) {
359 const char* data;
360 if (!iter->ReadBytes(&data, sizeof(param_type)))
361 return false;
362 memcpy(r, data, sizeof(param_type));
363 return true;
364}
365
366void ParamTraits<signed char>::Log(const param_type& p, std::string* l) {
367 l->append(base::IntToString(p));
368}
369
370void ParamTraits<unsigned char>::GetSize(base::PickleSizer* sizer,
371 const param_type& p) {
372 sizer->AddBytes(sizeof(param_type));
373}
374
375void ParamTraits<unsigned char>::Write(base::Pickle* m, const param_type& p) {
376 m->WriteBytes(&p, sizeof(param_type));
377}
378
379bool ParamTraits<unsigned char>::Read(const base::Pickle* m,
380 base::PickleIterator* iter,
381 param_type* r) {
382 const char* data;
383 if (!iter->ReadBytes(&data, sizeof(param_type)))
384 return false;
385 memcpy(r, data, sizeof(param_type));
386 return true;
387}
388
389void ParamTraits<unsigned char>::Log(const param_type& p, std::string* l) {
390 l->append(base::UintToString(p));
391}
392
393void ParamTraits<unsigned short>::GetSize(base::PickleSizer* sizer,
394 const param_type& p) {
395 sizer->AddBytes(sizeof(param_type));
396}
397
398void ParamTraits<unsigned short>::Write(base::Pickle* m, const param_type& p) {
399 m->WriteBytes(&p, sizeof(param_type));
400}
401
402bool ParamTraits<unsigned short>::Read(const base::Pickle* m,
403 base::PickleIterator* iter,
404 param_type* r) {
405 const char* data;
406 if (!iter->ReadBytes(&data, sizeof(param_type)))
407 return false;
408 memcpy(r, data, sizeof(param_type));
409 return true;
410}
411
412void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
413 l->append(base::UintToString(p));
414}
415
416void ParamTraits<int>::Log(const param_type& p, std::string* l) {
417 l->append(base::IntToString(p));
418}
419
420void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
421 l->append(base::UintToString(p));
422}
423
424#if defined(OS_WIN) || defined(OS_LINUX) || \
425 (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS))
426void ParamTraits<long>::Log(const param_type& p, std::string* l) {
427 l->append(base::Int64ToString(static_cast<int64_t>(p)));
428}
429
430void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
431 l->append(base::Uint64ToString(static_cast<uint64_t>(p)));
432}
433#endif
434
435void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
436 l->append(base::Int64ToString(static_cast<int64_t>(p)));
437}
438
439void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
440 l->append(base::Uint64ToString(p));
441}
442
443void ParamTraits<float>::Log(const param_type& p, std::string* l) {
444 l->append(base::StringPrintf("%e", p));
445}
446
447void ParamTraits<double>::GetSize(base::PickleSizer* sizer,
448 const param_type& p) {
449 sizer->AddBytes(sizeof(param_type));
450}
451
452void ParamTraits<double>::Write(base::Pickle* m, const param_type& p) {
453 m->WriteBytes(reinterpret_cast<const char*>(&p), sizeof(param_type));
454}
455
456bool ParamTraits<double>::Read(const base::Pickle* m,
457 base::PickleIterator* iter,
458 param_type* r) {
459 const char *data;
460 if (!iter->ReadBytes(&data, sizeof(*r))) {
461 NOTREACHED();
462 return false;
463 }
464 memcpy(r, data, sizeof(param_type));
465 return true;
466}
467
468void ParamTraits<double>::Log(const param_type& p, std::string* l) {
469 l->append(base::StringPrintf("%e", p));
470}
471
472
473void ParamTraits<std::string>::Log(const param_type& p, std::string* l) {
474 l->append(p);
475}
476
477void ParamTraits<base::string16>::Log(const param_type& p, std::string* l) {
478 l->append(base::UTF16ToUTF8(p));
479}
480
481void ParamTraits<std::vector<char>>::GetSize(base::PickleSizer* sizer,
482 const param_type& p) {
483 sizer->AddData(static_cast<int>(p.size()));
484}
485
486void ParamTraits<std::vector<char>>::Write(base::Pickle* m,
487 const param_type& p) {
488 if (p.empty()) {
489 m->WriteData(NULL, 0);
490 } else {
491 m->WriteData(&p.front(), static_cast<int>(p.size()));
492 }
493}
494
495bool ParamTraits<std::vector<char>>::Read(const base::Pickle* m,
496 base::PickleIterator* iter,
497 param_type* r) {
498 const char *data;
499 int data_size = 0;
500 if (!iter->ReadData(&data, &data_size) || data_size < 0)
501 return false;
502 r->resize(data_size);
503 if (data_size)
504 memcpy(&r->front(), data, data_size);
505 return true;
506}
507
508void ParamTraits<std::vector<char> >::Log(const param_type& p, std::string* l) {
509 LogBytes(p, l);
510}
511
512void ParamTraits<std::vector<unsigned char>>::GetSize(base::PickleSizer* sizer,
513 const param_type& p) {
514 sizer->AddData(static_cast<int>(p.size()));
515}
516
517void ParamTraits<std::vector<unsigned char>>::Write(base::Pickle* m,
518 const param_type& p) {
519 if (p.empty()) {
520 m->WriteData(NULL, 0);
521 } else {
522 m->WriteData(reinterpret_cast<const char*>(&p.front()),
523 static_cast<int>(p.size()));
524 }
525}
526
527bool ParamTraits<std::vector<unsigned char>>::Read(const base::Pickle* m,
528 base::PickleIterator* iter,
529 param_type* r) {
530 const char *data;
531 int data_size = 0;
532 if (!iter->ReadData(&data, &data_size) || data_size < 0)
533 return false;
534 r->resize(data_size);
535 if (data_size)
536 memcpy(&r->front(), data, data_size);
537 return true;
538}
539
540void ParamTraits<std::vector<unsigned char> >::Log(const param_type& p,
541 std::string* l) {
542 LogBytes(p, l);
543}
544
545void ParamTraits<std::vector<bool>>::GetSize(base::PickleSizer* sizer,
546 const param_type& p) {
547 GetParamSize(sizer, static_cast<int>(p.size()));
548 for (size_t i = 0; i < p.size(); ++i)
549 GetParamSize(sizer, static_cast<bool>(p[i]));
550}
551
552void ParamTraits<std::vector<bool>>::Write(base::Pickle* m,
553 const param_type& p) {
554 WriteParam(m, static_cast<int>(p.size()));
555 // Cast to bool below is required because libc++'s
556 // vector<bool>::const_reference is different from bool, and we want to avoid
557 // writing an extra specialization of ParamTraits for it.
558 for (size_t i = 0; i < p.size(); i++)
559 WriteParam(m, static_cast<bool>(p[i]));
560}
561
562bool ParamTraits<std::vector<bool>>::Read(const base::Pickle* m,
563 base::PickleIterator* iter,
564 param_type* r) {
565 int size;
566 // ReadLength() checks for < 0 itself.
567 if (!iter->ReadLength(&size))
568 return false;
569 r->resize(size);
570 for (int i = 0; i < size; i++) {
571 bool value;
572 if (!ReadParam(m, iter, &value))
573 return false;
574 (*r)[i] = value;
575 }
576 return true;
577}
578
579void ParamTraits<std::vector<bool> >::Log(const param_type& p, std::string* l) {
580 for (size_t i = 0; i < p.size(); ++i) {
581 if (i != 0)
582 l->push_back(' ');
583 LogParam(static_cast<bool>(p[i]), l);
584 }
585}
586
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800587void ParamTraits<base::DictionaryValue>::GetSize(base::PickleSizer* sizer,
588 const param_type& p) {
589 GetValueSize(sizer, &p, 0);
590}
591
592void ParamTraits<base::DictionaryValue>::Write(base::Pickle* m,
593 const param_type& p) {
594 WriteValue(m, &p, 0);
595}
596
597bool ParamTraits<base::DictionaryValue>::Read(const base::Pickle* m,
598 base::PickleIterator* iter,
599 param_type* r) {
600 int type;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700601 if (!ReadParam(m, iter, &type) ||
602 type != static_cast<int>(base::Value::Type::DICTIONARY))
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800603 return false;
604
605 return ReadDictionaryValue(m, iter, r, 0);
606}
607
608void ParamTraits<base::DictionaryValue>::Log(const param_type& p,
609 std::string* l) {
610 std::string json;
611 base::JSONWriter::Write(p, &json);
612 l->append(json);
613}
614
615#if defined(OS_POSIX)
616void ParamTraits<base::FileDescriptor>::GetSize(base::PickleSizer* sizer,
617 const param_type& p) {
618 GetParamSize(sizer, p.fd >= 0);
619 if (p.fd >= 0)
620 sizer->AddAttachment();
621}
622
623void ParamTraits<base::FileDescriptor>::Write(base::Pickle* m,
624 const param_type& p) {
625 const bool valid = p.fd >= 0;
626 WriteParam(m, valid);
627
628 if (!valid)
629 return;
630
631 if (p.auto_close) {
632 if (!m->WriteAttachment(
633 new internal::PlatformFileAttachment(base::ScopedFD(p.fd))))
634 NOTREACHED();
635 } else {
636 if (!m->WriteAttachment(new internal::PlatformFileAttachment(p.fd)))
637 NOTREACHED();
638 }
639}
640
641bool ParamTraits<base::FileDescriptor>::Read(const base::Pickle* m,
642 base::PickleIterator* iter,
643 param_type* r) {
644 *r = base::FileDescriptor();
645
646 bool valid;
647 if (!ReadParam(m, iter, &valid))
648 return false;
649
650 // TODO(morrita): Seems like this should return false.
651 if (!valid)
652 return true;
653
654 scoped_refptr<base::Pickle::Attachment> attachment;
655 if (!m->ReadAttachment(iter, &attachment))
656 return false;
657
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700658 if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
659 MessageAttachment::Type::PLATFORM_FILE) {
660 return false;
661 }
662
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800663 *r = base::FileDescriptor(
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700664 static_cast<internal::PlatformFileAttachment*>(attachment.get())
665 ->TakePlatformFile(),
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800666 true);
667 return true;
668}
669
670void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
671 std::string* l) {
672 if (p.auto_close) {
673 l->append(base::StringPrintf("FD(%d auto-close)", p.fd));
674 } else {
675 l->append(base::StringPrintf("FD(%d)", p.fd));
676 }
677}
678#endif // defined(OS_POSIX)
679
680#if defined(OS_MACOSX) && !defined(OS_IOS)
681void ParamTraits<base::SharedMemoryHandle>::GetSize(base::PickleSizer* sizer,
682 const param_type& p) {
683 GetParamSize(sizer, p.GetMemoryObject());
684 uint32_t dummy = 0;
685 GetParamSize(sizer, dummy);
686}
687
688void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m,
689 const param_type& p) {
690 MachPortMac mach_port_mac(p.GetMemoryObject());
691 ParamTraits<MachPortMac>::Write(m, mach_port_mac);
692 size_t size = 0;
693 bool result = p.GetSize(&size);
694 DCHECK(result);
695 ParamTraits<uint32_t>::Write(m, static_cast<uint32_t>(size));
696
697 // If the caller intended to pass ownership to the IPC stack, release a
698 // reference.
699 if (p.OwnershipPassesToIPC())
700 p.Close();
701}
702
703bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m,
704 base::PickleIterator* iter,
705 param_type* r) {
706 MachPortMac mach_port_mac;
707 if (!ParamTraits<MachPortMac>::Read(m, iter, &mach_port_mac))
708 return false;
709
710 uint32_t size;
711 if (!ParamTraits<uint32_t>::Read(m, iter, &size))
712 return false;
713
714 *r = base::SharedMemoryHandle(mach_port_mac.get_mach_port(),
715 static_cast<size_t>(size),
716 base::GetCurrentProcId());
717 return true;
718}
719
720void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p,
721 std::string* l) {
722 l->append("Mach port: ");
723 LogParam(p.GetMemoryObject(), l);
724}
725
726#elif defined(OS_WIN)
727void ParamTraits<base::SharedMemoryHandle>::GetSize(base::PickleSizer* s,
728 const param_type& p) {
729 GetParamSize(s, p.NeedsBrokering());
730 if (p.NeedsBrokering()) {
731 GetParamSize(s, p.GetHandle());
732 } else {
733 GetParamSize(s, HandleToLong(p.GetHandle()));
734 }
735}
736
737void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m,
738 const param_type& p) {
739 m->WriteBool(p.NeedsBrokering());
740
741 if (p.NeedsBrokering()) {
742 HandleWin handle_win(p.GetHandle(), HandleWin::DUPLICATE);
743 ParamTraits<HandleWin>::Write(m, handle_win);
744
745 // If the caller intended to pass ownership to the IPC stack, release a
746 // reference.
747 if (p.OwnershipPassesToIPC() && p.BelongsToCurrentProcess())
748 p.Close();
749 } else {
750 m->WriteInt(HandleToLong(p.GetHandle()));
751 }
752}
753
754bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m,
755 base::PickleIterator* iter,
756 param_type* r) {
757 bool needs_brokering;
758 if (!iter->ReadBool(&needs_brokering))
759 return false;
760
761 if (needs_brokering) {
762 HandleWin handle_win;
763 if (!ParamTraits<HandleWin>::Read(m, iter, &handle_win))
764 return false;
765 *r = base::SharedMemoryHandle(handle_win.get_handle(),
766 base::GetCurrentProcId());
767 return true;
768 }
769
770 int handle_int;
771 if (!iter->ReadInt(&handle_int))
772 return false;
773 HANDLE handle = LongToHandle(handle_int);
774 *r = base::SharedMemoryHandle(handle, base::GetCurrentProcId());
775 return true;
776}
777
778void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p,
779 std::string* l) {
780 LogParam(p.GetHandle(), l);
781 l->append(" needs brokering: ");
782 LogParam(p.NeedsBrokering(), l);
783}
784#endif // defined(OS_MACOSX) && !defined(OS_IOS)
785
786void ParamTraits<base::FilePath>::GetSize(base::PickleSizer* sizer,
787 const param_type& p) {
788 p.GetSizeForPickle(sizer);
789}
790
791void ParamTraits<base::FilePath>::Write(base::Pickle* m, const param_type& p) {
792 p.WriteToPickle(m);
793}
794
795bool ParamTraits<base::FilePath>::Read(const base::Pickle* m,
796 base::PickleIterator* iter,
797 param_type* r) {
798 return r->ReadFromPickle(iter);
799}
800
801void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) {
802 ParamTraits<base::FilePath::StringType>::Log(p.value(), l);
803}
804
805void ParamTraits<base::ListValue>::GetSize(base::PickleSizer* sizer,
806 const param_type& p) {
807 GetValueSize(sizer, &p, 0);
808}
809
810void ParamTraits<base::ListValue>::Write(base::Pickle* m, const param_type& p) {
811 WriteValue(m, &p, 0);
812}
813
814bool ParamTraits<base::ListValue>::Read(const base::Pickle* m,
815 base::PickleIterator* iter,
816 param_type* r) {
817 int type;
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700818 if (!ReadParam(m, iter, &type) ||
819 type != static_cast<int>(base::Value::Type::LIST))
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800820 return false;
821
822 return ReadListValue(m, iter, r, 0);
823}
824
825void ParamTraits<base::ListValue>::Log(const param_type& p, std::string* l) {
826 std::string json;
827 base::JSONWriter::Write(p, &json);
828 l->append(json);
829}
830
831void ParamTraits<base::NullableString16>::GetSize(base::PickleSizer* sizer,
832 const param_type& p) {
833 GetParamSize(sizer, p.string());
834 GetParamSize(sizer, p.is_null());
835}
836
837void ParamTraits<base::NullableString16>::Write(base::Pickle* m,
838 const param_type& p) {
839 WriteParam(m, p.string());
840 WriteParam(m, p.is_null());
841}
842
843bool ParamTraits<base::NullableString16>::Read(const base::Pickle* m,
844 base::PickleIterator* iter,
845 param_type* r) {
846 base::string16 string;
847 if (!ReadParam(m, iter, &string))
848 return false;
849 bool is_null;
850 if (!ReadParam(m, iter, &is_null))
851 return false;
852 *r = base::NullableString16(string, is_null);
853 return true;
854}
855
856void ParamTraits<base::NullableString16>::Log(const param_type& p,
857 std::string* l) {
858 l->append("(");
859 LogParam(p.string(), l);
860 l->append(", ");
861 LogParam(p.is_null(), l);
862 l->append(")");
863}
864
865void ParamTraits<base::File::Info>::GetSize(base::PickleSizer* sizer,
866 const param_type& p) {
867 GetParamSize(sizer, p.size);
868 GetParamSize(sizer, p.is_directory);
869 GetParamSize(sizer, p.last_modified.ToDoubleT());
870 GetParamSize(sizer, p.last_accessed.ToDoubleT());
871 GetParamSize(sizer, p.creation_time.ToDoubleT());
872}
873
874void ParamTraits<base::File::Info>::Write(base::Pickle* m,
875 const param_type& p) {
876 WriteParam(m, p.size);
877 WriteParam(m, p.is_directory);
878 WriteParam(m, p.last_modified.ToDoubleT());
879 WriteParam(m, p.last_accessed.ToDoubleT());
880 WriteParam(m, p.creation_time.ToDoubleT());
881}
882
883bool ParamTraits<base::File::Info>::Read(const base::Pickle* m,
884 base::PickleIterator* iter,
885 param_type* p) {
886 double last_modified, last_accessed, creation_time;
887 if (!ReadParam(m, iter, &p->size) ||
888 !ReadParam(m, iter, &p->is_directory) ||
889 !ReadParam(m, iter, &last_modified) ||
890 !ReadParam(m, iter, &last_accessed) ||
891 !ReadParam(m, iter, &creation_time))
892 return false;
893 p->last_modified = base::Time::FromDoubleT(last_modified);
894 p->last_accessed = base::Time::FromDoubleT(last_accessed);
895 p->creation_time = base::Time::FromDoubleT(creation_time);
896 return true;
897}
898
899void ParamTraits<base::File::Info>::Log(const param_type& p,
900 std::string* l) {
901 l->append("(");
902 LogParam(p.size, l);
903 l->append(",");
904 LogParam(p.is_directory, l);
905 l->append(",");
906 LogParam(p.last_modified.ToDoubleT(), l);
907 l->append(",");
908 LogParam(p.last_accessed.ToDoubleT(), l);
909 l->append(",");
910 LogParam(p.creation_time.ToDoubleT(), l);
911 l->append(")");
912}
913
914void ParamTraits<base::Time>::GetSize(base::PickleSizer* sizer,
915 const param_type& p) {
916 sizer->AddInt64();
917}
918
919void ParamTraits<base::Time>::Write(base::Pickle* m, const param_type& p) {
920 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
921}
922
923bool ParamTraits<base::Time>::Read(const base::Pickle* m,
924 base::PickleIterator* iter,
925 param_type* r) {
926 int64_t value;
927 if (!ParamTraits<int64_t>::Read(m, iter, &value))
928 return false;
929 *r = base::Time::FromInternalValue(value);
930 return true;
931}
932
933void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
934 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
935}
936
937void ParamTraits<base::TimeDelta>::GetSize(base::PickleSizer* sizer,
938 const param_type& p) {
939 sizer->AddInt64();
940}
941
942void ParamTraits<base::TimeDelta>::Write(base::Pickle* m, const param_type& p) {
943 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
944}
945
946bool ParamTraits<base::TimeDelta>::Read(const base::Pickle* m,
947 base::PickleIterator* iter,
948 param_type* r) {
949 int64_t value;
950 bool ret = ParamTraits<int64_t>::Read(m, iter, &value);
951 if (ret)
952 *r = base::TimeDelta::FromInternalValue(value);
953
954 return ret;
955}
956
957void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) {
958 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
959}
960
961void ParamTraits<base::TimeTicks>::GetSize(base::PickleSizer* sizer,
962 const param_type& p) {
963 sizer->AddInt64();
964}
965
966void ParamTraits<base::TimeTicks>::Write(base::Pickle* m, const param_type& p) {
967 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
968}
969
970bool ParamTraits<base::TimeTicks>::Read(const base::Pickle* m,
971 base::PickleIterator* iter,
972 param_type* r) {
973 int64_t value;
974 bool ret = ParamTraits<int64_t>::Read(m, iter, &value);
975 if (ret)
976 *r = base::TimeTicks::FromInternalValue(value);
977
978 return ret;
979}
980
981void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) {
982 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
983}
984
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700985// If base::UnguessableToken is no longer 128 bits, the IPC serialization logic
986// below should be updated.
987static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t),
988 "base::UnguessableToken should be of size 2 * sizeof(uint64_t).");
989
990void ParamTraits<base::UnguessableToken>::GetSize(base::PickleSizer* sizer,
991 const param_type& p) {
992 sizer->AddBytes(2 * sizeof(uint64_t));
993}
994
995void ParamTraits<base::UnguessableToken>::Write(base::Pickle* m,
996 const param_type& p) {
997 DCHECK(!p.is_empty());
998
999 ParamTraits<uint64_t>::Write(m, p.GetHighForSerialization());
1000 ParamTraits<uint64_t>::Write(m, p.GetLowForSerialization());
1001}
1002
1003bool ParamTraits<base::UnguessableToken>::Read(const base::Pickle* m,
1004 base::PickleIterator* iter,
1005 param_type* r) {
1006 uint64_t high, low;
1007 if (!ParamTraits<uint64_t>::Read(m, iter, &high) ||
1008 !ParamTraits<uint64_t>::Read(m, iter, &low))
1009 return false;
1010
1011 // Receiving a zeroed UnguessableToken is a security issue.
1012 if (high == 0 && low == 0)
1013 return false;
1014
1015 *r = base::UnguessableToken::Deserialize(high, low);
1016 return true;
1017}
1018
1019void ParamTraits<base::UnguessableToken>::Log(const param_type& p,
1020 std::string* l) {
1021 l->append(p.ToString());
1022}
1023
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001024void ParamTraits<IPC::ChannelHandle>::GetSize(base::PickleSizer* sizer,
1025 const param_type& p) {
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001026#if defined(OS_NACL_SFI)
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001027 GetParamSize(sizer, p.socket);
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001028#else
Luis Hector Chavez21a249e2017-07-26 17:38:05 +00001029 GetParamSize(sizer, p.mojo_handle);
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001030#endif
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001031}
1032
1033void ParamTraits<IPC::ChannelHandle>::Write(base::Pickle* m,
1034 const param_type& p) {
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001035#if defined(OS_NACL_SFI)
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001036 WriteParam(m, p.socket);
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001037#else
Luis Hector Chavez21a249e2017-07-26 17:38:05 +00001038 WriteParam(m, p.mojo_handle);
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001039#endif
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001040}
1041
1042bool ParamTraits<IPC::ChannelHandle>::Read(const base::Pickle* m,
1043 base::PickleIterator* iter,
1044 param_type* r) {
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001045#if defined(OS_NACL_SFI)
1046 return ReadParam(m, iter, &r->socket);
1047#else
1048 return ReadParam(m, iter, &r->mojo_handle);
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001049#endif
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001050}
1051
1052void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
1053 std::string* l) {
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001054 l->append("ChannelHandle(");
1055#if defined(OS_NACL_SFI)
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001056 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001057#else
Luis Hector Chavez21a249e2017-07-26 17:38:05 +00001058 LogParam(p.mojo_handle, l);
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001059#endif
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001060 l->append(")");
1061}
1062
1063void ParamTraits<LogData>::GetSize(base::PickleSizer* sizer,
1064 const param_type& p) {
1065 GetParamSize(sizer, p.channel);
1066 GetParamSize(sizer, p.routing_id);
1067 GetParamSize(sizer, p.type);
1068 GetParamSize(sizer, p.flags);
1069 GetParamSize(sizer, p.sent);
1070 GetParamSize(sizer, p.receive);
1071 GetParamSize(sizer, p.dispatch);
1072 GetParamSize(sizer, p.message_name);
1073 GetParamSize(sizer, p.params);
1074}
1075
1076void ParamTraits<LogData>::Write(base::Pickle* m, const param_type& p) {
1077 WriteParam(m, p.channel);
1078 WriteParam(m, p.routing_id);
1079 WriteParam(m, p.type);
1080 WriteParam(m, p.flags);
1081 WriteParam(m, p.sent);
1082 WriteParam(m, p.receive);
1083 WriteParam(m, p.dispatch);
1084 WriteParam(m, p.message_name);
1085 WriteParam(m, p.params);
1086}
1087
1088bool ParamTraits<LogData>::Read(const base::Pickle* m,
1089 base::PickleIterator* iter,
1090 param_type* r) {
1091 return
1092 ReadParam(m, iter, &r->channel) &&
1093 ReadParam(m, iter, &r->routing_id) &&
1094 ReadParam(m, iter, &r->type) &&
1095 ReadParam(m, iter, &r->flags) &&
1096 ReadParam(m, iter, &r->sent) &&
1097 ReadParam(m, iter, &r->receive) &&
1098 ReadParam(m, iter, &r->dispatch) &&
1099 ReadParam(m, iter, &r->message_name) &&
1100 ReadParam(m, iter, &r->params);
1101}
1102
1103void ParamTraits<LogData>::Log(const param_type& p, std::string* l) {
1104 // Doesn't make sense to implement this!
1105}
1106
1107void ParamTraits<Message>::Write(base::Pickle* m, const Message& p) {
1108#if defined(OS_POSIX)
1109 // We don't serialize the file descriptors in the nested message, so there
1110 // better not be any.
1111 DCHECK(!p.HasAttachments());
1112#endif
1113
1114 // Don't just write out the message. This is used to send messages between
1115 // NaCl (Posix environment) and the browser (could be on Windows). The message
1116 // header formats differ between these systems (so does handle sharing, but
1117 // we already asserted we don't have any handles). So just write out the
1118 // parts of the header we use.
1119 //
1120 // Be careful also to use only explicitly-sized types. The NaCl environment
1121 // could be 64-bit and the host browser could be 32-bits. The nested message
1122 // may or may not be safe to send between 32-bit and 64-bit systems, but we
1123 // leave that up to the code sending the message to ensure.
1124 m->WriteUInt32(static_cast<uint32_t>(p.routing_id()));
1125 m->WriteUInt32(p.type());
1126 m->WriteUInt32(p.flags());
1127 m->WriteData(p.payload(), static_cast<uint32_t>(p.payload_size()));
1128}
1129
1130bool ParamTraits<Message>::Read(const base::Pickle* m,
1131 base::PickleIterator* iter,
1132 Message* r) {
1133 uint32_t routing_id, type, flags;
1134 if (!iter->ReadUInt32(&routing_id) ||
1135 !iter->ReadUInt32(&type) ||
1136 !iter->ReadUInt32(&flags))
1137 return false;
1138
1139 int payload_size;
1140 const char* payload;
1141 if (!iter->ReadData(&payload, &payload_size))
1142 return false;
1143
1144 r->SetHeaderValues(static_cast<int32_t>(routing_id), type, flags);
1145 return r->WriteBytes(payload, payload_size);
1146}
1147
1148void ParamTraits<Message>::Log(const Message& p, std::string* l) {
1149 l->append("<IPC::Message>");
1150}
1151
1152#if defined(OS_WIN)
1153void ParamTraits<HANDLE>::GetSize(base::PickleSizer* sizer,
1154 const param_type& p) {
1155 sizer->AddInt();
1156}
1157
1158// Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
1159// bit systems. That's why we use the Windows macros to convert to 32 bits.
1160void ParamTraits<HANDLE>::Write(base::Pickle* m, const param_type& p) {
1161 m->WriteInt(HandleToLong(p));
1162}
1163
1164bool ParamTraits<HANDLE>::Read(const base::Pickle* m,
1165 base::PickleIterator* iter,
1166 param_type* r) {
1167 int32_t temp;
1168 if (!iter->ReadInt(&temp))
1169 return false;
1170 *r = LongToHandle(temp);
1171 return true;
1172}
1173
1174void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) {
1175 l->append(base::StringPrintf("0x%p", p));
1176}
1177
1178void ParamTraits<LOGFONT>::GetSize(base::PickleSizer* sizer,
1179 const param_type& p) {
1180 sizer->AddData(sizeof(LOGFONT));
1181}
1182
1183void ParamTraits<LOGFONT>::Write(base::Pickle* m, const param_type& p) {
1184 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
1185}
1186
1187bool ParamTraits<LOGFONT>::Read(const base::Pickle* m,
1188 base::PickleIterator* iter,
1189 param_type* r) {
1190 const char *data;
1191 int data_size = 0;
1192 if (iter->ReadData(&data, &data_size) && data_size == sizeof(LOGFONT)) {
1193 const LOGFONT *font = reinterpret_cast<LOGFONT*>(const_cast<char*>(data));
1194 if (_tcsnlen(font->lfFaceName, LF_FACESIZE) < LF_FACESIZE) {
1195 memcpy(r, data, sizeof(LOGFONT));
1196 return true;
1197 }
1198 }
1199
1200 NOTREACHED();
1201 return false;
1202}
1203
1204void ParamTraits<LOGFONT>::Log(const param_type& p, std::string* l) {
1205 l->append(base::StringPrintf("<LOGFONT>"));
1206}
1207
1208void ParamTraits<MSG>::GetSize(base::PickleSizer* sizer, const param_type& p) {
1209 sizer->AddData(sizeof(MSG));
1210}
1211
1212void ParamTraits<MSG>::Write(base::Pickle* m, const param_type& p) {
1213 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
1214}
1215
1216bool ParamTraits<MSG>::Read(const base::Pickle* m,
1217 base::PickleIterator* iter,
1218 param_type* r) {
1219 const char *data;
1220 int data_size = 0;
1221 bool result = iter->ReadData(&data, &data_size);
1222 if (result && data_size == sizeof(MSG)) {
1223 memcpy(r, data, sizeof(MSG));
1224 } else {
1225 result = false;
1226 NOTREACHED();
1227 }
1228
1229 return result;
1230}
1231
1232void ParamTraits<MSG>::Log(const param_type& p, std::string* l) {
1233 l->append("<MSG>");
1234}
1235
1236#endif // OS_WIN
1237
1238} // namespace IPC