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