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 #ifndef IPC_IPC_MESSAGE_UTILS_H_
      6 #define IPC_IPC_MESSAGE_UTILS_H_
      7 
      8 #include <limits.h>
      9 #include <stddef.h>
     10 #include <stdint.h>
     11 
     12 #include <algorithm>
     13 #include <map>
     14 #include <memory>
     15 #include <set>
     16 #include <string>
     17 #include <tuple>
     18 #include <vector>
     19 
     20 #include "base/containers/small_map.h"
     21 #include "base/containers/stack_container.h"
     22 #include "base/files/file.h"
     23 #include "base/format_macros.h"
     24 #include "base/memory/scoped_vector.h"
     25 #include "base/optional.h"
     26 #include "base/strings/string16.h"
     27 #include "base/strings/string_util.h"
     28 #include "base/strings/stringprintf.h"
     29 #include "build/build_config.h"
     30 #include "ipc/ipc_message_start.h"
     31 #include "ipc/ipc_param_traits.h"
     32 #include "ipc/ipc_sync_message.h"
     33 
     34 namespace base {
     35 class DictionaryValue;
     36 class FilePath;
     37 class ListValue;
     38 class NullableString16;
     39 class Time;
     40 class TimeDelta;
     41 class TimeTicks;
     42 class UnguessableToken;
     43 struct FileDescriptor;
     44 
     45 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
     46 class SharedMemoryHandle;
     47 #endif  // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
     48 }
     49 
     50 namespace IPC {
     51 
     52 struct ChannelHandle;
     53 
     54 // -----------------------------------------------------------------------------
     55 // How we send IPC message logs across channels.
     56 struct IPC_EXPORT LogData {
     57   LogData();
     58   LogData(const LogData& other);
     59   ~LogData();
     60 
     61   std::string channel;
     62   int32_t routing_id;
     63   uint32_t type;  // "User-defined" message type, from ipc_message.h.
     64   std::string flags;
     65   int64_t sent;  // Time that the message was sent (i.e. at Send()).
     66   int64_t receive;  // Time before it was dispatched (i.e. before calling
     67                     // OnMessageReceived).
     68   int64_t dispatch;  // Time after it was dispatched (i.e. after calling
     69                      // OnMessageReceived).
     70   std::string message_name;
     71   std::string params;
     72 };
     73 
     74 //-----------------------------------------------------------------------------
     75 
     76 // A dummy struct to place first just to allow leading commas for all
     77 // members in the macro-generated constructor initializer lists.
     78 struct NoParams {
     79 };
     80 
     81 // Specializations are checked by 'IPC checker' part of find-bad-constructs
     82 // Clang plugin (see WriteParam() below for the details).
     83 template <typename... Ts>
     84 struct CheckedTuple {
     85   typedef std::tuple<Ts...> Tuple;
     86 };
     87 
     88 template <class P>
     89 static inline void GetParamSize(base::PickleSizer* sizer, const P& p) {
     90   typedef typename SimilarTypeTraits<P>::Type Type;
     91   ParamTraits<Type>::GetSize(sizer, static_cast<const Type&>(p));
     92 }
     93 
     94 // This function is checked by 'IPC checker' part of find-bad-constructs
     95 // Clang plugin to make it's not called on the following types:
     96 // 1. long / unsigned long (but not typedefs to)
     97 // 2. intmax_t, uintmax_t, intptr_t, uintptr_t, wint_t,
     98 //    size_t, rsize_t, ssize_t, ptrdiff_t, dev_t, off_t, clock_t,
     99 //    time_t, suseconds_t (including typedefs to)
    100 // 3. Any template referencing types above (e.g. std::vector<size_t>)
    101 template <class P>
    102 static inline void WriteParam(base::Pickle* m, const P& p) {
    103   typedef typename SimilarTypeTraits<P>::Type Type;
    104   ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
    105 }
    106 
    107 template <class P>
    108 static inline bool WARN_UNUSED_RESULT ReadParam(const base::Pickle* m,
    109                                                 base::PickleIterator* iter,
    110                                                 P* p) {
    111   typedef typename SimilarTypeTraits<P>::Type Type;
    112   return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
    113 }
    114 
    115 template <class P>
    116 static inline void LogParam(const P& p, std::string* l) {
    117   typedef typename SimilarTypeTraits<P>::Type Type;
    118   ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
    119 }
    120 
    121 // Primitive ParamTraits -------------------------------------------------------
    122 
    123 template <>
    124 struct ParamTraits<bool> {
    125   typedef bool param_type;
    126   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    127     sizer->AddBool();
    128   }
    129   static void Write(base::Pickle* m, const param_type& p) { m->WriteBool(p); }
    130   static bool Read(const base::Pickle* m,
    131                    base::PickleIterator* iter,
    132                    param_type* r) {
    133     return iter->ReadBool(r);
    134   }
    135   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    136 };
    137 
    138 template <>
    139 struct IPC_EXPORT ParamTraits<signed char> {
    140   typedef signed char param_type;
    141   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    142   static void Write(base::Pickle* m, const param_type& p);
    143   static bool Read(const base::Pickle* m,
    144                    base::PickleIterator* iter,
    145                    param_type* r);
    146   static void Log(const param_type& p, std::string* l);
    147 };
    148 
    149 template <>
    150 struct IPC_EXPORT ParamTraits<unsigned char> {
    151   typedef unsigned char param_type;
    152   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    153   static void Write(base::Pickle* m, const param_type& p);
    154   static bool Read(const base::Pickle* m,
    155                    base::PickleIterator* iter,
    156                    param_type* r);
    157   static void Log(const param_type& p, std::string* l);
    158 };
    159 
    160 template <>
    161 struct IPC_EXPORT ParamTraits<unsigned short> {
    162   typedef unsigned short param_type;
    163   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    164   static void Write(base::Pickle* m, const param_type& p);
    165   static bool Read(const base::Pickle* m,
    166                    base::PickleIterator* iter,
    167                    param_type* r);
    168   static void Log(const param_type& p, std::string* l);
    169 };
    170 
    171 template <>
    172 struct ParamTraits<int> {
    173   typedef int param_type;
    174   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    175     sizer->AddInt();
    176   }
    177   static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); }
    178   static bool Read(const base::Pickle* m,
    179                    base::PickleIterator* iter,
    180                    param_type* r) {
    181     return iter->ReadInt(r);
    182   }
    183   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    184 };
    185 
    186 template <>
    187 struct ParamTraits<unsigned int> {
    188   typedef unsigned int param_type;
    189   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    190     sizer->AddInt();
    191   }
    192   static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); }
    193   static bool Read(const base::Pickle* m,
    194                    base::PickleIterator* iter,
    195                    param_type* r) {
    196     return iter->ReadInt(reinterpret_cast<int*>(r));
    197   }
    198   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    199 };
    200 
    201 // long isn't safe to send over IPC because it's 4 bytes on 32 bit builds but
    202 // 8 bytes on 64 bit builds. So if a 32 bit and 64 bit process have a channel
    203 // that would cause problem.
    204 // We need to keep this on for a few configs:
    205 //   1) Windows because DWORD is typedef'd to it, which is fine because we have
    206 //      very few IPCs that cross this boundary.
    207 //   2) We also need to keep it for Linux for two reasons: int64_t is typedef'd
    208 //      to long, and gfx::PluginWindow is long and is used in one GPU IPC.
    209 //   3) Android 64 bit also has int64_t typedef'd to long.
    210 // Since we want to support Android 32<>64 bit IPC, as long as we don't have
    211 // these traits for 32 bit ARM then that'll catch any errors.
    212 #if defined(OS_WIN) || defined(OS_LINUX) || \
    213     (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS))
    214 template <>
    215 struct ParamTraits<long> {
    216   typedef long param_type;
    217   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    218     sizer->AddLong();
    219   }
    220   static void Write(base::Pickle* m, const param_type& p) {
    221     m->WriteLong(p);
    222   }
    223   static bool Read(const base::Pickle* m,
    224                    base::PickleIterator* iter,
    225                    param_type* r) {
    226     return iter->ReadLong(r);
    227   }
    228   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    229 };
    230 
    231 template <>
    232 struct ParamTraits<unsigned long> {
    233   typedef unsigned long param_type;
    234   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    235     sizer->AddLong();
    236   }
    237   static void Write(base::Pickle* m, const param_type& p) {
    238     m->WriteLong(p);
    239   }
    240   static bool Read(const base::Pickle* m,
    241                    base::PickleIterator* iter,
    242                    param_type* r) {
    243     return iter->ReadLong(reinterpret_cast<long*>(r));
    244   }
    245   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    246 };
    247 #endif
    248 
    249 template <>
    250 struct ParamTraits<long long> {
    251   typedef long long param_type;
    252   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    253     sizer->AddInt64();
    254   }
    255   static void Write(base::Pickle* m, const param_type& p) {
    256     m->WriteInt64(static_cast<int64_t>(p));
    257   }
    258   static bool Read(const base::Pickle* m,
    259                    base::PickleIterator* iter,
    260                    param_type* r) {
    261     return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
    262   }
    263   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    264 };
    265 
    266 template <>
    267 struct ParamTraits<unsigned long long> {
    268   typedef unsigned long long param_type;
    269   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    270     sizer->AddInt64();
    271   }
    272   static void Write(base::Pickle* m, const param_type& p) { m->WriteInt64(p); }
    273   static bool Read(const base::Pickle* m,
    274                    base::PickleIterator* iter,
    275                    param_type* r) {
    276     return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
    277   }
    278   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    279 };
    280 
    281 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values.  Clients
    282 // should be sure to check the sanity of these values after receiving them over
    283 // IPC.
    284 template <>
    285 struct IPC_EXPORT ParamTraits<float> {
    286   typedef float param_type;
    287   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    288     sizer->AddFloat();
    289   }
    290   static void Write(base::Pickle* m, const param_type& p) { m->WriteFloat(p); }
    291   static bool Read(const base::Pickle* m,
    292                    base::PickleIterator* iter,
    293                    param_type* r) {
    294     return iter->ReadFloat(r);
    295   }
    296   static void Log(const param_type& p, std::string* l);
    297 };
    298 
    299 template <>
    300 struct IPC_EXPORT ParamTraits<double> {
    301   typedef double param_type;
    302   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    303   static void Write(base::Pickle* m, const param_type& p);
    304   static bool Read(const base::Pickle* m,
    305                    base::PickleIterator* iter,
    306                    param_type* r);
    307   static void Log(const param_type& p, std::string* l);
    308 };
    309 
    310 template <class P, size_t Size>
    311 struct ParamTraits<P[Size]> {
    312   using param_type = P[Size];
    313   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    314     for (const P& element : p)
    315       GetParamSize(sizer, element);
    316   }
    317   static void Write(base::Pickle* m, const param_type& p) {
    318     for (const P& element : p)
    319       WriteParam(m, element);
    320   }
    321   static bool Read(const base::Pickle* m,
    322                    base::PickleIterator* iter,
    323                    param_type* r) {
    324     for (P& element : *r) {
    325       if (!ReadParam(m, iter, &element))
    326         return false;
    327     }
    328     return true;
    329   }
    330   static void Log(const param_type& p, std::string* l) {
    331     l->append("[");
    332     for (const P& element : p) {
    333       if (&element != &p[0])
    334         l->append(" ");
    335       LogParam(element, l);
    336     }
    337     l->append("]");
    338   }
    339 };
    340 
    341 // STL ParamTraits -------------------------------------------------------------
    342 
    343 template <>
    344 struct ParamTraits<std::string> {
    345   typedef std::string param_type;
    346   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    347     sizer->AddString(p);
    348   }
    349   static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); }
    350   static bool Read(const base::Pickle* m,
    351                    base::PickleIterator* iter,
    352                    param_type* r) {
    353     return iter->ReadString(r);
    354   }
    355   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    356 };
    357 
    358 template <>
    359 struct ParamTraits<base::string16> {
    360   typedef base::string16 param_type;
    361   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    362     sizer->AddString16(p);
    363   }
    364   static void Write(base::Pickle* m, const param_type& p) {
    365     m->WriteString16(p);
    366   }
    367   static bool Read(const base::Pickle* m,
    368                    base::PickleIterator* iter,
    369                    param_type* r) {
    370     return iter->ReadString16(r);
    371   }
    372   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    373 };
    374 
    375 template <>
    376 struct IPC_EXPORT ParamTraits<std::vector<char> > {
    377   typedef std::vector<char> param_type;
    378   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    379   static void Write(base::Pickle* m, const param_type& p);
    380   static bool Read(const base::Pickle*,
    381                    base::PickleIterator* iter,
    382                    param_type* r);
    383   static void Log(const param_type& p, std::string* l);
    384 };
    385 
    386 template <>
    387 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
    388   typedef std::vector<unsigned char> param_type;
    389   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    390   static void Write(base::Pickle* m, const param_type& p);
    391   static bool Read(const base::Pickle* m,
    392                    base::PickleIterator* iter,
    393                    param_type* r);
    394   static void Log(const param_type& p, std::string* l);
    395 };
    396 
    397 template <>
    398 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
    399   typedef std::vector<bool> param_type;
    400   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    401   static void Write(base::Pickle* m, const param_type& p);
    402   static bool Read(const base::Pickle* m,
    403                    base::PickleIterator* iter,
    404                    param_type* r);
    405   static void Log(const param_type& p, std::string* l);
    406 };
    407 
    408 template <class P>
    409 struct ParamTraits<std::vector<P>> {
    410   typedef std::vector<P> param_type;
    411   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    412     GetParamSize(sizer, static_cast<int>(p.size()));
    413     for (size_t i = 0; i < p.size(); i++)
    414       GetParamSize(sizer, p[i]);
    415   }
    416   static void Write(base::Pickle* m, const param_type& p) {
    417     WriteParam(m, static_cast<int>(p.size()));
    418     for (size_t i = 0; i < p.size(); i++)
    419       WriteParam(m, p[i]);
    420   }
    421   static bool Read(const base::Pickle* m,
    422                    base::PickleIterator* iter,
    423                    param_type* r) {
    424     int size;
    425     // ReadLength() checks for < 0 itself.
    426     if (!iter->ReadLength(&size))
    427       return false;
    428     // Resizing beforehand is not safe, see BUG 1006367 for details.
    429     if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
    430       return false;
    431     r->resize(size);
    432     for (int i = 0; i < size; i++) {
    433       if (!ReadParam(m, iter, &(*r)[i]))
    434         return false;
    435     }
    436     return true;
    437   }
    438   static void Log(const param_type& p, std::string* l) {
    439     for (size_t i = 0; i < p.size(); ++i) {
    440       if (i != 0)
    441         l->append(" ");
    442       LogParam((p[i]), l);
    443     }
    444   }
    445 };
    446 
    447 template <class P>
    448 struct ParamTraits<std::set<P> > {
    449   typedef std::set<P> param_type;
    450   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    451     GetParamSize(sizer, static_cast<int>(p.size()));
    452     typename param_type::const_iterator iter;
    453     for (iter = p.begin(); iter != p.end(); ++iter)
    454       GetParamSize(sizer, *iter);
    455   }
    456   static void Write(base::Pickle* m, const param_type& p) {
    457     WriteParam(m, static_cast<int>(p.size()));
    458     typename param_type::const_iterator iter;
    459     for (iter = p.begin(); iter != p.end(); ++iter)
    460       WriteParam(m, *iter);
    461   }
    462   static bool Read(const base::Pickle* m,
    463                    base::PickleIterator* iter,
    464                    param_type* r) {
    465     int size;
    466     if (!iter->ReadLength(&size))
    467       return false;
    468     for (int i = 0; i < size; ++i) {
    469       P item;
    470       if (!ReadParam(m, iter, &item))
    471         return false;
    472       r->insert(item);
    473     }
    474     return true;
    475   }
    476   static void Log(const param_type& p, std::string* l) {
    477     l->append("<std::set>");
    478   }
    479 };
    480 
    481 template <class K, class V, class C, class A>
    482 struct ParamTraits<std::map<K, V, C, A> > {
    483   typedef std::map<K, V, C, A> param_type;
    484   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    485     GetParamSize(sizer, static_cast<int>(p.size()));
    486     typename param_type::const_iterator iter;
    487     for (iter = p.begin(); iter != p.end(); ++iter) {
    488       GetParamSize(sizer, iter->first);
    489       GetParamSize(sizer, iter->second);
    490     }
    491   }
    492   static void Write(base::Pickle* m, const param_type& p) {
    493     WriteParam(m, static_cast<int>(p.size()));
    494     typename param_type::const_iterator iter;
    495     for (iter = p.begin(); iter != p.end(); ++iter) {
    496       WriteParam(m, iter->first);
    497       WriteParam(m, iter->second);
    498     }
    499   }
    500   static bool Read(const base::Pickle* m,
    501                    base::PickleIterator* iter,
    502                    param_type* r) {
    503     int size;
    504     if (!ReadParam(m, iter, &size) || size < 0)
    505       return false;
    506     for (int i = 0; i < size; ++i) {
    507       K k;
    508       if (!ReadParam(m, iter, &k))
    509         return false;
    510       V& value = (*r)[k];
    511       if (!ReadParam(m, iter, &value))
    512         return false;
    513     }
    514     return true;
    515   }
    516   static void Log(const param_type& p, std::string* l) {
    517     l->append("<std::map>");
    518   }
    519 };
    520 
    521 template <class A, class B>
    522 struct ParamTraits<std::pair<A, B> > {
    523   typedef std::pair<A, B> param_type;
    524   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    525     GetParamSize(sizer, p.first);
    526     GetParamSize(sizer, p.second);
    527   }
    528   static void Write(base::Pickle* m, const param_type& p) {
    529     WriteParam(m, p.first);
    530     WriteParam(m, p.second);
    531   }
    532   static bool Read(const base::Pickle* m,
    533                    base::PickleIterator* iter,
    534                    param_type* r) {
    535     return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
    536   }
    537   static void Log(const param_type& p, std::string* l) {
    538     l->append("(");
    539     LogParam(p.first, l);
    540     l->append(", ");
    541     LogParam(p.second, l);
    542     l->append(")");
    543   }
    544 };
    545 
    546 // Base ParamTraits ------------------------------------------------------------
    547 
    548 template <>
    549 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
    550   typedef base::DictionaryValue param_type;
    551   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    552   static void Write(base::Pickle* m, const param_type& p);
    553   static bool Read(const base::Pickle* m,
    554                    base::PickleIterator* iter,
    555                    param_type* r);
    556   static void Log(const param_type& p, std::string* l);
    557 };
    558 
    559 #if defined(OS_POSIX)
    560 // FileDescriptors may be serialised over IPC channels on POSIX. On the
    561 // receiving side, the FileDescriptor is a valid duplicate of the file
    562 // descriptor which was transmitted: *it is not just a copy of the integer like
    563 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
    564 // this case, the receiving end will see a value of -1. *Zero is a valid file
    565 // descriptor*.
    566 //
    567 // The received file descriptor will have the |auto_close| flag set to true. The
    568 // code which handles the message is responsible for taking ownership of it.
    569 // File descriptors are OS resources and must be closed when no longer needed.
    570 //
    571 // When sending a file descriptor, the file descriptor must be valid at the time
    572 // of transmission. Since transmission is not synchronous, one should consider
    573 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
    574 // flag, which causes the file descriptor to be closed after writing.
    575 template<>
    576 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
    577   typedef base::FileDescriptor param_type;
    578   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    579   static void Write(base::Pickle* m, const param_type& p);
    580   static bool Read(const base::Pickle* m,
    581                    base::PickleIterator* iter,
    582                    param_type* r);
    583   static void Log(const param_type& p, std::string* l);
    584 };
    585 #endif  // defined(OS_POSIX)
    586 
    587 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
    588 template <>
    589 struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
    590   typedef base::SharedMemoryHandle param_type;
    591   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    592   static void Write(base::Pickle* m, const param_type& p);
    593   static bool Read(const base::Pickle* m,
    594                    base::PickleIterator* iter,
    595                    param_type* r);
    596   static void Log(const param_type& p, std::string* l);
    597 };
    598 #endif  // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
    599 
    600 template <>
    601 struct IPC_EXPORT ParamTraits<base::FilePath> {
    602   typedef base::FilePath param_type;
    603   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    604   static void Write(base::Pickle* m, const param_type& p);
    605   static bool Read(const base::Pickle* m,
    606                    base::PickleIterator* iter,
    607                    param_type* r);
    608   static void Log(const param_type& p, std::string* l);
    609 };
    610 
    611 template <>
    612 struct IPC_EXPORT ParamTraits<base::ListValue> {
    613   typedef base::ListValue param_type;
    614   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    615   static void Write(base::Pickle* m, const param_type& p);
    616   static bool Read(const base::Pickle* m,
    617                    base::PickleIterator* iter,
    618                    param_type* r);
    619   static void Log(const param_type& p, std::string* l);
    620 };
    621 
    622 template <>
    623 struct IPC_EXPORT ParamTraits<base::NullableString16> {
    624   typedef base::NullableString16 param_type;
    625   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    626   static void Write(base::Pickle* m, const param_type& p);
    627   static bool Read(const base::Pickle* m,
    628                    base::PickleIterator* iter,
    629                    param_type* r);
    630   static void Log(const param_type& p, std::string* l);
    631 };
    632 
    633 template <>
    634 struct IPC_EXPORT ParamTraits<base::File::Info> {
    635   typedef base::File::Info param_type;
    636   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    637   static void Write(base::Pickle* m, const param_type& p);
    638   static bool Read(const base::Pickle* m,
    639                    base::PickleIterator* iter,
    640                    param_type* r);
    641   static void Log(const param_type& p, std::string* l);
    642 };
    643 
    644 template <>
    645 struct SimilarTypeTraits<base::File::Error> {
    646   typedef int Type;
    647 };
    648 
    649 #if defined(OS_WIN)
    650 template <>
    651 struct SimilarTypeTraits<HWND> {
    652   typedef HANDLE Type;
    653 };
    654 #endif  // defined(OS_WIN)
    655 
    656 template <>
    657 struct IPC_EXPORT ParamTraits<base::Time> {
    658   typedef base::Time param_type;
    659   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    660   static void Write(base::Pickle* m, const param_type& p);
    661   static bool Read(const base::Pickle* m,
    662                    base::PickleIterator* iter,
    663                    param_type* r);
    664   static void Log(const param_type& p, std::string* l);
    665 };
    666 
    667 template <>
    668 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
    669   typedef base::TimeDelta param_type;
    670   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    671   static void Write(base::Pickle* m, const param_type& p);
    672   static bool Read(const base::Pickle* m,
    673                    base::PickleIterator* iter,
    674                    param_type* r);
    675   static void Log(const param_type& p, std::string* l);
    676 };
    677 
    678 template <>
    679 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
    680   typedef base::TimeTicks param_type;
    681   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    682   static void Write(base::Pickle* m, const param_type& p);
    683   static bool Read(const base::Pickle* m,
    684                    base::PickleIterator* iter,
    685                    param_type* r);
    686   static void Log(const param_type& p, std::string* l);
    687 };
    688 
    689 template <>
    690 struct IPC_EXPORT ParamTraits<base::UnguessableToken> {
    691   typedef base::UnguessableToken param_type;
    692   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    693   static void Write(base::Pickle* m, const param_type& p);
    694   static bool Read(const base::Pickle* m,
    695                    base::PickleIterator* iter,
    696                    param_type* r);
    697   static void Log(const param_type& p, std::string* l);
    698 };
    699 
    700 template <>
    701 struct ParamTraits<std::tuple<>> {
    702   typedef std::tuple<> param_type;
    703   static void GetSize(base::PickleSizer* sizer, const param_type& p) {}
    704   static void Write(base::Pickle* m, const param_type& p) {}
    705   static bool Read(const base::Pickle* m,
    706                    base::PickleIterator* iter,
    707                    param_type* r) {
    708     return true;
    709   }
    710   static void Log(const param_type& p, std::string* l) {
    711   }
    712 };
    713 
    714 template <class A>
    715 struct ParamTraits<std::tuple<A>> {
    716   typedef std::tuple<A> param_type;
    717   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    718     GetParamSize(sizer, std::get<0>(p));
    719   }
    720   static void Write(base::Pickle* m, const param_type& p) {
    721     WriteParam(m, std::get<0>(p));
    722   }
    723   static bool Read(const base::Pickle* m,
    724                    base::PickleIterator* iter,
    725                    param_type* r) {
    726     return ReadParam(m, iter, &std::get<0>(*r));
    727   }
    728   static void Log(const param_type& p, std::string* l) {
    729     LogParam(std::get<0>(p), l);
    730   }
    731 };
    732 
    733 template <class A, class B>
    734 struct ParamTraits<std::tuple<A, B>> {
    735   typedef std::tuple<A, B> param_type;
    736   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    737     GetParamSize(sizer, std::get<0>(p));
    738     GetParamSize(sizer, std::get<1>(p));
    739   }
    740   static void Write(base::Pickle* m, const param_type& p) {
    741     WriteParam(m, std::get<0>(p));
    742     WriteParam(m, std::get<1>(p));
    743   }
    744   static bool Read(const base::Pickle* m,
    745                    base::PickleIterator* iter,
    746                    param_type* r) {
    747     return (ReadParam(m, iter, &std::get<0>(*r)) &&
    748             ReadParam(m, iter, &std::get<1>(*r)));
    749   }
    750   static void Log(const param_type& p, std::string* l) {
    751     LogParam(std::get<0>(p), l);
    752     l->append(", ");
    753     LogParam(std::get<1>(p), l);
    754   }
    755 };
    756 
    757 template <class A, class B, class C>
    758 struct ParamTraits<std::tuple<A, B, C>> {
    759   typedef std::tuple<A, B, C> param_type;
    760   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    761     GetParamSize(sizer, std::get<0>(p));
    762     GetParamSize(sizer, std::get<1>(p));
    763     GetParamSize(sizer, std::get<2>(p));
    764   }
    765   static void Write(base::Pickle* m, const param_type& p) {
    766     WriteParam(m, std::get<0>(p));
    767     WriteParam(m, std::get<1>(p));
    768     WriteParam(m, std::get<2>(p));
    769   }
    770   static bool Read(const base::Pickle* m,
    771                    base::PickleIterator* iter,
    772                    param_type* r) {
    773     return (ReadParam(m, iter, &std::get<0>(*r)) &&
    774             ReadParam(m, iter, &std::get<1>(*r)) &&
    775             ReadParam(m, iter, &std::get<2>(*r)));
    776   }
    777   static void Log(const param_type& p, std::string* l) {
    778     LogParam(std::get<0>(p), l);
    779     l->append(", ");
    780     LogParam(std::get<1>(p), l);
    781     l->append(", ");
    782     LogParam(std::get<2>(p), l);
    783   }
    784 };
    785 
    786 template <class A, class B, class C, class D>
    787 struct ParamTraits<std::tuple<A, B, C, D>> {
    788   typedef std::tuple<A, B, C, D> param_type;
    789   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    790     GetParamSize(sizer, std::get<0>(p));
    791     GetParamSize(sizer, std::get<1>(p));
    792     GetParamSize(sizer, std::get<2>(p));
    793     GetParamSize(sizer, std::get<3>(p));
    794   }
    795   static void Write(base::Pickle* m, const param_type& p) {
    796     WriteParam(m, std::get<0>(p));
    797     WriteParam(m, std::get<1>(p));
    798     WriteParam(m, std::get<2>(p));
    799     WriteParam(m, std::get<3>(p));
    800   }
    801   static bool Read(const base::Pickle* m,
    802                    base::PickleIterator* iter,
    803                    param_type* r) {
    804     return (ReadParam(m, iter, &std::get<0>(*r)) &&
    805             ReadParam(m, iter, &std::get<1>(*r)) &&
    806             ReadParam(m, iter, &std::get<2>(*r)) &&
    807             ReadParam(m, iter, &std::get<3>(*r)));
    808   }
    809   static void Log(const param_type& p, std::string* l) {
    810     LogParam(std::get<0>(p), l);
    811     l->append(", ");
    812     LogParam(std::get<1>(p), l);
    813     l->append(", ");
    814     LogParam(std::get<2>(p), l);
    815     l->append(", ");
    816     LogParam(std::get<3>(p), l);
    817   }
    818 };
    819 
    820 template <class A, class B, class C, class D, class E>
    821 struct ParamTraits<std::tuple<A, B, C, D, E>> {
    822   typedef std::tuple<A, B, C, D, E> param_type;
    823   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    824     GetParamSize(sizer, std::get<0>(p));
    825     GetParamSize(sizer, std::get<1>(p));
    826     GetParamSize(sizer, std::get<2>(p));
    827     GetParamSize(sizer, std::get<3>(p));
    828     GetParamSize(sizer, std::get<4>(p));
    829   }
    830   static void Write(base::Pickle* m, const param_type& p) {
    831     WriteParam(m, std::get<0>(p));
    832     WriteParam(m, std::get<1>(p));
    833     WriteParam(m, std::get<2>(p));
    834     WriteParam(m, std::get<3>(p));
    835     WriteParam(m, std::get<4>(p));
    836   }
    837   static bool Read(const base::Pickle* m,
    838                    base::PickleIterator* iter,
    839                    param_type* r) {
    840     return (ReadParam(m, iter, &std::get<0>(*r)) &&
    841             ReadParam(m, iter, &std::get<1>(*r)) &&
    842             ReadParam(m, iter, &std::get<2>(*r)) &&
    843             ReadParam(m, iter, &std::get<3>(*r)) &&
    844             ReadParam(m, iter, &std::get<4>(*r)));
    845   }
    846   static void Log(const param_type& p, std::string* l) {
    847     LogParam(std::get<0>(p), l);
    848     l->append(", ");
    849     LogParam(std::get<1>(p), l);
    850     l->append(", ");
    851     LogParam(std::get<2>(p), l);
    852     l->append(", ");
    853     LogParam(std::get<3>(p), l);
    854     l->append(", ");
    855     LogParam(std::get<4>(p), l);
    856   }
    857 };
    858 
    859 template<class P>
    860 struct ParamTraits<ScopedVector<P> > {
    861   typedef ScopedVector<P> param_type;
    862   static void Write(base::Pickle* m, const param_type& p) {
    863     WriteParam(m, static_cast<int>(p.size()));
    864     for (size_t i = 0; i < p.size(); i++)
    865       WriteParam(m, *p[i]);
    866   }
    867   static bool Read(const base::Pickle* m,
    868                    base::PickleIterator* iter,
    869                    param_type* r) {
    870     int size = 0;
    871     if (!iter->ReadLength(&size))
    872       return false;
    873     if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
    874       return false;
    875     r->resize(size);
    876     for (int i = 0; i < size; i++) {
    877       (*r)[i] = new P();
    878       if (!ReadParam(m, iter, (*r)[i]))
    879         return false;
    880     }
    881     return true;
    882   }
    883   static void Log(const param_type& p, std::string* l) {
    884     for (size_t i = 0; i < p.size(); ++i) {
    885       if (i != 0)
    886         l->append(" ");
    887       LogParam(*p[i], l);
    888     }
    889   }
    890 };
    891 
    892 template <class P, size_t stack_capacity>
    893 struct ParamTraits<base::StackVector<P, stack_capacity> > {
    894   typedef base::StackVector<P, stack_capacity> param_type;
    895   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    896     GetParamSize(sizer, static_cast<int>(p->size()));
    897     for (size_t i = 0; i < p->size(); i++)
    898       GetParamSize(sizer, p[i]);
    899   }
    900   static void Write(base::Pickle* m, const param_type& p) {
    901     WriteParam(m, static_cast<int>(p->size()));
    902     for (size_t i = 0; i < p->size(); i++)
    903       WriteParam(m, p[i]);
    904   }
    905   static bool Read(const base::Pickle* m,
    906                    base::PickleIterator* iter,
    907                    param_type* r) {
    908     int size;
    909     // ReadLength() checks for < 0 itself.
    910     if (!iter->ReadLength(&size))
    911       return false;
    912     // Sanity check for the vector size.
    913     if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
    914       return false;
    915     P value;
    916     for (int i = 0; i < size; i++) {
    917       if (!ReadParam(m, iter, &value))
    918         return false;
    919       (*r)->push_back(value);
    920     }
    921     return true;
    922   }
    923   static void Log(const param_type& p, std::string* l) {
    924     for (size_t i = 0; i < p->size(); ++i) {
    925       if (i != 0)
    926         l->append(" ");
    927       LogParam((p[i]), l);
    928     }
    929   }
    930 };
    931 
    932 template <typename NormalMap,
    933           int kArraySize,
    934           typename EqualKey,
    935           typename MapInit>
    936 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
    937   typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
    938   typedef typename param_type::key_type K;
    939   typedef typename param_type::data_type V;
    940   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    941     GetParamSize(sizer, static_cast<int>(p.size()));
    942     typename param_type::const_iterator iter;
    943     for (iter = p.begin(); iter != p.end(); ++iter) {
    944       GetParamSize(sizer, iter->first);
    945       GetParamSize(sizer, iter->second);
    946     }
    947   }
    948   static void Write(base::Pickle* m, const param_type& p) {
    949     WriteParam(m, static_cast<int>(p.size()));
    950     typename param_type::const_iterator iter;
    951     for (iter = p.begin(); iter != p.end(); ++iter) {
    952       WriteParam(m, iter->first);
    953       WriteParam(m, iter->second);
    954     }
    955   }
    956   static bool Read(const base::Pickle* m,
    957                    base::PickleIterator* iter,
    958                    param_type* r) {
    959     int size;
    960     if (!iter->ReadLength(&size))
    961       return false;
    962     for (int i = 0; i < size; ++i) {
    963       K key;
    964       if (!ReadParam(m, iter, &key))
    965         return false;
    966       V& value = (*r)[key];
    967       if (!ReadParam(m, iter, &value))
    968         return false;
    969     }
    970     return true;
    971   }
    972   static void Log(const param_type& p, std::string* l) {
    973     l->append("<base::SmallMap>");
    974   }
    975 };
    976 
    977 template <class P>
    978 struct ParamTraits<std::unique_ptr<P>> {
    979   typedef std::unique_ptr<P> param_type;
    980   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    981     bool valid = !!p;
    982     GetParamSize(sizer, valid);
    983     if (valid)
    984       GetParamSize(sizer, *p);
    985   }
    986   static void Write(base::Pickle* m, const param_type& p) {
    987     bool valid = !!p;
    988     WriteParam(m, valid);
    989     if (valid)
    990       WriteParam(m, *p);
    991   }
    992   static bool Read(const base::Pickle* m,
    993                    base::PickleIterator* iter,
    994                    param_type* r) {
    995     bool valid = false;
    996     if (!ReadParam(m, iter, &valid))
    997       return false;
    998 
    999     if (!valid) {
   1000       r->reset();
   1001       return true;
   1002     }
   1003 
   1004     param_type temp(new P());
   1005     if (!ReadParam(m, iter, temp.get()))
   1006       return false;
   1007 
   1008     r->swap(temp);
   1009     return true;
   1010   }
   1011   static void Log(const param_type& p, std::string* l) {
   1012     if (p)
   1013       LogParam(*p, l);
   1014     else
   1015       l->append("NULL");
   1016   }
   1017 };
   1018 
   1019 template <class P>
   1020 struct ParamTraits<base::Optional<P>> {
   1021   typedef base::Optional<P> param_type;
   1022   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
   1023     const bool is_set = static_cast<bool>(p);
   1024     GetParamSize(sizer, is_set);
   1025     if (is_set)
   1026       GetParamSize(sizer, p.value());
   1027   }
   1028   static void Write(base::Pickle* m, const param_type& p) {
   1029     const bool is_set = static_cast<bool>(p);
   1030     WriteParam(m, is_set);
   1031     if (is_set)
   1032       WriteParam(m, p.value());
   1033   }
   1034   static bool Read(const base::Pickle* m,
   1035                    base::PickleIterator* iter,
   1036                    param_type* r) {
   1037     bool is_set = false;
   1038     if (!iter->ReadBool(&is_set))
   1039       return false;
   1040     if (is_set) {
   1041       P value;
   1042       if (!ReadParam(m, iter, &value))
   1043         return false;
   1044       *r = std::move(value);
   1045     }
   1046     return true;
   1047   }
   1048   static void Log(const param_type& p, std::string* l) {
   1049     if (p)
   1050       LogParam(p.value(), l);
   1051     else
   1052       l->append("(unset)");
   1053   }
   1054 };
   1055 
   1056 // IPC types ParamTraits -------------------------------------------------------
   1057 
   1058 // A ChannelHandle is basically a platform-inspecific wrapper around the
   1059 // fact that IPC endpoints are handled specially on POSIX.  See above comments
   1060 // on FileDescriptor for more background.
   1061 template<>
   1062 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
   1063   typedef ChannelHandle param_type;
   1064   static void GetSize(base::PickleSizer* sizer, const param_type& p);
   1065   static void Write(base::Pickle* m, const param_type& p);
   1066   static bool Read(const base::Pickle* m,
   1067                    base::PickleIterator* iter,
   1068                    param_type* r);
   1069   static void Log(const param_type& p, std::string* l);
   1070 };
   1071 
   1072 template <>
   1073 struct IPC_EXPORT ParamTraits<LogData> {
   1074   typedef LogData param_type;
   1075   static void GetSize(base::PickleSizer* sizer, const param_type& p);
   1076   static void Write(base::Pickle* m, const param_type& p);
   1077   static bool Read(const base::Pickle* m,
   1078                    base::PickleIterator* iter,
   1079                    param_type* r);
   1080   static void Log(const param_type& p, std::string* l);
   1081 };
   1082 
   1083 template <>
   1084 struct IPC_EXPORT ParamTraits<Message> {
   1085   static void Write(base::Pickle* m, const Message& p);
   1086   static bool Read(const base::Pickle* m,
   1087                    base::PickleIterator* iter,
   1088                    Message* r);
   1089   static void Log(const Message& p, std::string* l);
   1090 };
   1091 
   1092 // Windows ParamTraits ---------------------------------------------------------
   1093 
   1094 #if defined(OS_WIN)
   1095 template <>
   1096 struct IPC_EXPORT ParamTraits<HANDLE> {
   1097   typedef HANDLE param_type;
   1098   static void GetSize(base::PickleSizer* sizer, const param_type& p);
   1099   static void Write(base::Pickle* m, const param_type& p);
   1100   static bool Read(const base::Pickle* m,
   1101                    base::PickleIterator* iter,
   1102                    param_type* r);
   1103   static void Log(const param_type& p, std::string* l);
   1104 };
   1105 
   1106 template <>
   1107 struct IPC_EXPORT ParamTraits<LOGFONT> {
   1108   typedef LOGFONT param_type;
   1109   static void GetSize(base::PickleSizer* sizer, const param_type& p);
   1110   static void Write(base::Pickle* m, const param_type& p);
   1111   static bool Read(const base::Pickle* m,
   1112                    base::PickleIterator* iter,
   1113                    param_type* r);
   1114   static void Log(const param_type& p, std::string* l);
   1115 };
   1116 
   1117 template <>
   1118 struct IPC_EXPORT ParamTraits<MSG> {
   1119   typedef MSG param_type;
   1120   static void GetSize(base::PickleSizer* sizer, const param_type& p);
   1121   static void Write(base::Pickle* m, const param_type& p);
   1122   static bool Read(const base::Pickle* m,
   1123                    base::PickleIterator* iter,
   1124                    param_type* r);
   1125   static void Log(const param_type& p, std::string* l);
   1126 };
   1127 #endif  // defined(OS_WIN)
   1128 
   1129 //-----------------------------------------------------------------------------
   1130 // Generic message subclasses
   1131 
   1132 // defined in ipc_logging.cc
   1133 IPC_EXPORT void GenerateLogData(const Message& message,
   1134                                 LogData* data,
   1135                                 bool get_params);
   1136 
   1137 #if defined(IPC_MESSAGE_LOG_ENABLED)
   1138 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
   1139   const std::string& output_params = msg->output_params();
   1140   if (!l->empty() && !output_params.empty())
   1141     l->append(", ");
   1142 
   1143   l->append(output_params);
   1144 }
   1145 
   1146 template <class ReplyParamType>
   1147 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
   1148                                     const Message* msg) {
   1149   if (msg->received_time() != 0) {
   1150     std::string output_params;
   1151     LogParam(reply_params, &output_params);
   1152     msg->set_output_params(output_params);
   1153   }
   1154 }
   1155 
   1156 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
   1157   if (msg->sent_time()) {
   1158     // Don't log the sync message after dispatch, as we don't have the
   1159     // output parameters at that point.  Instead, save its data and log it
   1160     // with the outgoing reply message when it's sent.
   1161     LogData* data = new LogData;
   1162     GenerateLogData(*msg, data, true);
   1163     msg->set_dont_log();
   1164     reply->set_sync_log_data(data);
   1165   }
   1166 }
   1167 #else
   1168 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
   1169 
   1170 template <class ReplyParamType>
   1171 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
   1172                                     const Message* msg) {}
   1173 
   1174 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
   1175 #endif
   1176 
   1177 }  // namespace IPC
   1178 
   1179 #endif  // IPC_IPC_MESSAGE_UTILS_H_
   1180