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