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