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