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/brokerable_attachment.h"
     31 #include "ipc/ipc_message_start.h"
     32 #include "ipc/ipc_param_traits.h"
     33 #include "ipc/ipc_sync_message.h"
     34 
     35 namespace base {
     36 class DictionaryValue;
     37 class FilePath;
     38 class ListValue;
     39 class NullableString16;
     40 class Time;
     41 class TimeDelta;
     42 class TimeTicks;
     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 // STL ParamTraits -------------------------------------------------------------
    311 
    312 template <>
    313 struct ParamTraits<std::string> {
    314   typedef std::string param_type;
    315   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    316     sizer->AddString(p);
    317   }
    318   static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); }
    319   static bool Read(const base::Pickle* m,
    320                    base::PickleIterator* iter,
    321                    param_type* r) {
    322     return iter->ReadString(r);
    323   }
    324   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    325 };
    326 
    327 template <>
    328 struct ParamTraits<base::string16> {
    329   typedef base::string16 param_type;
    330   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    331     sizer->AddString16(p);
    332   }
    333   static void Write(base::Pickle* m, const param_type& p) {
    334     m->WriteString16(p);
    335   }
    336   static bool Read(const base::Pickle* m,
    337                    base::PickleIterator* iter,
    338                    param_type* r) {
    339     return iter->ReadString16(r);
    340   }
    341   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    342 };
    343 
    344 template <>
    345 struct IPC_EXPORT ParamTraits<std::vector<char> > {
    346   typedef std::vector<char> param_type;
    347   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    348   static void Write(base::Pickle* m, const param_type& p);
    349   static bool Read(const base::Pickle*,
    350                    base::PickleIterator* iter,
    351                    param_type* r);
    352   static void Log(const param_type& p, std::string* l);
    353 };
    354 
    355 template <>
    356 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
    357   typedef std::vector<unsigned char> param_type;
    358   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    359   static void Write(base::Pickle* m, const param_type& p);
    360   static bool Read(const base::Pickle* m,
    361                    base::PickleIterator* iter,
    362                    param_type* r);
    363   static void Log(const param_type& p, std::string* l);
    364 };
    365 
    366 template <>
    367 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
    368   typedef std::vector<bool> param_type;
    369   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    370   static void Write(base::Pickle* m, const param_type& p);
    371   static bool Read(const base::Pickle* m,
    372                    base::PickleIterator* iter,
    373                    param_type* r);
    374   static void Log(const param_type& p, std::string* l);
    375 };
    376 
    377 template <class P>
    378 struct ParamTraits<std::vector<P>> {
    379   typedef std::vector<P> param_type;
    380   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    381     GetParamSize(sizer, static_cast<int>(p.size()));
    382     for (size_t i = 0; i < p.size(); i++)
    383       GetParamSize(sizer, p[i]);
    384   }
    385   static void Write(base::Pickle* m, const param_type& p) {
    386     WriteParam(m, static_cast<int>(p.size()));
    387     for (size_t i = 0; i < p.size(); i++)
    388       WriteParam(m, p[i]);
    389   }
    390   static bool Read(const base::Pickle* m,
    391                    base::PickleIterator* iter,
    392                    param_type* r) {
    393     int size;
    394     // ReadLength() checks for < 0 itself.
    395     if (!iter->ReadLength(&size))
    396       return false;
    397     // Resizing beforehand is not safe, see BUG 1006367 for details.
    398     if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
    399       return false;
    400     r->resize(size);
    401     for (int i = 0; i < size; i++) {
    402       if (!ReadParam(m, iter, &(*r)[i]))
    403         return false;
    404     }
    405     return true;
    406   }
    407   static void Log(const param_type& p, std::string* l) {
    408     for (size_t i = 0; i < p.size(); ++i) {
    409       if (i != 0)
    410         l->append(" ");
    411       LogParam((p[i]), l);
    412     }
    413   }
    414 };
    415 
    416 template <class P>
    417 struct ParamTraits<std::set<P> > {
    418   typedef std::set<P> param_type;
    419   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    420     GetParamSize(sizer, static_cast<int>(p.size()));
    421     typename param_type::const_iterator iter;
    422     for (iter = p.begin(); iter != p.end(); ++iter)
    423       GetParamSize(sizer, *iter);
    424   }
    425   static void Write(base::Pickle* m, const param_type& p) {
    426     WriteParam(m, static_cast<int>(p.size()));
    427     typename param_type::const_iterator iter;
    428     for (iter = p.begin(); iter != p.end(); ++iter)
    429       WriteParam(m, *iter);
    430   }
    431   static bool Read(const base::Pickle* m,
    432                    base::PickleIterator* iter,
    433                    param_type* r) {
    434     int size;
    435     if (!iter->ReadLength(&size))
    436       return false;
    437     for (int i = 0; i < size; ++i) {
    438       P item;
    439       if (!ReadParam(m, iter, &item))
    440         return false;
    441       r->insert(item);
    442     }
    443     return true;
    444   }
    445   static void Log(const param_type& p, std::string* l) {
    446     l->append("<std::set>");
    447   }
    448 };
    449 
    450 template <class K, class V, class C, class A>
    451 struct ParamTraits<std::map<K, V, C, A> > {
    452   typedef std::map<K, V, C, A> param_type;
    453   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    454     GetParamSize(sizer, static_cast<int>(p.size()));
    455     typename param_type::const_iterator iter;
    456     for (iter = p.begin(); iter != p.end(); ++iter) {
    457       GetParamSize(sizer, iter->first);
    458       GetParamSize(sizer, iter->second);
    459     }
    460   }
    461   static void Write(base::Pickle* m, const param_type& p) {
    462     WriteParam(m, static_cast<int>(p.size()));
    463     typename param_type::const_iterator iter;
    464     for (iter = p.begin(); iter != p.end(); ++iter) {
    465       WriteParam(m, iter->first);
    466       WriteParam(m, iter->second);
    467     }
    468   }
    469   static bool Read(const base::Pickle* m,
    470                    base::PickleIterator* iter,
    471                    param_type* r) {
    472     int size;
    473     if (!ReadParam(m, iter, &size) || size < 0)
    474       return false;
    475     for (int i = 0; i < size; ++i) {
    476       K k;
    477       if (!ReadParam(m, iter, &k))
    478         return false;
    479       V& value = (*r)[k];
    480       if (!ReadParam(m, iter, &value))
    481         return false;
    482     }
    483     return true;
    484   }
    485   static void Log(const param_type& p, std::string* l) {
    486     l->append("<std::map>");
    487   }
    488 };
    489 
    490 template <class A, class B>
    491 struct ParamTraits<std::pair<A, B> > {
    492   typedef std::pair<A, B> param_type;
    493   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    494     GetParamSize(sizer, p.first);
    495     GetParamSize(sizer, p.second);
    496   }
    497   static void Write(base::Pickle* m, const param_type& p) {
    498     WriteParam(m, p.first);
    499     WriteParam(m, p.second);
    500   }
    501   static bool Read(const base::Pickle* m,
    502                    base::PickleIterator* iter,
    503                    param_type* r) {
    504     return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
    505   }
    506   static void Log(const param_type& p, std::string* l) {
    507     l->append("(");
    508     LogParam(p.first, l);
    509     l->append(", ");
    510     LogParam(p.second, l);
    511     l->append(")");
    512   }
    513 };
    514 
    515 // IPC ParamTraits -------------------------------------------------------------
    516 template <>
    517 struct IPC_EXPORT ParamTraits<BrokerableAttachment::AttachmentId> {
    518   typedef BrokerableAttachment::AttachmentId param_type;
    519   static void Write(base::Pickle* m, const param_type& p);
    520   static bool Read(const base::Pickle* m,
    521                    base::PickleIterator* iter,
    522                    param_type* r);
    523   static void Log(const param_type& p, std::string* l);
    524 };
    525 
    526 // Base ParamTraits ------------------------------------------------------------
    527 
    528 template <>
    529 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
    530   typedef base::DictionaryValue param_type;
    531   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    532   static void Write(base::Pickle* m, const param_type& p);
    533   static bool Read(const base::Pickle* m,
    534                    base::PickleIterator* iter,
    535                    param_type* r);
    536   static void Log(const param_type& p, std::string* l);
    537 };
    538 
    539 #if defined(OS_POSIX)
    540 // FileDescriptors may be serialised over IPC channels on POSIX. On the
    541 // receiving side, the FileDescriptor is a valid duplicate of the file
    542 // descriptor which was transmitted: *it is not just a copy of the integer like
    543 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
    544 // this case, the receiving end will see a value of -1. *Zero is a valid file
    545 // descriptor*.
    546 //
    547 // The received file descriptor will have the |auto_close| flag set to true. The
    548 // code which handles the message is responsible for taking ownership of it.
    549 // File descriptors are OS resources and must be closed when no longer needed.
    550 //
    551 // When sending a file descriptor, the file descriptor must be valid at the time
    552 // of transmission. Since transmission is not synchronous, one should consider
    553 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
    554 // flag, which causes the file descriptor to be closed after writing.
    555 template<>
    556 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
    557   typedef base::FileDescriptor param_type;
    558   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    559   static void Write(base::Pickle* m, const param_type& p);
    560   static bool Read(const base::Pickle* m,
    561                    base::PickleIterator* iter,
    562                    param_type* r);
    563   static void Log(const param_type& p, std::string* l);
    564 };
    565 #endif  // defined(OS_POSIX)
    566 
    567 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
    568 template <>
    569 struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
    570   typedef base::SharedMemoryHandle param_type;
    571   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    572   static void Write(base::Pickle* m, const param_type& p);
    573   static bool Read(const base::Pickle* m,
    574                    base::PickleIterator* iter,
    575                    param_type* r);
    576   static void Log(const param_type& p, std::string* l);
    577 };
    578 #endif  // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
    579 
    580 template <>
    581 struct IPC_EXPORT ParamTraits<base::FilePath> {
    582   typedef base::FilePath param_type;
    583   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    584   static void Write(base::Pickle* m, const param_type& p);
    585   static bool Read(const base::Pickle* m,
    586                    base::PickleIterator* iter,
    587                    param_type* r);
    588   static void Log(const param_type& p, std::string* l);
    589 };
    590 
    591 template <>
    592 struct IPC_EXPORT ParamTraits<base::ListValue> {
    593   typedef base::ListValue param_type;
    594   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    595   static void Write(base::Pickle* m, const param_type& p);
    596   static bool Read(const base::Pickle* m,
    597                    base::PickleIterator* iter,
    598                    param_type* r);
    599   static void Log(const param_type& p, std::string* l);
    600 };
    601 
    602 template <>
    603 struct IPC_EXPORT ParamTraits<base::NullableString16> {
    604   typedef base::NullableString16 param_type;
    605   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    606   static void Write(base::Pickle* m, const param_type& p);
    607   static bool Read(const base::Pickle* m,
    608                    base::PickleIterator* iter,
    609                    param_type* r);
    610   static void Log(const param_type& p, std::string* l);
    611 };
    612 
    613 template <>
    614 struct IPC_EXPORT ParamTraits<base::File::Info> {
    615   typedef base::File::Info param_type;
    616   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    617   static void Write(base::Pickle* m, const param_type& p);
    618   static bool Read(const base::Pickle* m,
    619                    base::PickleIterator* iter,
    620                    param_type* r);
    621   static void Log(const param_type& p, std::string* l);
    622 };
    623 
    624 template <>
    625 struct SimilarTypeTraits<base::File::Error> {
    626   typedef int Type;
    627 };
    628 
    629 #if defined(OS_WIN)
    630 template <>
    631 struct SimilarTypeTraits<HWND> {
    632   typedef HANDLE Type;
    633 };
    634 #endif  // defined(OS_WIN)
    635 
    636 template <>
    637 struct IPC_EXPORT ParamTraits<base::Time> {
    638   typedef base::Time param_type;
    639   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    640   static void Write(base::Pickle* m, const param_type& p);
    641   static bool Read(const base::Pickle* m,
    642                    base::PickleIterator* iter,
    643                    param_type* r);
    644   static void Log(const param_type& p, std::string* l);
    645 };
    646 
    647 template <>
    648 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
    649   typedef base::TimeDelta param_type;
    650   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    651   static void Write(base::Pickle* m, const param_type& p);
    652   static bool Read(const base::Pickle* m,
    653                    base::PickleIterator* iter,
    654                    param_type* r);
    655   static void Log(const param_type& p, std::string* l);
    656 };
    657 
    658 template <>
    659 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
    660   typedef base::TimeTicks param_type;
    661   static void GetSize(base::PickleSizer* sizer, const param_type& p);
    662   static void Write(base::Pickle* m, const param_type& p);
    663   static bool Read(const base::Pickle* m,
    664                    base::PickleIterator* iter,
    665                    param_type* r);
    666   static void Log(const param_type& p, std::string* l);
    667 };
    668 
    669 template <>
    670 struct ParamTraits<std::tuple<>> {
    671   typedef std::tuple<> param_type;
    672   static void GetSize(base::PickleSizer* sizer, const param_type& p) {}
    673   static void Write(base::Pickle* m, const param_type& p) {}
    674   static bool Read(const base::Pickle* m,
    675                    base::PickleIterator* iter,
    676                    param_type* r) {
    677     return true;
    678   }
    679   static void Log(const param_type& p, std::string* l) {
    680   }
    681 };
    682 
    683 template <class A>
    684 struct ParamTraits<std::tuple<A>> {
    685   typedef std::tuple<A> param_type;
    686   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    687     GetParamSize(sizer, std::get<0>(p));
    688   }
    689   static void Write(base::Pickle* m, const param_type& p) {
    690     WriteParam(m, std::get<0>(p));
    691   }
    692   static bool Read(const base::Pickle* m,
    693                    base::PickleIterator* iter,
    694                    param_type* r) {
    695     return ReadParam(m, iter, &std::get<0>(*r));
    696   }
    697   static void Log(const param_type& p, std::string* l) {
    698     LogParam(std::get<0>(p), l);
    699   }
    700 };
    701 
    702 template <class A, class B>
    703 struct ParamTraits<std::tuple<A, B>> {
    704   typedef std::tuple<A, B> param_type;
    705   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    706     GetParamSize(sizer, std::get<0>(p));
    707     GetParamSize(sizer, std::get<1>(p));
    708   }
    709   static void Write(base::Pickle* m, const param_type& p) {
    710     WriteParam(m, std::get<0>(p));
    711     WriteParam(m, std::get<1>(p));
    712   }
    713   static bool Read(const base::Pickle* m,
    714                    base::PickleIterator* iter,
    715                    param_type* r) {
    716     return (ReadParam(m, iter, &std::get<0>(*r)) &&
    717             ReadParam(m, iter, &std::get<1>(*r)));
    718   }
    719   static void Log(const param_type& p, std::string* l) {
    720     LogParam(std::get<0>(p), l);
    721     l->append(", ");
    722     LogParam(std::get<1>(p), l);
    723   }
    724 };
    725 
    726 template <class A, class B, class C>
    727 struct ParamTraits<std::tuple<A, B, C>> {
    728   typedef std::tuple<A, B, C> param_type;
    729   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    730     GetParamSize(sizer, std::get<0>(p));
    731     GetParamSize(sizer, std::get<1>(p));
    732     GetParamSize(sizer, std::get<2>(p));
    733   }
    734   static void Write(base::Pickle* m, const param_type& p) {
    735     WriteParam(m, std::get<0>(p));
    736     WriteParam(m, std::get<1>(p));
    737     WriteParam(m, std::get<2>(p));
    738   }
    739   static bool Read(const base::Pickle* m,
    740                    base::PickleIterator* iter,
    741                    param_type* r) {
    742     return (ReadParam(m, iter, &std::get<0>(*r)) &&
    743             ReadParam(m, iter, &std::get<1>(*r)) &&
    744             ReadParam(m, iter, &std::get<2>(*r)));
    745   }
    746   static void Log(const param_type& p, std::string* l) {
    747     LogParam(std::get<0>(p), l);
    748     l->append(", ");
    749     LogParam(std::get<1>(p), l);
    750     l->append(", ");
    751     LogParam(std::get<2>(p), l);
    752   }
    753 };
    754 
    755 template <class A, class B, class C, class D>
    756 struct ParamTraits<std::tuple<A, B, C, D>> {
    757   typedef std::tuple<A, B, C, D> param_type;
    758   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    759     GetParamSize(sizer, std::get<0>(p));
    760     GetParamSize(sizer, std::get<1>(p));
    761     GetParamSize(sizer, std::get<2>(p));
    762     GetParamSize(sizer, std::get<3>(p));
    763   }
    764   static void Write(base::Pickle* m, const param_type& p) {
    765     WriteParam(m, std::get<0>(p));
    766     WriteParam(m, std::get<1>(p));
    767     WriteParam(m, std::get<2>(p));
    768     WriteParam(m, std::get<3>(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             ReadParam(m, iter, &std::get<3>(*r)));
    777   }
    778   static void Log(const param_type& p, std::string* l) {
    779     LogParam(std::get<0>(p), l);
    780     l->append(", ");
    781     LogParam(std::get<1>(p), l);
    782     l->append(", ");
    783     LogParam(std::get<2>(p), l);
    784     l->append(", ");
    785     LogParam(std::get<3>(p), l);
    786   }
    787 };
    788 
    789 template <class A, class B, class C, class D, class E>
    790 struct ParamTraits<std::tuple<A, B, C, D, E>> {
    791   typedef std::tuple<A, B, C, D, E> param_type;
    792   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    793     GetParamSize(sizer, std::get<0>(p));
    794     GetParamSize(sizer, std::get<1>(p));
    795     GetParamSize(sizer, std::get<2>(p));
    796     GetParamSize(sizer, std::get<3>(p));
    797     GetParamSize(sizer, std::get<4>(p));
    798   }
    799   static void Write(base::Pickle* m, const param_type& p) {
    800     WriteParam(m, std::get<0>(p));
    801     WriteParam(m, std::get<1>(p));
    802     WriteParam(m, std::get<2>(p));
    803     WriteParam(m, std::get<3>(p));
    804     WriteParam(m, std::get<4>(p));
    805   }
    806   static bool Read(const base::Pickle* m,
    807                    base::PickleIterator* iter,
    808                    param_type* r) {
    809     return (ReadParam(m, iter, &std::get<0>(*r)) &&
    810             ReadParam(m, iter, &std::get<1>(*r)) &&
    811             ReadParam(m, iter, &std::get<2>(*r)) &&
    812             ReadParam(m, iter, &std::get<3>(*r)) &&
    813             ReadParam(m, iter, &std::get<4>(*r)));
    814   }
    815   static void Log(const param_type& p, std::string* l) {
    816     LogParam(std::get<0>(p), l);
    817     l->append(", ");
    818     LogParam(std::get<1>(p), l);
    819     l->append(", ");
    820     LogParam(std::get<2>(p), l);
    821     l->append(", ");
    822     LogParam(std::get<3>(p), l);
    823     l->append(", ");
    824     LogParam(std::get<4>(p), l);
    825   }
    826 };
    827 
    828 template<class P>
    829 struct ParamTraits<ScopedVector<P> > {
    830   typedef ScopedVector<P> param_type;
    831   static void Write(base::Pickle* m, const param_type& p) {
    832     WriteParam(m, static_cast<int>(p.size()));
    833     for (size_t i = 0; i < p.size(); i++)
    834       WriteParam(m, *p[i]);
    835   }
    836   static bool Read(const base::Pickle* m,
    837                    base::PickleIterator* iter,
    838                    param_type* r) {
    839     int size = 0;
    840     if (!iter->ReadLength(&size))
    841       return false;
    842     if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
    843       return false;
    844     r->resize(size);
    845     for (int i = 0; i < size; i++) {
    846       (*r)[i] = new P();
    847       if (!ReadParam(m, iter, (*r)[i]))
    848         return false;
    849     }
    850     return true;
    851   }
    852   static void Log(const param_type& p, std::string* l) {
    853     for (size_t i = 0; i < p.size(); ++i) {
    854       if (i != 0)
    855         l->append(" ");
    856       LogParam(*p[i], l);
    857     }
    858   }
    859 };
    860 
    861 template <class P, size_t stack_capacity>
    862 struct ParamTraits<base::StackVector<P, stack_capacity> > {
    863   typedef base::StackVector<P, stack_capacity> param_type;
    864   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    865     GetParamSize(sizer, static_cast<int>(p->size()));
    866     for (size_t i = 0; i < p->size(); i++)
    867       GetParamSize(sizer, p[i]);
    868   }
    869   static void Write(base::Pickle* m, const param_type& p) {
    870     WriteParam(m, static_cast<int>(p->size()));
    871     for (size_t i = 0; i < p->size(); i++)
    872       WriteParam(m, p[i]);
    873   }
    874   static bool Read(const base::Pickle* m,
    875                    base::PickleIterator* iter,
    876                    param_type* r) {
    877     int size;
    878     // ReadLength() checks for < 0 itself.
    879     if (!iter->ReadLength(&size))
    880       return false;
    881     // Sanity check for the vector size.
    882     if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
    883       return false;
    884     P value;
    885     for (int i = 0; i < size; i++) {
    886       if (!ReadParam(m, iter, &value))
    887         return false;
    888       (*r)->push_back(value);
    889     }
    890     return true;
    891   }
    892   static void Log(const param_type& p, std::string* l) {
    893     for (size_t i = 0; i < p->size(); ++i) {
    894       if (i != 0)
    895         l->append(" ");
    896       LogParam((p[i]), l);
    897     }
    898   }
    899 };
    900 
    901 template <typename NormalMap,
    902           int kArraySize,
    903           typename EqualKey,
    904           typename MapInit>
    905 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
    906   typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
    907   typedef typename param_type::key_type K;
    908   typedef typename param_type::data_type V;
    909   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    910     GetParamSize(sizer, static_cast<int>(p.size()));
    911     typename param_type::const_iterator iter;
    912     for (iter = p.begin(); iter != p.end(); ++iter) {
    913       GetParamSize(sizer, iter->first);
    914       GetParamSize(sizer, iter->second);
    915     }
    916   }
    917   static void Write(base::Pickle* m, const param_type& p) {
    918     WriteParam(m, static_cast<int>(p.size()));
    919     typename param_type::const_iterator iter;
    920     for (iter = p.begin(); iter != p.end(); ++iter) {
    921       WriteParam(m, iter->first);
    922       WriteParam(m, iter->second);
    923     }
    924   }
    925   static bool Read(const base::Pickle* m,
    926                    base::PickleIterator* iter,
    927                    param_type* r) {
    928     int size;
    929     if (!iter->ReadLength(&size))
    930       return false;
    931     for (int i = 0; i < size; ++i) {
    932       K key;
    933       if (!ReadParam(m, iter, &key))
    934         return false;
    935       V& value = (*r)[key];
    936       if (!ReadParam(m, iter, &value))
    937         return false;
    938     }
    939     return true;
    940   }
    941   static void Log(const param_type& p, std::string* l) {
    942     l->append("<base::SmallMap>");
    943   }
    944 };
    945 
    946 template <class P>
    947 struct ParamTraits<std::unique_ptr<P>> {
    948   typedef std::unique_ptr<P> param_type;
    949   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    950     bool valid = !!p;
    951     GetParamSize(sizer, valid);
    952     if (valid)
    953       GetParamSize(sizer, *p);
    954   }
    955   static void Write(base::Pickle* m, const param_type& p) {
    956     bool valid = !!p;
    957     WriteParam(m, valid);
    958     if (valid)
    959       WriteParam(m, *p);
    960   }
    961   static bool Read(const base::Pickle* m,
    962                    base::PickleIterator* iter,
    963                    param_type* r) {
    964     bool valid = false;
    965     if (!ReadParam(m, iter, &valid))
    966       return false;
    967 
    968     if (!valid) {
    969       r->reset();
    970       return true;
    971     }
    972 
    973     param_type temp(new P());
    974     if (!ReadParam(m, iter, temp.get()))
    975       return false;
    976 
    977     r->swap(temp);
    978     return true;
    979   }
    980   static void Log(const param_type& p, std::string* l) {
    981     if (p)
    982       LogParam(*p, l);
    983     else
    984       l->append("NULL");
    985   }
    986 };
    987 
    988 template <class P>
    989 struct ParamTraits<base::Optional<P>> {
    990   typedef base::Optional<P> param_type;
    991   static void GetSize(base::PickleSizer* sizer, const param_type& p) {
    992     const bool is_set = static_cast<bool>(p);
    993     GetParamSize(sizer, is_set);
    994     if (is_set)
    995       GetParamSize(sizer, p.value());
    996   }
    997   static void Write(base::Pickle* m, const param_type& p) {
    998     const bool is_set = static_cast<bool>(p);
    999     WriteParam(m, is_set);
   1000     if (is_set)
   1001       WriteParam(m, p.value());
   1002   }
   1003   static bool Read(const base::Pickle* m,
   1004                    base::PickleIterator* iter,
   1005                    param_type* r) {
   1006     bool is_set = false;
   1007     if (!iter->ReadBool(&is_set))
   1008       return false;
   1009     if (is_set) {
   1010       P value;
   1011       if (!ReadParam(m, iter, &value))
   1012         return false;
   1013       *r = std::move(value);
   1014     }
   1015     return true;
   1016   }
   1017   static void Log(const param_type& p, std::string* l) {
   1018     if (p)
   1019       LogParam(p.value(), l);
   1020     else
   1021       l->append("(unset)");
   1022   }
   1023 };
   1024 
   1025 // IPC types ParamTraits -------------------------------------------------------
   1026 
   1027 // A ChannelHandle is basically a platform-inspecific wrapper around the
   1028 // fact that IPC endpoints are handled specially on POSIX.  See above comments
   1029 // on FileDescriptor for more background.
   1030 template<>
   1031 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
   1032   typedef ChannelHandle param_type;
   1033   static void GetSize(base::PickleSizer* sizer, const param_type& p);
   1034   static void Write(base::Pickle* m, const param_type& p);
   1035   static bool Read(const base::Pickle* m,
   1036                    base::PickleIterator* iter,
   1037                    param_type* r);
   1038   static void Log(const param_type& p, std::string* l);
   1039 };
   1040 
   1041 template <>
   1042 struct IPC_EXPORT ParamTraits<LogData> {
   1043   typedef LogData param_type;
   1044   static void GetSize(base::PickleSizer* sizer, const param_type& p);
   1045   static void Write(base::Pickle* m, const param_type& p);
   1046   static bool Read(const base::Pickle* m,
   1047                    base::PickleIterator* iter,
   1048                    param_type* r);
   1049   static void Log(const param_type& p, std::string* l);
   1050 };
   1051 
   1052 template <>
   1053 struct IPC_EXPORT ParamTraits<Message> {
   1054   static void Write(base::Pickle* m, const Message& p);
   1055   static bool Read(const base::Pickle* m,
   1056                    base::PickleIterator* iter,
   1057                    Message* r);
   1058   static void Log(const Message& p, std::string* l);
   1059 };
   1060 
   1061 // Windows ParamTraits ---------------------------------------------------------
   1062 
   1063 #if defined(OS_WIN)
   1064 template <>
   1065 struct IPC_EXPORT ParamTraits<HANDLE> {
   1066   typedef HANDLE param_type;
   1067   static void GetSize(base::PickleSizer* sizer, const param_type& p);
   1068   static void Write(base::Pickle* m, const param_type& p);
   1069   static bool Read(const base::Pickle* m,
   1070                    base::PickleIterator* iter,
   1071                    param_type* r);
   1072   static void Log(const param_type& p, std::string* l);
   1073 };
   1074 
   1075 template <>
   1076 struct IPC_EXPORT ParamTraits<LOGFONT> {
   1077   typedef LOGFONT param_type;
   1078   static void GetSize(base::PickleSizer* sizer, const param_type& p);
   1079   static void Write(base::Pickle* m, const param_type& p);
   1080   static bool Read(const base::Pickle* m,
   1081                    base::PickleIterator* iter,
   1082                    param_type* r);
   1083   static void Log(const param_type& p, std::string* l);
   1084 };
   1085 
   1086 template <>
   1087 struct IPC_EXPORT ParamTraits<MSG> {
   1088   typedef MSG param_type;
   1089   static void GetSize(base::PickleSizer* sizer, const param_type& p);
   1090   static void Write(base::Pickle* m, const param_type& p);
   1091   static bool Read(const base::Pickle* m,
   1092                    base::PickleIterator* iter,
   1093                    param_type* r);
   1094   static void Log(const param_type& p, std::string* l);
   1095 };
   1096 #endif  // defined(OS_WIN)
   1097 
   1098 //-----------------------------------------------------------------------------
   1099 // Generic message subclasses
   1100 
   1101 // defined in ipc_logging.cc
   1102 IPC_EXPORT void GenerateLogData(const std::string& channel,
   1103                                 const Message& message,
   1104                                 LogData* data, bool get_params);
   1105 
   1106 
   1107 #if defined(IPC_MESSAGE_LOG_ENABLED)
   1108 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
   1109   const std::string& output_params = msg->output_params();
   1110   if (!l->empty() && !output_params.empty())
   1111     l->append(", ");
   1112 
   1113   l->append(output_params);
   1114 }
   1115 
   1116 template <class ReplyParamType>
   1117 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
   1118                                     const Message* msg) {
   1119   if (msg->received_time() != 0) {
   1120     std::string output_params;
   1121     LogParam(reply_params, &output_params);
   1122     msg->set_output_params(output_params);
   1123   }
   1124 }
   1125 
   1126 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
   1127   if (msg->sent_time()) {
   1128     // Don't log the sync message after dispatch, as we don't have the
   1129     // output parameters at that point.  Instead, save its data and log it
   1130     // with the outgoing reply message when it's sent.
   1131     LogData* data = new LogData;
   1132     GenerateLogData("", *msg, data, true);
   1133     msg->set_dont_log();
   1134     reply->set_sync_log_data(data);
   1135   }
   1136 }
   1137 #else
   1138 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
   1139 
   1140 template <class ReplyParamType>
   1141 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
   1142                                     const Message* msg) {}
   1143 
   1144 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
   1145 #endif
   1146 
   1147 }  // namespace IPC
   1148 
   1149 #endif  // IPC_IPC_MESSAGE_UTILS_H_
   1150