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.
5 #include "ipc/ipc_message_utils.h"
10 #include <type_traits>
12 #include "base/files/file_path.h"
13 #include "base/json/json_writer.h"
14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/notreached.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/time/time.h"
21 #include "base/unguessable_token.h"
22 #include "build/build_config.h"
23 #include "ipc/ipc_channel_handle.h"
24 #include "ipc/ipc_message.h"
25 #include "ipc/ipc_message_attachment.h"
26 #include "ipc/ipc_message_attachment_set.h"
27 #include "ipc/ipc_mojo_param_traits.h"
28 #include "third_party/abseil-cpp/absl/strings/ascii.h"
30 #if BUILDFLAG(IS_APPLE)
31 #include "ipc/mach_port_mac.h"
36 #include "ipc/handle_win.h"
37 #include "ipc/ipc_platform_file.h"
38 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
39 #include "base/file_descriptor_posix.h"
40 #include "ipc/ipc_platform_file_attachment_posix.h"
43 #if BUILDFLAG(IS_FUCHSIA)
44 #include "base/fuchsia/fuchsia_logging.h"
45 #include "ipc/handle_attachment_fuchsia.h"
48 #if BUILDFLAG(IS_ANDROID)
49 #include "base/android/scoped_hardware_buffer_handle.h"
50 #include "ipc/ipc_mojo_handle_attachment.h"
51 #include "mojo/public/cpp/system/message_pipe.h"
52 #include "mojo/public/cpp/system/scope_to_message_pipe.h"
59 const int kMaxRecursionDepth = 200;
61 template<typename CharType>
62 void LogBytes(const std::vector<CharType>& data, std::string* out) {
64 // Windows has a GUI for logging, which can handle arbitrary binary data.
65 for (size_t i = 0; i < data.size(); ++i)
66 out->push_back(data[i]);
67 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
68 // On POSIX, we log to stdout, which we assume can display ASCII.
69 static const size_t kMaxBytesToLog = 100;
70 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
71 if (absl::ascii_isprint(static_cast<unsigned char>(data[i]))) {
72 out->push_back(data[i]);
75 base::StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
78 if (data.size() > kMaxBytesToLog) {
79 out->append(base::StringPrintf(
81 static_cast<unsigned>(data.size() - kMaxBytesToLog)));
86 template <typename CharType>
87 void WriteCharVector(base::Pickle* m, const std::vector<CharType>& p) {
88 static_assert(sizeof(CharType) == 1);
89 static_assert(std::is_integral_v<CharType>);
91 m->WriteData(nullptr, 0);
93 const char* data = reinterpret_cast<const char*>(p.data());
94 m->WriteData(data, p.size());
98 template <typename CharType>
99 bool ReadCharVector(const base::Pickle* m,
100 base::PickleIterator* iter,
101 std::vector<CharType>* r) {
102 static_assert(sizeof(CharType) == 1);
103 static_assert(std::is_integral_v<CharType>);
105 size_t data_size = 0;
106 if (!iter->ReadData(&data, &data_size)) {
109 const CharType* begin = reinterpret_cast<const CharType*>(data);
110 const CharType* end = begin + data_size;
111 r->assign(begin, end);
115 void WriteValue(const base::Value& value, int recursion, base::Pickle* pickle);
117 void WriteDictValue(const base::Value::Dict& value,
119 base::Pickle* pickle) {
120 WriteParam(pickle, base::checked_cast<int>(value.size()));
121 for (const auto entry : value) {
122 WriteParam(pickle, entry.first);
123 WriteValue(entry.second, recursion + 1, pickle);
127 void WriteListValue(const base::Value::List& value,
129 base::Pickle* pickle) {
130 WriteParam(pickle, base::checked_cast<int>(value.size()));
131 for (const auto& entry : value) {
132 WriteValue(entry, recursion + 1, pickle);
136 void WriteValue(const base::Value& value, int recursion, base::Pickle* pickle) {
138 if (recursion > kMaxRecursionDepth) {
139 LOG(ERROR) << "Max recursion depth hit in WriteValue.";
143 pickle->WriteInt(static_cast<int>(value.type()));
145 switch (value.type()) {
146 case base::Value::Type::NONE:
148 case base::Value::Type::BOOLEAN: {
149 WriteParam(pickle, value.GetBool());
152 case base::Value::Type::INTEGER: {
153 DCHECK(value.is_int());
154 WriteParam(pickle, value.GetInt());
157 case base::Value::Type::DOUBLE: {
158 DCHECK(value.is_int() || value.is_double());
159 WriteParam(pickle, value.GetDouble());
162 case base::Value::Type::STRING: {
163 const std::string* val = value.GetIfString();
166 WriteParam(pickle, *val);
169 case base::Value::Type::BINARY: {
170 pickle->WriteData(reinterpret_cast<const char*>(value.GetBlob().data()),
171 value.GetBlob().size());
174 case base::Value::Type::DICT: {
175 DCHECK(value.is_dict());
176 WriteDictValue(value.GetDict(), recursion, pickle);
179 case base::Value::Type::LIST: {
180 DCHECK(value.is_list());
181 WriteListValue(value.GetList(), recursion, pickle);
187 bool ReadValue(const base::Pickle* pickle,
188 base::PickleIterator* iter,
192 // Helper for ReadValue that reads a Value::Dict into a pre-allocated object.
193 bool ReadDictValue(const base::Pickle* pickle,
194 base::PickleIterator* iter,
196 base::Value::Dict* value) {
198 if (!ReadParam(pickle, iter, &size))
201 for (int i = 0; i < size; i++) {
203 base::Value subvalue;
204 if (!ReadParam(pickle, iter, &key) ||
205 !ReadValue(pickle, iter, recursion + 1, &subvalue)) {
208 value->Set(key, std::move(subvalue));
214 // Helper for ReadValue that reads a Value::List into a pre-allocated object.
215 bool ReadListValue(const base::Pickle* pickle,
216 base::PickleIterator* iter,
218 base::Value::List* value) {
220 if (!ReadParam(pickle, iter, &size))
223 value->reserve(size);
224 for (int i = 0; i < size; i++) {
226 if (!ReadValue(pickle, iter, recursion + 1, &subval))
228 value->Append(std::move(subval));
233 bool ReadValue(const base::Pickle* pickle,
234 base::PickleIterator* iter,
236 base::Value* value) {
237 if (recursion > kMaxRecursionDepth) {
238 LOG(ERROR) << "Max recursion depth hit in ReadValue.";
243 if (!ReadParam(pickle, iter, &type))
246 constexpr int kMinValueType = static_cast<int>(base::Value::Type::NONE);
247 constexpr int kMaxValueType = static_cast<int>(base::Value::Type::LIST);
248 if (type > kMaxValueType || type < kMinValueType)
251 switch (static_cast<base::Value::Type>(type)) {
252 case base::Value::Type::NONE:
253 *value = base::Value();
255 case base::Value::Type::BOOLEAN: {
257 if (!ReadParam(pickle, iter, &val))
259 *value = base::Value(val);
262 case base::Value::Type::INTEGER: {
264 if (!ReadParam(pickle, iter, &val))
266 *value = base::Value(val);
269 case base::Value::Type::DOUBLE: {
271 if (!ReadParam(pickle, iter, &val))
273 *value = base::Value(val);
276 case base::Value::Type::STRING: {
278 if (!ReadParam(pickle, iter, &val))
280 *value = base::Value(std::move(val));
283 case base::Value::Type::BINARY: {
284 absl::optional<base::span<const uint8_t>> data = iter->ReadData();
288 *value = base::Value(*data);
291 case base::Value::Type::DICT: {
292 base::Value::Dict val;
293 if (!ReadDictValue(pickle, iter, recursion, &val))
295 *value = base::Value(std::move(val));
298 case base::Value::Type::LIST: {
299 base::Value::List val;
300 if (!ReadListValue(pickle, iter, recursion, &val))
302 *value = base::Value(std::move(val));
315 // -----------------------------------------------------------------------------
325 LogData::LogData(const LogData& other) = default;
327 LogData::~LogData() = default;
329 void ParamTraits<bool>::Log(const param_type& p, std::string* l) {
330 l->append(p ? "true" : "false");
333 void ParamTraits<signed char>::Write(base::Pickle* m, const param_type& p) {
334 m->WriteBytes(&p, sizeof(param_type));
337 bool ParamTraits<signed char>::Read(const base::Pickle* m,
338 base::PickleIterator* iter,
341 if (!iter->ReadBytes(&data, sizeof(param_type)))
343 memcpy(r, data, sizeof(param_type));
347 void ParamTraits<signed char>::Log(const param_type& p, std::string* l) {
348 l->append(base::NumberToString(p));
351 void ParamTraits<unsigned char>::Write(base::Pickle* m, const param_type& p) {
352 m->WriteBytes(&p, sizeof(param_type));
355 bool ParamTraits<unsigned char>::Read(const base::Pickle* m,
356 base::PickleIterator* iter,
359 if (!iter->ReadBytes(&data, sizeof(param_type)))
361 memcpy(r, data, sizeof(param_type));
365 void ParamTraits<unsigned char>::Log(const param_type& p, std::string* l) {
366 l->append(base::NumberToString(p));
369 void ParamTraits<unsigned short>::Write(base::Pickle* m, const param_type& p) {
370 m->WriteBytes(&p, sizeof(param_type));
373 bool ParamTraits<unsigned short>::Read(const base::Pickle* m,
374 base::PickleIterator* iter,
377 if (!iter->ReadBytes(&data, sizeof(param_type)))
379 memcpy(r, data, sizeof(param_type));
383 void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
384 l->append(base::NumberToString(p));
387 void ParamTraits<int>::Log(const param_type& p, std::string* l) {
388 l->append(base::NumberToString(p));
391 void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
392 l->append(base::NumberToString(p));
395 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
396 BUILDFLAG(IS_FUCHSIA) || \
397 (BUILDFLAG(IS_ANDROID) && defined(ARCH_CPU_64_BITS))
398 void ParamTraits<long>::Log(const param_type& p, std::string* l) {
399 l->append(base::NumberToString(p));
402 void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
403 l->append(base::NumberToString(p));
407 void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
408 l->append(base::NumberToString(p));
411 void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
412 l->append(base::NumberToString(p));
415 void ParamTraits<float>::Log(const param_type& p, std::string* l) {
416 l->append(base::StringPrintf("%e", p));
419 void ParamTraits<double>::Write(base::Pickle* m, const param_type& p) {
420 m->WriteBytes(reinterpret_cast<const char*>(&p), sizeof(param_type));
423 bool ParamTraits<double>::Read(const base::Pickle* m,
424 base::PickleIterator* iter,
427 if (!iter->ReadBytes(&data, sizeof(*r))) {
431 memcpy(r, data, sizeof(param_type));
435 void ParamTraits<double>::Log(const param_type& p, std::string* l) {
436 l->append(base::StringPrintf("%e", p));
440 void ParamTraits<std::string>::Log(const param_type& p, std::string* l) {
444 void ParamTraits<std::u16string>::Log(const param_type& p, std::string* l) {
445 l->append(base::UTF16ToUTF8(p));
448 #if BUILDFLAG(IS_WIN)
449 bool ParamTraits<std::wstring>::Read(const base::Pickle* m,
450 base::PickleIterator* iter,
452 base::StringPiece16 piece16;
453 if (!iter->ReadStringPiece16(&piece16))
456 *r = base::AsWString(piece16);
460 void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
461 l->append(base::WideToUTF8(p));
465 void ParamTraits<std::vector<char>>::Write(base::Pickle* m,
466 const param_type& p) {
467 WriteCharVector(m, p);
470 bool ParamTraits<std::vector<char>>::Read(const base::Pickle* m,
471 base::PickleIterator* iter,
473 return ReadCharVector(m, iter, r);
476 void ParamTraits<std::vector<char>>::Log(const param_type& p, std::string* l) {
480 void ParamTraits<std::vector<unsigned char>>::Write(base::Pickle* m,
481 const param_type& p) {
482 WriteCharVector(m, p);
485 bool ParamTraits<std::vector<unsigned char>>::Read(const base::Pickle* m,
486 base::PickleIterator* iter,
488 return ReadCharVector(m, iter, r);
491 void ParamTraits<std::vector<unsigned char> >::Log(const param_type& p,
496 void ParamTraits<std::vector<bool>>::Write(base::Pickle* m,
497 const param_type& p) {
498 WriteParam(m, base::checked_cast<int>(p.size()));
499 // Cast to bool below is required because libc++'s
500 // vector<bool>::const_reference is different from bool, and we want to avoid
501 // writing an extra specialization of ParamTraits for it.
502 for (size_t i = 0; i < p.size(); i++)
503 WriteParam(m, static_cast<bool>(p[i]));
506 bool ParamTraits<std::vector<bool>>::Read(const base::Pickle* m,
507 base::PickleIterator* iter,
510 if (!iter->ReadLength(&size))
513 for (size_t i = 0; i < size; i++) {
515 if (!ReadParam(m, iter, &value))
522 void ParamTraits<std::vector<bool> >::Log(const param_type& p, std::string* l) {
523 for (size_t i = 0; i < p.size(); ++i) {
526 LogParam(static_cast<bool>(p[i]), l);
530 void ParamTraits<base::Value::Dict>::Write(base::Pickle* m,
531 const param_type& p) {
532 WriteDictValue(p, 0, m);
535 bool ParamTraits<base::Value::Dict>::Read(const base::Pickle* m,
536 base::PickleIterator* iter,
538 return ReadDictValue(m, iter, 0, r);
541 void ParamTraits<base::Value::Dict>::Log(const param_type& p, std::string* l) {
543 base::JSONWriter::Write(p, &json);
547 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
548 void ParamTraits<base::FileDescriptor>::Write(base::Pickle* m,
549 const param_type& p) {
550 // This serialization must be kept in sync with
551 // nacl_message_scanner.cc:WriteHandle().
552 const bool valid = p.fd >= 0;
553 WriteParam(m, valid);
559 if (!m->WriteAttachment(
560 new internal::PlatformFileAttachment(base::ScopedFD(p.fd))))
563 if (!m->WriteAttachment(new internal::PlatformFileAttachment(p.fd)))
568 bool ParamTraits<base::FileDescriptor>::Read(const base::Pickle* m,
569 base::PickleIterator* iter,
571 *r = base::FileDescriptor();
574 if (!ReadParam(m, iter, &valid))
580 scoped_refptr<base::Pickle::Attachment> attachment;
581 if (!m->ReadAttachment(iter, &attachment))
584 if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
585 MessageAttachment::Type::PLATFORM_FILE) {
589 *r = base::FileDescriptor(
590 static_cast<internal::PlatformFileAttachment*>(attachment.get())
591 ->TakePlatformFile(),
596 void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
599 l->append(base::StringPrintf("FD(%d auto-close)", p.fd));
601 l->append(base::StringPrintf("FD(%d)", p.fd));
605 void ParamTraits<base::ScopedFD>::Write(base::Pickle* m, const param_type& p) {
606 // This serialization must be kept in sync with
607 // nacl_message_scanner.cc:WriteHandle().
608 const bool valid = p.is_valid();
609 WriteParam(m, valid);
614 if (!m->WriteAttachment(new internal::PlatformFileAttachment(
615 std::move(const_cast<param_type&>(p))))) {
620 bool ParamTraits<base::ScopedFD>::Read(const base::Pickle* m,
621 base::PickleIterator* iter,
626 if (!ReadParam(m, iter, &valid))
632 scoped_refptr<base::Pickle::Attachment> attachment;
633 if (!m->ReadAttachment(iter, &attachment))
636 if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
637 MessageAttachment::Type::PLATFORM_FILE) {
642 static_cast<internal::PlatformFileAttachment*>(attachment.get())
643 ->TakePlatformFile());
647 void ParamTraits<base::ScopedFD>::Log(const param_type& p, std::string* l) {
648 l->append(base::StringPrintf("ScopedFD(%d)", p.get()));
650 #endif // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
652 #if BUILDFLAG(IS_WIN)
653 void ParamTraits<base::win::ScopedHandle>::Write(base::Pickle* m,
654 const param_type& p) {
655 const bool valid = p.IsValid();
656 WriteParam(m, valid);
660 HandleWin handle(p.Get());
661 WriteParam(m, handle);
664 bool ParamTraits<base::win::ScopedHandle>::Read(const base::Pickle* m,
665 base::PickleIterator* iter,
670 if (!ReadParam(m, iter, &valid))
676 if (!ReadParam(m, iter, &handle))
679 r->Set(handle.get_handle());
683 void ParamTraits<base::win::ScopedHandle>::Log(const param_type& p,
685 l->append(base::StringPrintf("ScopedHandle(%p)", p.Get()));
687 #endif // BUILDFLAG(IS_WIN)
689 #if BUILDFLAG(IS_FUCHSIA)
690 void ParamTraits<zx::vmo>::Write(base::Pickle* m, const param_type& p) {
691 // This serialization must be kept in sync with
692 // nacl_message_scanner.cc:WriteHandle().
693 const bool valid = p.is_valid();
694 WriteParam(m, valid);
699 if (!m->WriteAttachment(new internal::HandleAttachmentFuchsia(
700 std::move(const_cast<param_type&>(p))))) {
705 bool ParamTraits<zx::vmo>::Read(const base::Pickle* m,
706 base::PickleIterator* iter,
711 if (!ReadParam(m, iter, &valid))
717 scoped_refptr<base::Pickle::Attachment> attachment;
718 if (!m->ReadAttachment(iter, &attachment))
721 if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
722 MessageAttachment::Type::FUCHSIA_HANDLE) {
726 *r = zx::vmo(static_cast<internal::HandleAttachmentFuchsia*>(attachment.get())
731 void ParamTraits<zx::vmo>::Log(const param_type& p, std::string* l) {
732 l->append("ZirconVMO");
735 void ParamTraits<zx::channel>::Write(base::Pickle* m, const param_type& p) {
736 // This serialization must be kept in sync with
737 // nacl_message_scanner.cc:WriteHandle().
738 const bool valid = p.is_valid();
739 WriteParam(m, valid);
744 if (!m->WriteAttachment(new internal::HandleAttachmentFuchsia(
745 std::move(const_cast<param_type&>(p))))) {
750 bool ParamTraits<zx::channel>::Read(const base::Pickle* m,
751 base::PickleIterator* iter,
756 if (!ReadParam(m, iter, &valid))
762 scoped_refptr<base::Pickle::Attachment> attachment;
763 if (!m->ReadAttachment(iter, &attachment))
766 if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
767 MessageAttachment::Type::FUCHSIA_HANDLE) {
772 static_cast<internal::HandleAttachmentFuchsia*>(attachment.get())
777 void ParamTraits<zx::channel>::Log(const param_type& p, std::string* l) {
778 l->append("ZirconChannel");
780 #endif // BUILDFLAG(IS_FUCHSIA)
782 #if BUILDFLAG(IS_ANDROID)
783 void ParamTraits<base::android::ScopedHardwareBufferHandle>::Write(
785 const param_type& p) {
786 const bool is_valid = p.is_valid();
787 WriteParam(m, is_valid);
791 // We must keep a ref to the AHardwareBuffer alive until the receiver has
792 // acquired its own reference. We do this by sending a message pipe handle
793 // along with the buffer. When the receiver deserializes (or even if they
794 // die without ever reading the message) their end of the pipe will be
795 // closed. We will eventually detect this and release the AHB reference.
796 mojo::MessagePipe tracking_pipe;
797 m->WriteAttachment(new internal::MojoHandleAttachment(
798 mojo::ScopedHandle::From(std::move(tracking_pipe.handle0))));
799 WriteParam(m, base::FileDescriptor(p.SerializeAsFileDescriptor().release(),
800 true /* auto_close */));
802 // Pass ownership of the input handle to our tracking pipe to keep the AHB
803 // alive long enough to be deserialized by the receiver.
804 mojo::ScopeToMessagePipe(std::move(const_cast<param_type&>(p)),
805 std::move(tracking_pipe.handle1));
808 bool ParamTraits<base::android::ScopedHardwareBufferHandle>::Read(
809 const base::Pickle* m,
810 base::PickleIterator* iter,
812 *r = base::android::ScopedHardwareBufferHandle();
815 if (!ReadParam(m, iter, &is_valid))
820 scoped_refptr<base::Pickle::Attachment> tracking_pipe_attachment;
821 if (!m->ReadAttachment(iter, &tracking_pipe_attachment))
824 // We keep this alive until the AHB is safely deserialized below. When this
825 // goes out of scope, the sender holding the other end of this pipe will treat
826 // this handle closure as a signal that it's safe to release their AHB
828 mojo::ScopedHandle tracking_pipe =
829 static_cast<MessageAttachment*>(tracking_pipe_attachment.get())
832 base::FileDescriptor descriptor;
833 if (!ReadParam(m, iter, &descriptor))
836 // NOTE: It is valid to deserialize an invalid FileDescriptor, so the success
837 // of |ReadParam()| above does not imply that |descriptor| is valid.
838 base::ScopedFD scoped_fd(descriptor.fd);
839 if (!scoped_fd.is_valid())
842 *r = base::android::ScopedHardwareBufferHandle::DeserializeFromFileDescriptor(
843 std::move(scoped_fd));
847 void ParamTraits<base::android::ScopedHardwareBufferHandle>::Log(
850 l->append(base::StringPrintf("base::android::ScopedHardwareBufferHandle(%p)",
853 #endif // BUILDFLAG(IS_ANDROID)
855 void ParamTraits<base::ReadOnlySharedMemoryRegion>::Write(base::Pickle* m,
856 const param_type& p) {
857 base::subtle::PlatformSharedMemoryRegion handle =
858 base::ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
859 std::move(const_cast<param_type&>(p)));
860 WriteParam(m, std::move(handle));
863 bool ParamTraits<base::ReadOnlySharedMemoryRegion>::Read(
864 const base::Pickle* m,
865 base::PickleIterator* iter,
867 base::subtle::PlatformSharedMemoryRegion handle;
868 if (!ReadParam(m, iter, &handle))
871 *r = base::ReadOnlySharedMemoryRegion::Deserialize(std::move(handle));
875 void ParamTraits<base::ReadOnlySharedMemoryRegion>::Log(const param_type& p,
877 *l = "<base::ReadOnlySharedMemoryRegion>";
878 // TODO(alexilin): currently there is no way to access underlying handle
879 // without destructing a ReadOnlySharedMemoryRegion instance.
882 void ParamTraits<base::WritableSharedMemoryRegion>::Write(base::Pickle* m,
883 const param_type& p) {
884 base::subtle::PlatformSharedMemoryRegion handle =
885 base::WritableSharedMemoryRegion::TakeHandleForSerialization(
886 std::move(const_cast<param_type&>(p)));
887 WriteParam(m, std::move(handle));
890 bool ParamTraits<base::WritableSharedMemoryRegion>::Read(
891 const base::Pickle* m,
892 base::PickleIterator* iter,
894 base::subtle::PlatformSharedMemoryRegion handle;
895 if (!ReadParam(m, iter, &handle))
898 *r = base::WritableSharedMemoryRegion::Deserialize(std::move(handle));
902 void ParamTraits<base::WritableSharedMemoryRegion>::Log(const param_type& p,
904 *l = "<base::WritableSharedMemoryRegion>";
905 // TODO(alexilin): currently there is no way to access underlying handle
906 // without destructing a ReadOnlySharedMemoryRegion instance.
909 void ParamTraits<base::UnsafeSharedMemoryRegion>::Write(base::Pickle* m,
910 const param_type& p) {
911 base::subtle::PlatformSharedMemoryRegion handle =
912 base::UnsafeSharedMemoryRegion::TakeHandleForSerialization(
913 std::move(const_cast<param_type&>(p)));
914 WriteParam(m, std::move(handle));
917 bool ParamTraits<base::UnsafeSharedMemoryRegion>::Read(
918 const base::Pickle* m,
919 base::PickleIterator* iter,
921 base::subtle::PlatformSharedMemoryRegion handle;
922 if (!ReadParam(m, iter, &handle))
925 *r = base::UnsafeSharedMemoryRegion::Deserialize(std::move(handle));
929 void ParamTraits<base::UnsafeSharedMemoryRegion>::Log(const param_type& p,
931 *l = "<base::UnsafeSharedMemoryRegion>";
932 // TODO(alexilin): currently there is no way to access underlying handle
933 // without destructing a ReadOnlySharedMemoryRegion instance.
936 void ParamTraits<base::subtle::PlatformSharedMemoryRegion>::Write(
938 const param_type& p) {
939 // This serialization must be kept in sync with
940 // nacl_message_scanner.cc::WriteHandle().
941 const bool valid = p.IsValid();
942 WriteParam(m, valid);
947 WriteParam(m, p.GetMode());
948 WriteParam(m, static_cast<uint64_t>(p.GetSize()));
949 WriteParam(m, p.GetGUID());
951 #if BUILDFLAG(IS_WIN)
952 base::win::ScopedHandle h = const_cast<param_type&>(p).PassPlatformHandle();
953 HandleWin handle_win(h.Get());
954 WriteParam(m, handle_win);
955 #elif BUILDFLAG(IS_FUCHSIA)
956 zx::vmo vmo = const_cast<param_type&>(p).PassPlatformHandle();
958 #elif BUILDFLAG(IS_APPLE)
959 base::apple::ScopedMachSendRight h =
960 const_cast<param_type&>(p).PassPlatformHandle();
961 MachPortMac mach_port_mac(h.get());
962 WriteParam(m, mach_port_mac);
963 #elif BUILDFLAG(IS_ANDROID)
964 m->WriteAttachment(new internal::PlatformFileAttachment(
965 base::ScopedFD(const_cast<param_type&>(p).PassPlatformHandle())));
966 #elif BUILDFLAG(IS_POSIX)
967 base::subtle::ScopedFDPair h =
968 const_cast<param_type&>(p).PassPlatformHandle();
969 m->WriteAttachment(new internal::PlatformFileAttachment(std::move(h.fd)));
971 base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
973 new internal::PlatformFileAttachment(std::move(h.readonly_fd)));
978 bool ParamTraits<base::subtle::PlatformSharedMemoryRegion>::Read(
979 const base::Pickle* m,
980 base::PickleIterator* iter,
983 if (!ReadParam(m, iter, &valid))
986 *r = base::subtle::PlatformSharedMemoryRegion();
990 base::subtle::PlatformSharedMemoryRegion::Mode mode;
992 base::UnguessableToken guid;
993 if (!ReadParam(m, iter, &mode) || !ReadParam(m, iter, &shm_size) ||
994 !base::IsValueInRangeForNumericType<size_t>(shm_size) ||
995 !ReadParam(m, iter, &guid)) {
998 size_t size = static_cast<size_t>(shm_size);
1000 #if BUILDFLAG(IS_WIN)
1001 HandleWin handle_win;
1002 if (!ReadParam(m, iter, &handle_win))
1004 *r = base::subtle::PlatformSharedMemoryRegion::Take(
1005 base::win::ScopedHandle(handle_win.get_handle()), mode, size, guid);
1006 #elif BUILDFLAG(IS_FUCHSIA)
1008 if (!ReadParam(m, iter, &vmo))
1010 *r = base::subtle::PlatformSharedMemoryRegion::Take(std::move(vmo), mode,
1012 #elif BUILDFLAG(IS_APPLE)
1013 MachPortMac mach_port_mac;
1014 if (!ReadParam(m, iter, &mach_port_mac))
1016 *r = base::subtle::PlatformSharedMemoryRegion::Take(
1017 base::apple::ScopedMachSendRight(mach_port_mac.get_mach_port()), mode,
1019 #elif BUILDFLAG(IS_POSIX)
1020 scoped_refptr<base::Pickle::Attachment> attachment;
1021 if (!m->ReadAttachment(iter, &attachment))
1023 if (static_cast<MessageAttachment*>(attachment.get())->GetType() !=
1024 MessageAttachment::Type::PLATFORM_FILE) {
1028 #if BUILDFLAG(IS_ANDROID)
1029 *r = base::subtle::PlatformSharedMemoryRegion::Take(
1031 static_cast<internal::PlatformFileAttachment*>(attachment.get())
1032 ->TakePlatformFile()),
1035 scoped_refptr<base::Pickle::Attachment> readonly_attachment;
1036 if (mode == base::subtle::PlatformSharedMemoryRegion::Mode::kWritable) {
1037 if (!m->ReadAttachment(iter, &readonly_attachment))
1040 if (static_cast<MessageAttachment*>(readonly_attachment.get())->GetType() !=
1041 MessageAttachment::Type::PLATFORM_FILE) {
1045 *r = base::subtle::PlatformSharedMemoryRegion::Take(
1046 base::subtle::ScopedFDPair(
1048 static_cast<internal::PlatformFileAttachment*>(attachment.get())
1049 ->TakePlatformFile()),
1051 ? base::ScopedFD(static_cast<internal::PlatformFileAttachment*>(
1052 readonly_attachment.get())
1053 ->TakePlatformFile())
1054 : base::ScopedFD()),
1056 #endif // BUILDFLAG(IS_ANDROID)
1063 void ParamTraits<base::subtle::PlatformSharedMemoryRegion>::Log(
1064 const param_type& p,
1066 #if BUILDFLAG(IS_FUCHSIA)
1067 l->append("Handle: ");
1068 LogParam(p.GetPlatformHandle()->get(), l);
1069 #elif BUILDFLAG(IS_WIN)
1070 l->append("Handle: ");
1071 LogParam(p.GetPlatformHandle(), l);
1072 #elif BUILDFLAG(IS_APPLE)
1073 l->append("Mach port: ");
1074 LogParam(p.GetPlatformHandle(), l);
1075 #elif BUILDFLAG(IS_ANDROID)
1077 LogParam(p.GetPlatformHandle(), l);
1078 #elif BUILDFLAG(IS_POSIX)
1079 base::subtle::FDPair h = p.GetPlatformHandle();
1082 l->append("Read-only FD: ");
1083 LogParam(h.readonly_fd, l);
1086 l->append("Mode: ");
1087 LogParam(p.GetMode(), l);
1088 l->append("size: ");
1089 LogParam(static_cast<uint64_t>(p.GetSize()), l);
1090 l->append("GUID: ");
1091 LogParam(p.GetGUID(), l);
1094 void ParamTraits<base::subtle::PlatformSharedMemoryRegion::Mode>::Write(
1096 const param_type& value) {
1097 DCHECK(static_cast<int>(value) >= 0 &&
1098 static_cast<int>(value) <= static_cast<int>(param_type::kMaxValue));
1099 m->WriteInt(static_cast<int>(value));
1102 bool ParamTraits<base::subtle::PlatformSharedMemoryRegion::Mode>::Read(
1103 const base::Pickle* m,
1104 base::PickleIterator* iter,
1107 if (!iter->ReadInt(&value))
1109 if (!(static_cast<int>(value) >= 0 &&
1110 static_cast<int>(value) <= static_cast<int>(param_type::kMaxValue))) {
1113 *p = static_cast<param_type>(value);
1117 void ParamTraits<base::subtle::PlatformSharedMemoryRegion::Mode>::Log(
1118 const param_type& p,
1120 LogParam(static_cast<int>(p), l);
1123 #if BUILDFLAG(IS_WIN)
1124 void ParamTraits<PlatformFileForTransit>::Write(base::Pickle* m,
1125 const param_type& p) {
1126 m->WriteBool(p.IsValid());
1128 HandleWin handle_win(p.GetHandle());
1129 ParamTraits<HandleWin>::Write(m, handle_win);
1130 ::CloseHandle(p.GetHandle());
1134 bool ParamTraits<PlatformFileForTransit>::Read(const base::Pickle* m,
1135 base::PickleIterator* iter,
1138 if (!iter->ReadBool(&is_valid))
1141 *r = PlatformFileForTransit();
1145 HandleWin handle_win;
1146 if (!ParamTraits<HandleWin>::Read(m, iter, &handle_win))
1148 *r = PlatformFileForTransit(handle_win.get_handle());
1152 void ParamTraits<PlatformFileForTransit>::Log(const param_type& p,
1154 LogParam(p.GetHandle(), l);
1156 #endif // BUILDFLAG(IS_WIN)
1158 void ParamTraits<base::FilePath>::Write(base::Pickle* m, const param_type& p) {
1162 bool ParamTraits<base::FilePath>::Read(const base::Pickle* m,
1163 base::PickleIterator* iter,
1165 return r->ReadFromPickle(iter);
1168 void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) {
1169 ParamTraits<base::FilePath::StringType>::Log(p.value(), l);
1172 void ParamTraits<base::Value::List>::Write(base::Pickle* m,
1173 const param_type& p) {
1174 WriteListValue(p, 0, m);
1177 bool ParamTraits<base::Value::List>::Read(const base::Pickle* m,
1178 base::PickleIterator* iter,
1180 return ReadListValue(m, iter, 0, r);
1183 void ParamTraits<base::Value::List>::Log(const param_type& p, std::string* l) {
1185 base::JSONWriter::Write(p, &json);
1189 void ParamTraits<base::Value>::Write(base::Pickle* m, const param_type& p) {
1190 WriteValue(p, 0, m);
1193 bool ParamTraits<base::Value>::Read(const base::Pickle* m,
1194 base::PickleIterator* iter,
1196 return ReadValue(m, iter, 0, r);
1199 void ParamTraits<base::Value>::Log(const param_type& p, std::string* l) {
1201 base::JSONWriter::Write(p, &json);
1205 void ParamTraits<base::File::Info>::Write(base::Pickle* m,
1206 const param_type& p) {
1207 WriteParam(m, p.size);
1208 WriteParam(m, p.is_directory);
1209 WriteParam(m, p.last_modified.InSecondsFSinceUnixEpoch());
1210 WriteParam(m, p.last_accessed.InSecondsFSinceUnixEpoch());
1211 WriteParam(m, p.creation_time.InSecondsFSinceUnixEpoch());
1214 bool ParamTraits<base::File::Info>::Read(const base::Pickle* m,
1215 base::PickleIterator* iter,
1217 double last_modified, last_accessed, creation_time;
1218 if (!ReadParam(m, iter, &p->size) ||
1219 !ReadParam(m, iter, &p->is_directory) ||
1220 !ReadParam(m, iter, &last_modified) ||
1221 !ReadParam(m, iter, &last_accessed) ||
1222 !ReadParam(m, iter, &creation_time))
1224 p->last_modified = base::Time::FromSecondsSinceUnixEpoch(last_modified);
1225 p->last_accessed = base::Time::FromSecondsSinceUnixEpoch(last_accessed);
1226 p->creation_time = base::Time::FromSecondsSinceUnixEpoch(creation_time);
1230 void ParamTraits<base::File::Info>::Log(const param_type& p,
1233 LogParam(p.size, l);
1235 LogParam(p.is_directory, l);
1237 LogParam(p.last_modified.InSecondsFSinceUnixEpoch(), l);
1239 LogParam(p.last_accessed.InSecondsFSinceUnixEpoch(), l);
1241 LogParam(p.creation_time.InSecondsFSinceUnixEpoch(), l);
1245 void ParamTraits<base::Time>::Write(base::Pickle* m, const param_type& p) {
1246 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
1249 bool ParamTraits<base::Time>::Read(const base::Pickle* m,
1250 base::PickleIterator* iter,
1253 if (!ParamTraits<int64_t>::Read(m, iter, &value))
1255 *r = base::Time::FromInternalValue(value);
1259 void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
1260 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
1263 void ParamTraits<base::TimeDelta>::Write(base::Pickle* m, const param_type& p) {
1264 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
1267 bool ParamTraits<base::TimeDelta>::Read(const base::Pickle* m,
1268 base::PickleIterator* iter,
1271 bool ret = ParamTraits<int64_t>::Read(m, iter, &value);
1273 *r = base::TimeDelta::FromInternalValue(value);
1278 void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) {
1279 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
1282 void ParamTraits<base::TimeTicks>::Write(base::Pickle* m, const param_type& p) {
1283 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
1286 bool ParamTraits<base::TimeTicks>::Read(const base::Pickle* m,
1287 base::PickleIterator* iter,
1290 bool ret = ParamTraits<int64_t>::Read(m, iter, &value);
1292 *r = base::TimeTicks::FromInternalValue(value);
1297 void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) {
1298 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
1301 // If base::UnguessableToken is no longer 128 bits, the IPC serialization logic
1302 // below should be updated.
1303 static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t),
1304 "base::UnguessableToken should be of size 2 * sizeof(uint64_t).");
1306 void ParamTraits<base::UnguessableToken>::Write(base::Pickle* m,
1307 const param_type& p) {
1308 DCHECK(!p.is_empty());
1310 ParamTraits<uint64_t>::Write(m, p.GetHighForSerialization());
1311 ParamTraits<uint64_t>::Write(m, p.GetLowForSerialization());
1314 bool ParamTraits<base::UnguessableToken>::Read(const base::Pickle* m,
1315 base::PickleIterator* iter,
1318 if (!ParamTraits<uint64_t>::Read(m, iter, &high) ||
1319 !ParamTraits<uint64_t>::Read(m, iter, &low))
1322 // This is not mapped as nullable_is_same_type, so any UnguessableToken
1323 // deserialized by the traits should always yield a non-empty token.
1324 // If deserialization results in an empty token, the data is malformed.
1325 absl::optional<base::UnguessableToken> token =
1326 base::UnguessableToken::Deserialize(high, low);
1327 if (!token.has_value()) {
1335 void ParamTraits<base::UnguessableToken>::Log(const param_type& p,
1337 l->append(p.ToString());
1340 void ParamTraits<IPC::ChannelHandle>::Write(base::Pickle* m,
1341 const param_type& p) {
1342 #if BUILDFLAG(IS_NACL)
1343 WriteParam(m, p.socket);
1345 WriteParam(m, p.mojo_handle);
1349 bool ParamTraits<IPC::ChannelHandle>::Read(const base::Pickle* m,
1350 base::PickleIterator* iter,
1352 #if BUILDFLAG(IS_NACL)
1353 return ReadParam(m, iter, &r->socket);
1355 return ReadParam(m, iter, &r->mojo_handle);
1359 void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
1361 l->append("ChannelHandle(");
1362 #if BUILDFLAG(IS_NACL)
1363 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
1365 LogParam(p.mojo_handle, l);
1370 void ParamTraits<LogData>::Write(base::Pickle* m, const param_type& p) {
1371 WriteParam(m, p.channel);
1372 WriteParam(m, p.routing_id);
1373 WriteParam(m, p.type);
1374 WriteParam(m, p.flags);
1375 WriteParam(m, p.sent);
1376 WriteParam(m, p.receive);
1377 WriteParam(m, p.dispatch);
1378 WriteParam(m, p.message_name);
1379 WriteParam(m, p.params);
1382 bool ParamTraits<LogData>::Read(const base::Pickle* m,
1383 base::PickleIterator* iter,
1386 ReadParam(m, iter, &r->channel) &&
1387 ReadParam(m, iter, &r->routing_id) &&
1388 ReadParam(m, iter, &r->type) &&
1389 ReadParam(m, iter, &r->flags) &&
1390 ReadParam(m, iter, &r->sent) &&
1391 ReadParam(m, iter, &r->receive) &&
1392 ReadParam(m, iter, &r->dispatch) &&
1393 ReadParam(m, iter, &r->message_name) &&
1394 ReadParam(m, iter, &r->params);
1397 void ParamTraits<LogData>::Log(const param_type& p, std::string* l) {
1398 // Doesn't make sense to implement this!
1401 void ParamTraits<Message>::Write(base::Pickle* m, const Message& p) {
1402 #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
1403 // We don't serialize the file descriptors in the nested message, so there
1404 // better not be any.
1405 DCHECK(!p.HasAttachments());
1408 // Don't just write out the message. This is used to send messages between
1409 // NaCl (Posix environment) and the browser (could be on Windows). The message
1410 // header formats differ between these systems (so does handle sharing, but
1411 // we already asserted we don't have any handles). So just write out the
1412 // parts of the header we use.
1414 // Be careful also to use only explicitly-sized types. The NaCl environment
1415 // could be 64-bit and the host browser could be 32-bits. The nested message
1416 // may or may not be safe to send between 32-bit and 64-bit systems, but we
1417 // leave that up to the code sending the message to ensure.
1418 m->WriteUInt32(static_cast<uint32_t>(p.routing_id()));
1419 m->WriteUInt32(p.type());
1420 m->WriteUInt32(p.flags());
1421 m->WriteData(p.payload(), p.payload_size());
1424 bool ParamTraits<Message>::Read(const base::Pickle* m,
1425 base::PickleIterator* iter,
1427 uint32_t routing_id, type, flags;
1428 if (!iter->ReadUInt32(&routing_id) ||
1429 !iter->ReadUInt32(&type) ||
1430 !iter->ReadUInt32(&flags))
1433 size_t payload_size;
1434 const char* payload;
1435 if (!iter->ReadData(&payload, &payload_size))
1438 r->SetHeaderValues(static_cast<int32_t>(routing_id), type, flags);
1439 r->WriteBytes(payload, payload_size);
1443 void ParamTraits<Message>::Log(const Message& p, std::string* l) {
1444 l->append("<IPC::Message>");
1447 #if BUILDFLAG(IS_WIN)
1448 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
1449 // bit systems. That's why we use the Windows macros to convert to 32 bits.
1450 void ParamTraits<HANDLE>::Write(base::Pickle* m, const param_type& p) {
1451 m->WriteInt(HandleToLong(p));
1454 bool ParamTraits<HANDLE>::Read(const base::Pickle* m,
1455 base::PickleIterator* iter,
1458 if (!iter->ReadInt(&temp))
1460 *r = LongToHandle(temp);
1464 void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) {
1465 l->append(base::StringPrintf("0x%p", p));
1468 void ParamTraits<MSG>::Write(base::Pickle* m, const param_type& p) {
1469 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
1472 bool ParamTraits<MSG>::Read(const base::Pickle* m,
1473 base::PickleIterator* iter,
1476 size_t data_size = 0;
1477 bool result = iter->ReadData(&data, &data_size);
1478 if (result && data_size == sizeof(MSG)) {
1479 memcpy(r, data, sizeof(MSG));
1488 void ParamTraits<MSG>::Log(const param_type& p, std::string* l) {
1492 #endif // BUILDFLAG(IS_WIN)