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