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