[M120 Migration][VD] Enable direct rendering for TVPlus
[platform/framework/web/chromium-efl.git] / ipc / ipc_message_utils.cc
1 // Copyright 2012 The Chromium Authors
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 <type_traits>
11
12 #include "base/files/file_path.h"
13 #include "base/json/json_writer.h"
14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/notreached.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/time/time.h"
21 #include "base/unguessable_token.h"
22 #include "build/build_config.h"
23 #include "ipc/ipc_channel_handle.h"
24 #include "ipc/ipc_message.h"
25 #include "ipc/ipc_message_attachment.h"
26 #include "ipc/ipc_message_attachment_set.h"
27 #include "ipc/ipc_mojo_param_traits.h"
28 #include "third_party/abseil-cpp/absl/strings/ascii.h"
29
30 #if BUILDFLAG(IS_APPLE)
31 #include "ipc/mach_port_mac.h"
32 #endif
33
34 #if BUILDFLAG(IS_WIN)
35 #include <tchar.h>
36 #include "ipc/handle_win.h"
37 #include "ipc/ipc_platform_file.h"
38 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
39 #include "base/file_descriptor_posix.h"
40 #include "ipc/ipc_platform_file_attachment_posix.h"
41 #endif
42
43 #if BUILDFLAG(IS_FUCHSIA)
44 #include "base/fuchsia/fuchsia_logging.h"
45 #include "ipc/handle_attachment_fuchsia.h"
46 #endif
47
48 #if BUILDFLAG(IS_ANDROID)
49 #include "base/android/scoped_hardware_buffer_handle.h"
50 #include "ipc/ipc_mojo_handle_attachment.h"
51 #include "mojo/public/cpp/system/message_pipe.h"
52 #include "mojo/public/cpp/system/scope_to_message_pipe.h"
53 #endif
54
55 namespace IPC {
56
57 namespace {
58
59 const int kMaxRecursionDepth = 200;
60
61 template<typename CharType>
62 void LogBytes(const std::vector<CharType>& data, std::string* out) {
63 #if BUILDFLAG(IS_WIN)
64   // Windows has a GUI for logging, which can handle arbitrary binary data.
65   for (size_t i = 0; i < data.size(); ++i)
66     out->push_back(data[i]);
67 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
68   // On POSIX, we log to stdout, which we assume can display ASCII.
69   static const size_t kMaxBytesToLog = 100;
70   for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
71     if (absl::ascii_isprint(static_cast<unsigned char>(data[i]))) {
72       out->push_back(data[i]);
73     } else {
74       out->append(
75           base::StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
76     }
77   }
78   if (data.size() > kMaxBytesToLog) {
79     out->append(base::StringPrintf(
80         " and %u more bytes",
81         static_cast<unsigned>(data.size() - kMaxBytesToLog)));
82   }
83 #endif
84 }
85
86 template <typename CharType>
87 void WriteCharVector(base::Pickle* m, const std::vector<CharType>& p) {
88   static_assert(sizeof(CharType) == 1);
89   static_assert(std::is_integral_v<CharType>);
90   if (p.empty()) {
91     m->WriteData(nullptr, 0);
92   } else {
93     const char* data = reinterpret_cast<const char*>(p.data());
94     m->WriteData(data, p.size());
95   }
96 }
97
98 template <typename CharType>
99 bool ReadCharVector(const base::Pickle* m,
100                     base::PickleIterator* iter,
101                     std::vector<CharType>* r) {
102   static_assert(sizeof(CharType) == 1);
103   static_assert(std::is_integral_v<CharType>);
104   const char* data;
105   size_t data_size = 0;
106   if (!iter->ReadData(&data, &data_size)) {
107     return false;
108   }
109   const CharType* begin = reinterpret_cast<const CharType*>(data);
110   const CharType* end = begin + data_size;
111   r->assign(begin, end);
112   return true;
113 }
114
115 void WriteValue(const base::Value& value, int recursion, base::Pickle* pickle);
116
117 void WriteDictValue(const base::Value::Dict& value,
118                     int recursion,
119                     base::Pickle* pickle) {
120   WriteParam(pickle, base::checked_cast<int>(value.size()));
121   for (const auto entry : value) {
122     WriteParam(pickle, entry.first);
123     WriteValue(entry.second, recursion + 1, pickle);
124   }
125 }
126
127 void WriteListValue(const base::Value::List& value,
128                     int recursion,
129                     base::Pickle* pickle) {
130   WriteParam(pickle, base::checked_cast<int>(value.size()));
131   for (const auto& entry : value) {
132     WriteValue(entry, recursion + 1, pickle);
133   }
134 }
135
136 void WriteValue(const base::Value& value, int recursion, base::Pickle* pickle) {
137   bool result;
138   if (recursion > kMaxRecursionDepth) {
139     LOG(ERROR) << "Max recursion depth hit in WriteValue.";
140     return;
141   }
142
143   pickle->WriteInt(static_cast<int>(value.type()));
144
145   switch (value.type()) {
146     case base::Value::Type::NONE:
147       break;
148     case base::Value::Type::BOOLEAN: {
149       WriteParam(pickle, value.GetBool());
150       break;
151     }
152     case base::Value::Type::INTEGER: {
153       DCHECK(value.is_int());
154       WriteParam(pickle, value.GetInt());
155       break;
156     }
157     case base::Value::Type::DOUBLE: {
158       DCHECK(value.is_int() || value.is_double());
159       WriteParam(pickle, value.GetDouble());
160       break;
161     }
162     case base::Value::Type::STRING: {
163       const std::string* val = value.GetIfString();
164       result = !!val;
165       DCHECK(result);
166       WriteParam(pickle, *val);
167       break;
168     }
169     case base::Value::Type::BINARY: {
170       pickle->WriteData(reinterpret_cast<const char*>(value.GetBlob().data()),
171                         value.GetBlob().size());
172       break;
173     }
174     case base::Value::Type::DICT: {
175       DCHECK(value.is_dict());
176       WriteDictValue(value.GetDict(), recursion, pickle);
177       break;
178     }
179     case base::Value::Type::LIST: {
180       DCHECK(value.is_list());
181       WriteListValue(value.GetList(), recursion, pickle);
182       break;
183     }
184   }
185 }
186
187 bool ReadValue(const base::Pickle* pickle,
188                base::PickleIterator* iter,
189                int recursion,
190                base::Value* value);
191
192 // Helper for ReadValue that reads a Value::Dict into a pre-allocated object.
193 bool ReadDictValue(const base::Pickle* pickle,
194                    base::PickleIterator* iter,
195                    int recursion,
196                    base::Value::Dict* value) {
197   int size;
198   if (!ReadParam(pickle, iter, &size))
199     return false;
200
201   for (int i = 0; i < size; i++) {
202     std::string key;
203     base::Value subvalue;
204     if (!ReadParam(pickle, iter, &key) ||
205         !ReadValue(pickle, iter, recursion + 1, &subvalue)) {
206       return false;
207     }
208     value->Set(key, std::move(subvalue));
209   }
210
211   return true;
212 }
213
214 // Helper for ReadValue that reads a Value::List into a pre-allocated object.
215 bool ReadListValue(const base::Pickle* pickle,
216                    base::PickleIterator* iter,
217                    int recursion,
218                    base::Value::List* value) {
219   int size;
220   if (!ReadParam(pickle, iter, &size))
221     return false;
222
223   value->reserve(size);
224   for (int i = 0; i < size; i++) {
225     base::Value subval;
226     if (!ReadValue(pickle, iter, recursion + 1, &subval))
227       return false;
228     value->Append(std::move(subval));
229   }
230   return true;
231 }
232
233 bool ReadValue(const base::Pickle* pickle,
234                base::PickleIterator* iter,
235                int recursion,
236                base::Value* value) {
237   if (recursion > kMaxRecursionDepth) {
238     LOG(ERROR) << "Max recursion depth hit in ReadValue.";
239     return false;
240   }
241
242   int type;
243   if (!ReadParam(pickle, iter, &type))
244     return false;
245
246   constexpr int kMinValueType = static_cast<int>(base::Value::Type::NONE);
247   constexpr int kMaxValueType = static_cast<int>(base::Value::Type::LIST);
248   if (type > kMaxValueType || type < kMinValueType)
249     return false;
250
251   switch (static_cast<base::Value::Type>(type)) {
252     case base::Value::Type::NONE:
253       *value = base::Value();
254       break;
255     case base::Value::Type::BOOLEAN: {
256       bool val;
257       if (!ReadParam(pickle, iter, &val))
258         return false;
259       *value = base::Value(val);
260       break;
261     }
262     case base::Value::Type::INTEGER: {
263       int val;
264       if (!ReadParam(pickle, iter, &val))
265         return false;
266       *value = base::Value(val);
267       break;
268     }
269     case base::Value::Type::DOUBLE: {
270       double val;
271       if (!ReadParam(pickle, iter, &val))
272         return false;
273       *value = base::Value(val);
274       break;
275     }
276     case base::Value::Type::STRING: {
277       std::string val;
278       if (!ReadParam(pickle, iter, &val))
279         return false;
280       *value = base::Value(std::move(val));
281       break;
282     }
283     case base::Value::Type::BINARY: {
284       absl::optional<base::span<const uint8_t>> data = iter->ReadData();
285       if (!data) {
286         return false;
287       }
288       *value = base::Value(*data);
289       break;
290     }
291     case base::Value::Type::DICT: {
292       base::Value::Dict val;
293       if (!ReadDictValue(pickle, iter, recursion, &val))
294         return false;
295       *value = base::Value(std::move(val));
296       break;
297     }
298     case base::Value::Type::LIST: {
299       base::Value::List val;
300       if (!ReadListValue(pickle, iter, recursion, &val))
301         return false;
302       *value = base::Value(std::move(val));
303       break;
304     }
305     default:
306       NOTREACHED();
307       return false;
308   }
309
310   return true;
311 }
312
313 }  // namespace
314
315 // -----------------------------------------------------------------------------
316
317 LogData::LogData()
318     : routing_id(0),
319       type(0),
320       sent(0),
321       receive(0),
322       dispatch(0) {
323 }
324
325 LogData::LogData(const LogData& other) = default;
326
327 LogData::~LogData() = default;
328
329 void ParamTraits<bool>::Log(const param_type& p, std::string* l) {
330   l->append(p ? "true" : "false");
331 }
332
333 void ParamTraits<signed char>::Write(base::Pickle* m, const param_type& p) {
334   m->WriteBytes(&p, sizeof(param_type));
335 }
336
337 bool ParamTraits<signed char>::Read(const base::Pickle* m,
338                                     base::PickleIterator* iter,
339                                     param_type* r) {
340   const char* data;
341   if (!iter->ReadBytes(&data, sizeof(param_type)))
342     return false;
343   memcpy(r, data, sizeof(param_type));
344   return true;
345 }
346
347 void ParamTraits<signed char>::Log(const param_type& p, std::string* l) {
348   l->append(base::NumberToString(p));
349 }
350
351 void ParamTraits<unsigned char>::Write(base::Pickle* m, const param_type& p) {
352   m->WriteBytes(&p, sizeof(param_type));
353 }
354
355 bool ParamTraits<unsigned char>::Read(const base::Pickle* m,
356                                       base::PickleIterator* iter,
357                                       param_type* r) {
358   const char* data;
359   if (!iter->ReadBytes(&data, sizeof(param_type)))
360     return false;
361   memcpy(r, data, sizeof(param_type));
362   return true;
363 }
364
365 void ParamTraits<unsigned char>::Log(const param_type& p, std::string* l) {
366   l->append(base::NumberToString(p));
367 }
368
369 void ParamTraits<unsigned short>::Write(base::Pickle* m, const param_type& p) {
370   m->WriteBytes(&p, sizeof(param_type));
371 }
372
373 bool ParamTraits<unsigned short>::Read(const base::Pickle* m,
374                                        base::PickleIterator* iter,
375                                        param_type* r) {
376   const char* data;
377   if (!iter->ReadBytes(&data, sizeof(param_type)))
378     return false;
379   memcpy(r, data, sizeof(param_type));
380   return true;
381 }
382
383 void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
384   l->append(base::NumberToString(p));
385 }
386
387 void ParamTraits<int>::Log(const param_type& p, std::string* l) {
388   l->append(base::NumberToString(p));
389 }
390
391 void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
392   l->append(base::NumberToString(p));
393 }
394
395 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
396     BUILDFLAG(IS_FUCHSIA) ||                                              \
397     (BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_64_BITS))
398 void ParamTraits<long>::Log(const param_type& p, std::string* l) {
399   l->append(base::NumberToString(p));
400 }
401
402 void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
403   l->append(base::NumberToString(p));
404 }
405 #endif
406
407 void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
408   l->append(base::NumberToString(p));
409 }
410
411 void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
412   l->append(base::NumberToString(p));
413 }
414
415 void ParamTraits<float>::Log(const param_type& p, std::string* l) {
416   l->append(base::StringPrintf("%e", p));
417 }
418
419 void ParamTraits<double>::Write(base::Pickle* m, const param_type& p) {
420   m->WriteBytes(reinterpret_cast<const char*>(&p), sizeof(param_type));
421 }
422
423 bool ParamTraits<double>::Read(const base::Pickle* m,
424                                base::PickleIterator* iter,
425                                param_type* r) {
426   const char *data;
427   if (!iter->ReadBytes(&data, sizeof(*r))) {
428     NOTREACHED();
429     return false;
430   }
431   memcpy(r, data, sizeof(param_type));
432   return true;
433 }
434
435 void ParamTraits<double>::Log(const param_type& p, std::string* l) {
436   l->append(base::StringPrintf("%e", p));
437 }
438
439
440 void ParamTraits<std::string>::Log(const param_type& p, std::string* l) {
441   l->append(p);
442 }
443
444 void ParamTraits<std::u16string>::Log(const param_type& p, std::string* l) {
445   l->append(base::UTF16ToUTF8(p));
446 }
447
448 #if BUILDFLAG(IS_WIN)
449 bool ParamTraits<std::wstring>::Read(const base::Pickle* m,
450                                      base::PickleIterator* iter,
451                                      param_type* r) {
452   base::StringPiece16 piece16;
453   if (!iter->ReadStringPiece16(&piece16))
454     return false;
455
456   *r = base::AsWString(piece16);
457   return true;
458 }
459
460 void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
461   l->append(base::WideToUTF8(p));
462 }
463 #endif
464
465 void ParamTraits<std::vector<char>>::Write(base::Pickle* m,
466                                            const param_type& p) {
467   WriteCharVector(m, p);
468 }
469
470 bool ParamTraits<std::vector<char>>::Read(const base::Pickle* m,
471                                           base::PickleIterator* iter,
472                                           param_type* r) {
473   return ReadCharVector(m, iter, r);
474 }
475
476 void ParamTraits<std::vector<char>>::Log(const param_type& p, std::string* l) {
477   LogBytes(p, l);
478 }
479
480 void ParamTraits<std::vector<unsigned char>>::Write(base::Pickle* m,
481                                                     const param_type& p) {
482   WriteCharVector(m, p);
483 }
484
485 bool ParamTraits<std::vector<unsigned char>>::Read(const base::Pickle* m,
486                                                    base::PickleIterator* iter,
487                                                    param_type* r) {
488   return ReadCharVector(m, iter, r);
489 }
490
491 void ParamTraits<std::vector<unsigned char> >::Log(const param_type& p,
492                                                    std::string* l) {
493   LogBytes(p, l);
494 }
495
496 void ParamTraits<std::vector<bool>>::Write(base::Pickle* m,
497                                            const param_type& p) {
498   WriteParam(m, base::checked_cast<int>(p.size()));
499   // Cast to bool below is required because libc++'s
500   // vector<bool>::const_reference is different from bool, and we want to avoid
501   // writing an extra specialization of ParamTraits for it.
502   for (size_t i = 0; i < p.size(); i++)
503     WriteParam(m, static_cast<bool>(p[i]));
504 }
505
506 bool ParamTraits<std::vector<bool>>::Read(const base::Pickle* m,
507                                           base::PickleIterator* iter,
508                                           param_type* r) {
509   size_t size;
510   if (!iter->ReadLength(&size))
511     return false;
512   r->resize(size);
513   for (size_t i = 0; i < size; i++) {
514     bool value;
515     if (!ReadParam(m, iter, &value))
516       return false;
517     (*r)[i] = value;
518   }
519   return true;
520 }
521
522 void ParamTraits<std::vector<bool> >::Log(const param_type& p, std::string* l) {
523   for (size_t i = 0; i < p.size(); ++i) {
524     if (i != 0)
525       l->push_back(' ');
526     LogParam(static_cast<bool>(p[i]), l);
527   }
528 }
529
530 void ParamTraits<base::Value::Dict>::Write(base::Pickle* m,
531                                            const param_type& p) {
532   WriteDictValue(p, 0, m);
533 }
534
535 bool ParamTraits<base::Value::Dict>::Read(const base::Pickle* m,
536                                           base::PickleIterator* iter,
537                                           param_type* r) {
538   return ReadDictValue(m, iter, 0, r);
539 }
540
541 void ParamTraits<base::Value::Dict>::Log(const param_type& p, std::string* l) {
542   std::string json;
543   base::JSONWriter::Write(p, &json);
544   l->append(json);
545 }
546
547 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
548 void ParamTraits<base::FileDescriptor>::Write(base::Pickle* m,
549                                               const param_type& p) {
550   // This serialization must be kept in sync with
551   // nacl_message_scanner.cc:WriteHandle().
552   const bool valid = p.fd >= 0;
553   WriteParam(m, valid);
554
555   if (!valid)
556     return;
557
558   if (p.auto_close) {
559     if (!m->WriteAttachment(
560             new internal::PlatformFileAttachment(base::ScopedFD(p.fd))))
561       NOTREACHED();
562   } else {
563     if (!m->WriteAttachment(new internal::PlatformFileAttachment(p.fd)))
564       NOTREACHED();
565   }
566 }
567
568 bool ParamTraits<base::FileDescriptor>::Read(const base::Pickle* m,
569                                              base::PickleIterator* iter,
570                                              param_type* r) {
571   *r = base::FileDescriptor();
572
573   bool valid;
574   if (!ReadParam(m, iter, &valid))
575     return false;
576
577   if (!valid)
578     return true;
579
580   scoped_refptr<base::Pickle::Attachment> attachment;
581   if (!m->ReadAttachment(iter, &attachment))
582     return false;
583
584   if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
585       MessageAttachment::Type::PLATFORM_FILE) {
586     return false;
587   }
588
589   *r = base::FileDescriptor(
590       static_cast<internal::PlatformFileAttachment*>(attachment.get())
591           ->TakePlatformFile(),
592       true);
593   return true;
594 }
595
596 void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
597                                             std::string* l) {
598   if (p.auto_close) {
599     l->append(base::StringPrintf("FD(%d auto-close)", p.fd));
600   } else {
601     l->append(base::StringPrintf("FD(%d)", p.fd));
602   }
603 }
604
605 void ParamTraits<base::ScopedFD>::Write(base::Pickle* m, const param_type& p) {
606   // This serialization must be kept in sync with
607   // nacl_message_scanner.cc:WriteHandle().
608   const bool valid = p.is_valid();
609   WriteParam(m, valid);
610
611   if (!valid)
612     return;
613
614   if (!m->WriteAttachment(new internal::PlatformFileAttachment(
615           std::move(const_cast<param_type&>(p))))) {
616     NOTREACHED();
617   }
618 }
619
620 bool ParamTraits<base::ScopedFD>::Read(const base::Pickle* m,
621                                        base::PickleIterator* iter,
622                                        param_type* r) {
623   r->reset();
624
625   bool valid;
626   if (!ReadParam(m, iter, &valid))
627     return false;
628
629   if (!valid)
630     return true;
631
632   scoped_refptr<base::Pickle::Attachment> attachment;
633   if (!m->ReadAttachment(iter, &attachment))
634     return false;
635
636   if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
637       MessageAttachment::Type::PLATFORM_FILE) {
638     return false;
639   }
640
641   *r = base::ScopedFD(
642       static_cast<internal::PlatformFileAttachment*>(attachment.get())
643           ->TakePlatformFile());
644   return true;
645 }
646
647 void ParamTraits<base::ScopedFD>::Log(const param_type& p, std::string* l) {
648   l->append(base::StringPrintf("ScopedFD(%d)", p.get()));
649 }
650 #endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
651
652 #if BUILDFLAG(IS_WIN)
653 void ParamTraits<base::win::ScopedHandle>::Write(base::Pickle* m,
654                                                  const param_type& p) {
655   const bool valid = p.IsValid();
656   WriteParam(m, valid);
657   if (!valid)
658     return;
659
660   HandleWin handle(p.Get());
661   WriteParam(m, handle);
662 }
663
664 bool ParamTraits<base::win::ScopedHandle>::Read(const base::Pickle* m,
665                                                 base::PickleIterator* iter,
666                                                 param_type* r) {
667   r->Close();
668
669   bool valid;
670   if (!ReadParam(m, iter, &valid))
671     return false;
672   if (!valid)
673     return true;
674
675   HandleWin handle;
676   if (!ReadParam(m, iter, &handle))
677     return false;
678
679   r->Set(handle.get_handle());
680   return true;
681 }
682
683 void ParamTraits<base::win::ScopedHandle>::Log(const param_type& p,
684                                                std::string* l) {
685   l->append(base::StringPrintf("ScopedHandle(%p)", p.Get()));
686 }
687 #endif  // BUILDFLAG(IS_WIN)
688
689 #if BUILDFLAG(IS_FUCHSIA)
690 void ParamTraits<zx::vmo>::Write(base::Pickle* m, const param_type& p) {
691   // This serialization must be kept in sync with
692   // nacl_message_scanner.cc:WriteHandle().
693   const bool valid = p.is_valid();
694   WriteParam(m, valid);
695
696   if (!valid)
697     return;
698
699   if (!m->WriteAttachment(new internal::HandleAttachmentFuchsia(
700           std::move(const_cast<param_type&>(p))))) {
701     NOTREACHED();
702   }
703 }
704
705 bool ParamTraits<zx::vmo>::Read(const base::Pickle* m,
706                                 base::PickleIterator* iter,
707                                 param_type* r) {
708   r->reset();
709
710   bool valid;
711   if (!ReadParam(m, iter, &valid))
712     return false;
713
714   if (!valid)
715     return true;
716
717   scoped_refptr<base::Pickle::Attachment> attachment;
718   if (!m->ReadAttachment(iter, &attachment))
719     return false;
720
721   if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
722       MessageAttachment::Type::FUCHSIA_HANDLE) {
723     return false;
724   }
725
726   *r = zx::vmo(static_cast<internal::HandleAttachmentFuchsia*>(attachment.get())
727                    ->Take());
728   return true;
729 }
730
731 void ParamTraits<zx::vmo>::Log(const param_type& p, std::string* l) {
732   l->append("ZirconVMO");
733 }
734
735 void ParamTraits<zx::channel>::Write(base::Pickle* m, const param_type& p) {
736   // This serialization must be kept in sync with
737   // nacl_message_scanner.cc:WriteHandle().
738   const bool valid = p.is_valid();
739   WriteParam(m, valid);
740
741   if (!valid)
742     return;
743
744   if (!m->WriteAttachment(new internal::HandleAttachmentFuchsia(
745           std::move(const_cast<param_type&>(p))))) {
746     NOTREACHED();
747   }
748 }
749
750 bool ParamTraits<zx::channel>::Read(const base::Pickle* m,
751                                     base::PickleIterator* iter,
752                                     param_type* r) {
753   r->reset();
754
755   bool valid;
756   if (!ReadParam(m, iter, &valid))
757     return false;
758
759   if (!valid)
760     return true;
761
762   scoped_refptr<base::Pickle::Attachment> attachment;
763   if (!m->ReadAttachment(iter, &attachment))
764     return false;
765
766   if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
767       MessageAttachment::Type::FUCHSIA_HANDLE) {
768     return false;
769   }
770
771   *r = zx::channel(
772       static_cast<internal::HandleAttachmentFuchsia*>(attachment.get())
773           ->Take());
774   return true;
775 }
776
777 void ParamTraits<zx::channel>::Log(const param_type& p, std::string* l) {
778   l->append("ZirconChannel");
779 }
780 #endif  // BUILDFLAG(IS_FUCHSIA)
781
782 #if BUILDFLAG(IS_ANDROID)
783 void ParamTraits<base::android::ScopedHardwareBufferHandle>::Write(
784     base::Pickle* m,
785     const param_type& p) {
786   const bool is_valid = p.is_valid();
787   WriteParam(m, is_valid);
788   if (!is_valid)
789     return;
790
791   // We must keep a ref to the AHardwareBuffer alive until the receiver has
792   // acquired its own reference. We do this by sending a message pipe handle
793   // along with the buffer. When the receiver deserializes (or even if they
794   // die without ever reading the message) their end of the pipe will be
795   // closed. We will eventually detect this and release the AHB reference.
796   mojo::MessagePipe tracking_pipe;
797   m->WriteAttachment(new internal::MojoHandleAttachment(
798       mojo::ScopedHandle::From(std::move(tracking_pipe.handle0))));
799   WriteParam(m, base::FileDescriptor(p.SerializeAsFileDescriptor().release(),
800                                      true /* auto_close */));
801
802   // Pass ownership of the input handle to our tracking pipe to keep the AHB
803   // alive long enough to be deserialized by the receiver.
804   mojo::ScopeToMessagePipe(std::move(const_cast<param_type&>(p)),
805                            std::move(tracking_pipe.handle1));
806 }
807
808 bool ParamTraits<base::android::ScopedHardwareBufferHandle>::Read(
809     const base::Pickle* m,
810     base::PickleIterator* iter,
811     param_type* r) {
812   *r = base::android::ScopedHardwareBufferHandle();
813
814   bool is_valid;
815   if (!ReadParam(m, iter, &is_valid))
816     return false;
817   if (!is_valid)
818     return true;
819
820   scoped_refptr<base::Pickle::Attachment> tracking_pipe_attachment;
821   if (!m->ReadAttachment(iter, &tracking_pipe_attachment))
822     return false;
823
824   // We keep this alive until the AHB is safely deserialized below. When this
825   // goes out of scope, the sender holding the other end of this pipe will treat
826   // this handle closure as a signal that it's safe to release their AHB
827   // keepalive ref.
828   mojo::ScopedHandle tracking_pipe =
829       static_cast<MessageAttachment*>(tracking_pipe_attachment.get())
830           ->TakeMojoHandle();
831
832   base::FileDescriptor descriptor;
833   if (!ReadParam(m, iter, &descriptor))
834     return false;
835
836   // NOTE: It is valid to deserialize an invalid FileDescriptor, so the success
837   // of |ReadParam()| above does not imply that |descriptor| is valid.
838   base::ScopedFD scoped_fd(descriptor.fd);
839   if (!scoped_fd.is_valid())
840     return false;
841
842   *r = base::android::ScopedHardwareBufferHandle::DeserializeFromFileDescriptor(
843       std::move(scoped_fd));
844   return true;
845 }
846
847 void ParamTraits<base::android::ScopedHardwareBufferHandle>::Log(
848     const param_type& p,
849     std::string* l) {
850   l->append(base::StringPrintf("base::android::ScopedHardwareBufferHandle(%p)",
851                                p.get()));
852 }
853 #endif  // BUILDFLAG(IS_ANDROID)
854
855 void ParamTraits<base::ReadOnlySharedMemoryRegion>::Write(base::Pickle* m,
856                                                           const param_type& p) {
857   base::subtle::PlatformSharedMemoryRegion handle =
858       base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
859           std::move(const_cast<param_type&>(p)));
860   WriteParam(m, std::move(handle));
861 }
862
863 bool ParamTraits<base::ReadOnlySharedMemoryRegion>::Read(
864     const base::Pickle* m,
865     base::PickleIterator* iter,
866     param_type* r) {
867   base::subtle::PlatformSharedMemoryRegion handle;
868   if (!ReadParam(m, iter, &handle))
869     return false;
870
871   *r = base::ReadOnlySharedMemoryRegion::Deserialize(std::move(handle));
872   return true;
873 }
874
875 void ParamTraits<base::ReadOnlySharedMemoryRegion>::Log(const param_type& p,
876                                                         std::string* l) {
877   *l = "<base::ReadOnlySharedMemoryRegion>";
878   // TODO(alexilin): currently there is no way to access underlying handle
879   // without destructing a ReadOnlySharedMemoryRegion instance.
880 }
881
882 void ParamTraits<base::WritableSharedMemoryRegion>::Write(base::Pickle* m,
883                                                           const param_type& p) {
884   base::subtle::PlatformSharedMemoryRegion handle =
885       base::WritableSharedMemoryRegion::TakeHandleForSerialization(
886           std::move(const_cast<param_type&>(p)));
887   WriteParam(m, std::move(handle));
888 }
889
890 bool ParamTraits<base::WritableSharedMemoryRegion>::Read(
891     const base::Pickle* m,
892     base::PickleIterator* iter,
893     param_type* r) {
894   base::subtle::PlatformSharedMemoryRegion handle;
895   if (!ReadParam(m, iter, &handle))
896     return false;
897
898   *r = base::WritableSharedMemoryRegion::Deserialize(std::move(handle));
899   return true;
900 }
901
902 void ParamTraits<base::WritableSharedMemoryRegion>::Log(const param_type& p,
903                                                         std::string* l) {
904   *l = "<base::WritableSharedMemoryRegion>";
905   // TODO(alexilin): currently there is no way to access underlying handle
906   // without destructing a ReadOnlySharedMemoryRegion instance.
907 }
908
909 void ParamTraits<base::UnsafeSharedMemoryRegion>::Write(base::Pickle* m,
910                                                         const param_type& p) {
911   base::subtle::PlatformSharedMemoryRegion handle =
912       base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
913           std::move(const_cast<param_type&>(p)));
914   WriteParam(m, std::move(handle));
915 }
916
917 bool ParamTraits<base::UnsafeSharedMemoryRegion>::Read(
918     const base::Pickle* m,
919     base::PickleIterator* iter,
920     param_type* r) {
921   base::subtle::PlatformSharedMemoryRegion handle;
922   if (!ReadParam(m, iter, &handle))
923     return false;
924
925   *r = base::UnsafeSharedMemoryRegion::Deserialize(std::move(handle));
926   return true;
927 }
928
929 void ParamTraits<base::UnsafeSharedMemoryRegion>::Log(const param_type& p,
930                                                       std::string* l) {
931   *l = "<base::UnsafeSharedMemoryRegion>";
932   // TODO(alexilin): currently there is no way to access underlying handle
933   // without destructing a ReadOnlySharedMemoryRegion instance.
934 }
935
936 void ParamTraits<base::subtle::PlatformSharedMemoryRegion>::Write(
937     base::Pickle* m,
938     const param_type& p) {
939   // This serialization must be kept in sync with
940   // nacl_message_scanner.cc::WriteHandle().
941   const bool valid = p.IsValid();
942   WriteParam(m, valid);
943
944   if (!valid)
945     return;
946
947   WriteParam(m, p.GetMode());
948   WriteParam(m, static_cast<uint64_t>(p.GetSize()));
949   WriteParam(m, p.GetGUID());
950
951 #if BUILDFLAG(IS_WIN)
952   base::win::ScopedHandle h = const_cast<param_type&>(p).PassPlatformHandle();
953   HandleWin handle_win(h.Get());
954   WriteParam(m, handle_win);
955 #elif BUILDFLAG(IS_FUCHSIA)
956   zx::vmo vmo = const_cast<param_type&>(p).PassPlatformHandle();
957   WriteParam(m, vmo);
958 #elif BUILDFLAG(IS_APPLE)
959   base::apple::ScopedMachSendRight h =
960       const_cast<param_type&>(p).PassPlatformHandle();
961   MachPortMac mach_port_mac(h.get());
962   WriteParam(m, mach_port_mac);
963 #elif BUILDFLAG(IS_ANDROID)
964   m->WriteAttachment(new internal::PlatformFileAttachment(
965       base::ScopedFD(const_cast<param_type&>(p).PassPlatformHandle())));
966 #elif BUILDFLAG(IS_POSIX)
967   base::subtle::ScopedFDPair h =
968       const_cast<param_type&>(p).PassPlatformHandle();
969   m->WriteAttachment(new internal::PlatformFileAttachment(std::move(h.fd)));
970   if (p.GetMode() ==
971       base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
972     m->WriteAttachment(
973         new internal::PlatformFileAttachment(std::move(h.readonly_fd)));
974   }
975 #endif
976 }
977
978 bool ParamTraits<base::subtle::PlatformSharedMemoryRegion>::Read(
979     const base::Pickle* m,
980     base::PickleIterator* iter,
981     param_type* r) {
982   bool valid;
983   if (!ReadParam(m, iter, &valid))
984     return false;
985   if (!valid) {
986     *r = base::subtle::PlatformSharedMemoryRegion();
987     return true;
988   }
989
990   base::subtle::PlatformSharedMemoryRegion::Mode mode;
991   uint64_t shm_size;
992   base::UnguessableToken guid;
993   if (!ReadParam(m, iter, &mode) || !ReadParam(m, iter, &shm_size) ||
994       !base::IsValueInRangeForNumericType<size_t>(shm_size) ||
995       !ReadParam(m, iter, &guid)) {
996     return false;
997   }
998   size_t size = static_cast<size_t>(shm_size);
999
1000 #if BUILDFLAG(IS_WIN)
1001   HandleWin handle_win;
1002   if (!ReadParam(m, iter, &handle_win))
1003     return false;
1004   *r = base::subtle::PlatformSharedMemoryRegion::Take(
1005       base::win::ScopedHandle(handle_win.get_handle()), mode, size, guid);
1006 #elif BUILDFLAG(IS_FUCHSIA)
1007   zx::vmo vmo;
1008   if (!ReadParam(m, iter, &vmo))
1009     return false;
1010   *r = base::subtle::PlatformSharedMemoryRegion::Take(std::move(vmo), mode,
1011                                                       size, guid);
1012 #elif BUILDFLAG(IS_APPLE)
1013   MachPortMac mach_port_mac;
1014   if (!ReadParam(m, iter, &mach_port_mac))
1015     return false;
1016   *r = base::subtle::PlatformSharedMemoryRegion::Take(
1017       base::apple::ScopedMachSendRight(mach_port_mac.get_mach_port()), mode,
1018       size, guid);
1019 #elif BUILDFLAG(IS_POSIX)
1020   scoped_refptr<base::Pickle::Attachment> attachment;
1021   if (!m->ReadAttachment(iter, &attachment))
1022     return false;
1023   if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
1024       MessageAttachment::Type::PLATFORM_FILE) {
1025     return false;
1026   }
1027
1028 #if BUILDFLAG(IS_ANDROID)
1029   *r = base::subtle::PlatformSharedMemoryRegion::Take(
1030       base::ScopedFD(
1031           static_cast<internal::PlatformFileAttachment*>(attachment.get())
1032               ->TakePlatformFile()),
1033       mode, size, guid);
1034 #else
1035   scoped_refptr<base::Pickle::Attachment> readonly_attachment;
1036   if (mode == base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
1037     if (!m->ReadAttachment(iter, &readonly_attachment))
1038       return false;
1039
1040     if (static_cast<MessageAttachment*>(readonly_attachment.get())->GetType() !=
1041         MessageAttachment::Type::PLATFORM_FILE) {
1042       return false;
1043     }
1044   }
1045   *r = base::subtle::PlatformSharedMemoryRegion::Take(
1046       base::subtle::ScopedFDPair(
1047           base::ScopedFD(
1048               static_cast<internal::PlatformFileAttachment*>(attachment.get())
1049                   ->TakePlatformFile()),
1050           readonly_attachment
1051               ? base::ScopedFD(static_cast<internal::PlatformFileAttachment*>(
1052                                    readonly_attachment.get())
1053                                    ->TakePlatformFile())
1054               : base::ScopedFD()),
1055       mode, size, guid);
1056 #endif  // BUILDFLAG(IS_ANDROID)
1057
1058 #endif
1059
1060   return true;
1061 }
1062
1063 void ParamTraits<base::subtle::PlatformSharedMemoryRegion>::Log(
1064     const param_type& p,
1065     std::string* l) {
1066 #if BUILDFLAG(IS_FUCHSIA)
1067   l->append("Handle: ");
1068   LogParam(p.GetPlatformHandle()->get(), l);
1069 #elif BUILDFLAG(IS_WIN)
1070   l->append("Handle: ");
1071   LogParam(p.GetPlatformHandle(), l);
1072 #elif BUILDFLAG(IS_APPLE)
1073   l->append("Mach port: ");
1074   LogParam(p.GetPlatformHandle(), l);
1075 #elif BUILDFLAG(IS_ANDROID)
1076   l->append("FD: ");
1077   LogParam(p.GetPlatformHandle(), l);
1078 #elif BUILDFLAG(IS_POSIX)
1079   base::subtle::FDPair h = p.GetPlatformHandle();
1080   l->append("FD: ");
1081   LogParam(h.fd, l);
1082   l->append("Read-only FD: ");
1083   LogParam(h.readonly_fd, l);
1084 #endif
1085
1086   l->append("Mode: ");
1087   LogParam(p.GetMode(), l);
1088   l->append("size: ");
1089   LogParam(static_cast<uint64_t>(p.GetSize()), l);
1090   l->append("GUID: ");
1091   LogParam(p.GetGUID(), l);
1092 }
1093
1094 void ParamTraits<base::subtle::PlatformSharedMemoryRegion::Mode>::Write(
1095     base::Pickle* m,
1096     const param_type& value) {
1097   DCHECK(static_cast<int>(value) >= 0 &&
1098          static_cast<int>(value) <= static_cast<int>(param_type::kMaxValue));
1099   m->WriteInt(static_cast<int>(value));
1100 }
1101
1102 bool ParamTraits<base::subtle::PlatformSharedMemoryRegion::Mode>::Read(
1103     const base::Pickle* m,
1104     base::PickleIterator* iter,
1105     param_type* p) {
1106   int value;
1107   if (!iter->ReadInt(&value))
1108     return false;
1109   if (!(static_cast<int>(value) >= 0 &&
1110         static_cast<int>(value) <= static_cast<int>(param_type::kMaxValue))) {
1111     return false;
1112   }
1113   *p = static_cast<param_type>(value);
1114   return true;
1115 }
1116
1117 void ParamTraits<base::subtle::PlatformSharedMemoryRegion::Mode>::Log(
1118     const param_type& p,
1119     std::string* l) {
1120   LogParam(static_cast<int>(p), l);
1121 }
1122
1123 #if BUILDFLAG(IS_WIN)
1124 void ParamTraits<PlatformFileForTransit>::Write(base::Pickle* m,
1125                                                 const param_type& p) {
1126   m->WriteBool(p.IsValid());
1127   if (p.IsValid()) {
1128     HandleWin handle_win(p.GetHandle());
1129     ParamTraits<HandleWin>::Write(m, handle_win);
1130     ::CloseHandle(p.GetHandle());
1131   }
1132 }
1133
1134 bool ParamTraits<PlatformFileForTransit>::Read(const base::Pickle* m,
1135                                                base::PickleIterator* iter,
1136                                                param_type* r) {
1137   bool is_valid;
1138   if (!iter->ReadBool(&is_valid))
1139     return false;
1140   if (!is_valid) {
1141     *r = PlatformFileForTransit();
1142     return true;
1143   }
1144
1145   HandleWin handle_win;
1146   if (!ParamTraits<HandleWin>::Read(m, iter, &handle_win))
1147     return false;
1148   *r = PlatformFileForTransit(handle_win.get_handle());
1149   return true;
1150 }
1151
1152 void ParamTraits<PlatformFileForTransit>::Log(const param_type& p,
1153                                               std::string* l) {
1154   LogParam(p.GetHandle(), l);
1155 }
1156 #endif  // BUILDFLAG(IS_WIN)
1157
1158 void ParamTraits<base::FilePath>::Write(base::Pickle* m, const param_type& p) {
1159   p.WriteToPickle(m);
1160 }
1161
1162 bool ParamTraits<base::FilePath>::Read(const base::Pickle* m,
1163                                        base::PickleIterator* iter,
1164                                        param_type* r) {
1165   return r->ReadFromPickle(iter);
1166 }
1167
1168 void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) {
1169   ParamTraits<base::FilePath::StringType>::Log(p.value(), l);
1170 }
1171
1172 void ParamTraits<base::Value::List>::Write(base::Pickle* m,
1173                                            const param_type& p) {
1174   WriteListValue(p, 0, m);
1175 }
1176
1177 bool ParamTraits<base::Value::List>::Read(const base::Pickle* m,
1178                                           base::PickleIterator* iter,
1179                                           param_type* r) {
1180   return ReadListValue(m, iter, 0, r);
1181 }
1182
1183 void ParamTraits<base::Value::List>::Log(const param_type& p, std::string* l) {
1184   std::string json;
1185   base::JSONWriter::Write(p, &json);
1186   l->append(json);
1187 }
1188
1189 void ParamTraits<base::Value>::Write(base::Pickle* m, const param_type& p) {
1190   WriteValue(p, 0, m);
1191 }
1192
1193 bool ParamTraits<base::Value>::Read(const base::Pickle* m,
1194                                     base::PickleIterator* iter,
1195                                     param_type* r) {
1196   return ReadValue(m, iter, 0, r);
1197 }
1198
1199 void ParamTraits<base::Value>::Log(const param_type& p, std::string* l) {
1200   std::string json;
1201   base::JSONWriter::Write(p, &json);
1202   l->append(json);
1203 }
1204
1205 void ParamTraits<base::File::Info>::Write(base::Pickle* m,
1206                                           const param_type& p) {
1207   WriteParam(m, p.size);
1208   WriteParam(m, p.is_directory);
1209   WriteParam(m, p.last_modified.InSecondsFSinceUnixEpoch());
1210   WriteParam(m, p.last_accessed.InSecondsFSinceUnixEpoch());
1211   WriteParam(m, p.creation_time.InSecondsFSinceUnixEpoch());
1212 }
1213
1214 bool ParamTraits<base::File::Info>::Read(const base::Pickle* m,
1215                                          base::PickleIterator* iter,
1216                                          param_type* p) {
1217   double last_modified, last_accessed, creation_time;
1218   if (!ReadParam(m, iter, &p->size) ||
1219       !ReadParam(m, iter, &p->is_directory) ||
1220       !ReadParam(m, iter, &last_modified) ||
1221       !ReadParam(m, iter, &last_accessed) ||
1222       !ReadParam(m, iter, &creation_time))
1223     return false;
1224   p->last_modified = base::Time::FromSecondsSinceUnixEpoch(last_modified);
1225   p->last_accessed = base::Time::FromSecondsSinceUnixEpoch(last_accessed);
1226   p->creation_time = base::Time::FromSecondsSinceUnixEpoch(creation_time);
1227   return true;
1228 }
1229
1230 void ParamTraits<base::File::Info>::Log(const param_type& p,
1231                                         std::string* l) {
1232   l->append("(");
1233   LogParam(p.size, l);
1234   l->append(",");
1235   LogParam(p.is_directory, l);
1236   l->append(",");
1237   LogParam(p.last_modified.InSecondsFSinceUnixEpoch(), l);
1238   l->append(",");
1239   LogParam(p.last_accessed.InSecondsFSinceUnixEpoch(), l);
1240   l->append(",");
1241   LogParam(p.creation_time.InSecondsFSinceUnixEpoch(), l);
1242   l->append(")");
1243 }
1244
1245 void ParamTraits<base::Time>::Write(base::Pickle* m, const param_type& p) {
1246   ParamTraits<int64_t>::Write(m, p.ToInternalValue());
1247 }
1248
1249 bool ParamTraits<base::Time>::Read(const base::Pickle* m,
1250                                    base::PickleIterator* iter,
1251                                    param_type* r) {
1252   int64_t value;
1253   if (!ParamTraits<int64_t>::Read(m, iter, &value))
1254     return false;
1255   *r = base::Time::FromInternalValue(value);
1256   return true;
1257 }
1258
1259 void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
1260   ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
1261 }
1262
1263 void ParamTraits<base::TimeDelta>::Write(base::Pickle* m, const param_type& p) {
1264   ParamTraits<int64_t>::Write(m, p.ToInternalValue());
1265 }
1266
1267 bool ParamTraits<base::TimeDelta>::Read(const base::Pickle* m,
1268                                         base::PickleIterator* iter,
1269                                         param_type* r) {
1270   int64_t value;
1271   bool ret = ParamTraits<int64_t>::Read(m, iter, &value);
1272   if (ret)
1273     *r = base::TimeDelta::FromInternalValue(value);
1274
1275   return ret;
1276 }
1277
1278 void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) {
1279   ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
1280 }
1281
1282 void ParamTraits<base::TimeTicks>::Write(base::Pickle* m, const param_type& p) {
1283   ParamTraits<int64_t>::Write(m, p.ToInternalValue());
1284 }
1285
1286 bool ParamTraits<base::TimeTicks>::Read(const base::Pickle* m,
1287                                         base::PickleIterator* iter,
1288                                         param_type* r) {
1289   int64_t value;
1290   bool ret = ParamTraits<int64_t>::Read(m, iter, &value);
1291   if (ret)
1292     *r = base::TimeTicks::FromInternalValue(value);
1293
1294   return ret;
1295 }
1296
1297 void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) {
1298   ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
1299 }
1300
1301 // If base::UnguessableToken is no longer 128 bits, the IPC serialization logic
1302 // below should be updated.
1303 static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t),
1304               "base::UnguessableToken should be of size 2 * sizeof(uint64_t).");
1305
1306 void ParamTraits<base::UnguessableToken>::Write(base::Pickle* m,
1307                                                 const param_type& p) {
1308   DCHECK(!p.is_empty());
1309
1310   ParamTraits<uint64_t>::Write(m, p.GetHighForSerialization());
1311   ParamTraits<uint64_t>::Write(m, p.GetLowForSerialization());
1312 }
1313
1314 bool ParamTraits<base::UnguessableToken>::Read(const base::Pickle* m,
1315                                                base::PickleIterator* iter,
1316                                                param_type* r) {
1317   uint64_t high, low;
1318   if (!ParamTraits<uint64_t>::Read(m, iter, &high) ||
1319       !ParamTraits<uint64_t>::Read(m, iter, &low))
1320     return false;
1321
1322   // This is not mapped as nullable_is_same_type, so any UnguessableToken
1323   // deserialized by the traits should always yield a non-empty token.
1324   // If deserialization results in an empty token, the data is malformed.
1325   absl::optional<base::UnguessableToken> token =
1326       base::UnguessableToken::Deserialize(high, low);
1327   if (!token.has_value()) {
1328     return false;
1329   }
1330
1331   *r = token.value();
1332   return true;
1333 }
1334
1335 void ParamTraits<base::UnguessableToken>::Log(const param_type& p,
1336                                               std::string* l) {
1337   l->append(p.ToString());
1338 }
1339
1340 void ParamTraits<IPC::ChannelHandle>::Write(base::Pickle* m,
1341                                             const param_type& p) {
1342 #if BUILDFLAG(IS_NACL)
1343   WriteParam(m, p.socket);
1344 #else
1345   WriteParam(m, p.mojo_handle);
1346 #endif
1347 }
1348
1349 bool ParamTraits<IPC::ChannelHandle>::Read(const base::Pickle* m,
1350                                            base::PickleIterator* iter,
1351                                            param_type* r) {
1352 #if BUILDFLAG(IS_NACL)
1353   return ReadParam(m, iter, &r->socket);
1354 #else
1355   return ReadParam(m, iter, &r->mojo_handle);
1356 #endif
1357 }
1358
1359 void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
1360                                           std::string* l) {
1361   l->append("ChannelHandle(");
1362 #if BUILDFLAG(IS_NACL)
1363   ParamTraits<base::FileDescriptor>::Log(p.socket, l);
1364 #else
1365   LogParam(p.mojo_handle, l);
1366 #endif
1367   l->append(")");
1368 }
1369
1370 void ParamTraits<LogData>::Write(base::Pickle* m, const param_type& p) {
1371   WriteParam(m, p.channel);
1372   WriteParam(m, p.routing_id);
1373   WriteParam(m, p.type);
1374   WriteParam(m, p.flags);
1375   WriteParam(m, p.sent);
1376   WriteParam(m, p.receive);
1377   WriteParam(m, p.dispatch);
1378   WriteParam(m, p.message_name);
1379   WriteParam(m, p.params);
1380 }
1381
1382 bool ParamTraits<LogData>::Read(const base::Pickle* m,
1383                                 base::PickleIterator* iter,
1384                                 param_type* r) {
1385   return
1386       ReadParam(m, iter, &r->channel) &&
1387       ReadParam(m, iter, &r->routing_id) &&
1388       ReadParam(m, iter, &r->type) &&
1389       ReadParam(m, iter, &r->flags) &&
1390       ReadParam(m, iter, &r->sent) &&
1391       ReadParam(m, iter, &r->receive) &&
1392       ReadParam(m, iter, &r->dispatch) &&
1393       ReadParam(m, iter, &r->message_name) &&
1394       ReadParam(m, iter, &r->params);
1395 }
1396
1397 void ParamTraits<LogData>::Log(const param_type& p, std::string* l) {
1398   // Doesn't make sense to implement this!
1399 }
1400
1401 void ParamTraits<Message>::Write(base::Pickle* m, const Message& p) {
1402 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
1403   // We don't serialize the file descriptors in the nested message, so there
1404   // better not be any.
1405   DCHECK(!p.HasAttachments());
1406 #endif
1407
1408   // Don't just write out the message. This is used to send messages between
1409   // NaCl (Posix environment) and the browser (could be on Windows). The message
1410   // header formats differ between these systems (so does handle sharing, but
1411   // we already asserted we don't have any handles). So just write out the
1412   // parts of the header we use.
1413   //
1414   // Be careful also to use only explicitly-sized types. The NaCl environment
1415   // could be 64-bit and the host browser could be 32-bits. The nested message
1416   // may or may not be safe to send between 32-bit and 64-bit systems, but we
1417   // leave that up to the code sending the message to ensure.
1418   m->WriteUInt32(static_cast<uint32_t>(p.routing_id()));
1419   m->WriteUInt32(p.type());
1420   m->WriteUInt32(p.flags());
1421   m->WriteData(p.payload(), p.payload_size());
1422 }
1423
1424 bool ParamTraits<Message>::Read(const base::Pickle* m,
1425                                 base::PickleIterator* iter,
1426                                 Message* r) {
1427   uint32_t routing_id, type, flags;
1428   if (!iter->ReadUInt32(&routing_id) ||
1429       !iter->ReadUInt32(&type) ||
1430       !iter->ReadUInt32(&flags))
1431     return false;
1432
1433   size_t payload_size;
1434   const char* payload;
1435   if (!iter->ReadData(&payload, &payload_size))
1436     return false;
1437
1438   r->SetHeaderValues(static_cast<int32_t>(routing_id), type, flags);
1439   r->WriteBytes(payload, payload_size);
1440   return true;
1441 }
1442
1443 void ParamTraits<Message>::Log(const Message& p, std::string* l) {
1444   l->append("<IPC::Message>");
1445 }
1446
1447 #if BUILDFLAG(IS_WIN)
1448 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
1449 // bit systems. That's why we use the Windows macros to convert to 32 bits.
1450 void ParamTraits<HANDLE>::Write(base::Pickle* m, const param_type& p) {
1451   m->WriteInt(HandleToLong(p));
1452 }
1453
1454 bool ParamTraits<HANDLE>::Read(const base::Pickle* m,
1455                                base::PickleIterator* iter,
1456                                param_type* r) {
1457   int32_t temp;
1458   if (!iter->ReadInt(&temp))
1459     return false;
1460   *r = LongToHandle(temp);
1461   return true;
1462 }
1463
1464 void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) {
1465   l->append(base::StringPrintf("0x%p", p));
1466 }
1467
1468 void ParamTraits<MSG>::Write(base::Pickle* m, const param_type& p) {
1469   m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
1470 }
1471
1472 bool ParamTraits<MSG>::Read(const base::Pickle* m,
1473                             base::PickleIterator* iter,
1474                             param_type* r) {
1475   const char *data;
1476   size_t data_size = 0;
1477   bool result = iter->ReadData(&data, &data_size);
1478   if (result && data_size == sizeof(MSG)) {
1479     memcpy(r, data, sizeof(MSG));
1480   } else {
1481     result = false;
1482     NOTREACHED();
1483   }
1484
1485   return result;
1486 }
1487
1488 void ParamTraits<MSG>::Log(const param_type& p, std::string* l) {
1489   l->append("<MSG>");
1490 }
1491
1492 #endif  // BUILDFLAG(IS_WIN)
1493
1494 }  // namespace IPC