• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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