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