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