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 <algorithm>
      9 #include <map>
     10 #include <set>
     11 #include <string>
     12 #include <vector>
     13 
     14 #include "base/format_macros.h"
     15 #include "base/memory/scoped_vector.h"
     16 #include "base/platform_file.h"
     17 #include "base/strings/string16.h"
     18 #include "base/strings/string_util.h"
     19 #include "base/strings/stringprintf.h"
     20 #include "base/tuple.h"
     21 #include "ipc/ipc_message_start.h"
     22 #include "ipc/ipc_param_traits.h"
     23 #include "ipc/ipc_sync_message.h"
     24 
     25 #if defined(COMPILER_GCC)
     26 // GCC "helpfully" tries to inline template methods in release mode. Except we
     27 // want the majority of the template junk being expanded once in the
     28 // implementation file (and only provide the definitions in
     29 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
     30 // at every call site. Special note: GCC happily accepts the attribute before
     31 // the method declaration, but only acts on it if it is after.
     32 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
     33 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
     34 // the introduced noclone attribute, which will create specialized versions of
     35 // functions/methods when certain types are constant.
     36 // www.gnu.org/software/gcc/gcc-4.5/changes.html
     37 #define IPC_MSG_NOINLINE  __attribute__((noinline, noclone));
     38 #else
     39 #define IPC_MSG_NOINLINE  __attribute__((noinline));
     40 #endif
     41 #elif defined(COMPILER_MSVC)
     42 // MSVC++ doesn't do this.
     43 #define IPC_MSG_NOINLINE
     44 #else
     45 #error "Please add the noinline property for your new compiler here."
     46 #endif
     47 
     48 namespace base {
     49 class DictionaryValue;
     50 class FilePath;
     51 class ListValue;
     52 class NullableString16;
     53 class Time;
     54 class TimeDelta;
     55 class TimeTicks;
     56 struct FileDescriptor;
     57 }
     58 
     59 namespace IPC {
     60 
     61 struct ChannelHandle;
     62 
     63 // -----------------------------------------------------------------------------
     64 // How we send IPC message logs across channels.
     65 struct IPC_EXPORT LogData {
     66   LogData();
     67   ~LogData();
     68 
     69   std::string channel;
     70   int32 routing_id;
     71   uint32 type;  // "User-defined" message type, from ipc_message.h.
     72   std::string flags;
     73   int64 sent;  // Time that the message was sent (i.e. at Send()).
     74   int64 receive;  // Time before it was dispatched (i.e. before calling
     75                   // OnMessageReceived).
     76   int64 dispatch;  // Time after it was dispatched (i.e. after calling
     77                    // OnMessageReceived).
     78   std::string message_name;
     79   std::string params;
     80 };
     81 
     82 //-----------------------------------------------------------------------------
     83 
     84 // A dummy struct to place first just to allow leading commas for all
     85 // members in the macro-generated constructor initializer lists.
     86 struct NoParams {
     87 };
     88 
     89 template <class P>
     90 static inline void WriteParam(Message* m, const P& p) {
     91   typedef typename SimilarTypeTraits<P>::Type Type;
     92   ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
     93 }
     94 
     95 template <class P>
     96 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m,
     97                                                 PickleIterator* iter,
     98                                                 P* p) {
     99   typedef typename SimilarTypeTraits<P>::Type Type;
    100   return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
    101 }
    102 
    103 template <class P>
    104 static inline void LogParam(const P& p, std::string* l) {
    105   typedef typename SimilarTypeTraits<P>::Type Type;
    106   ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
    107 }
    108 
    109 // Primitive ParamTraits -------------------------------------------------------
    110 
    111 template <>
    112 struct ParamTraits<bool> {
    113   typedef bool param_type;
    114   static void Write(Message* m, const param_type& p) {
    115     m->WriteBool(p);
    116   }
    117   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    118     return m->ReadBool(iter, r);
    119   }
    120   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    121 };
    122 
    123 template <>
    124 struct IPC_EXPORT ParamTraits<unsigned char> {
    125   typedef unsigned char param_type;
    126   static void Write(Message* m, const param_type& p);
    127   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    128   static void Log(const param_type& p, std::string* l);
    129 };
    130 
    131 template <>
    132 struct IPC_EXPORT ParamTraits<unsigned short> {
    133   typedef unsigned short param_type;
    134   static void Write(Message* m, const param_type& p);
    135   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    136   static void Log(const param_type& p, std::string* l);
    137 };
    138 
    139 template <>
    140 struct ParamTraits<int> {
    141   typedef int param_type;
    142   static void Write(Message* m, const param_type& p) {
    143     m->WriteInt(p);
    144   }
    145   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    146     return m->ReadInt(iter, r);
    147   }
    148   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    149 };
    150 
    151 template <>
    152 struct ParamTraits<unsigned int> {
    153   typedef unsigned int param_type;
    154   static void Write(Message* m, const param_type& p) {
    155     m->WriteInt(p);
    156   }
    157   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    158     return m->ReadInt(iter, reinterpret_cast<int*>(r));
    159   }
    160   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    161 };
    162 
    163 template <>
    164 struct ParamTraits<long> {
    165   typedef long param_type;
    166   static void Write(Message* m, const param_type& p) {
    167     m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
    168   }
    169   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    170     return m->ReadLong(iter, r);
    171   }
    172   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    173 };
    174 
    175 template <>
    176 struct ParamTraits<unsigned long> {
    177   typedef unsigned long param_type;
    178   static void Write(Message* m, const param_type& p) {
    179     m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
    180   }
    181   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    182     return m->ReadLong(iter, reinterpret_cast<long*>(r));
    183   }
    184   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    185 };
    186 
    187 template <>
    188 struct ParamTraits<long long> {
    189   typedef long long param_type;
    190   static void Write(Message* m, const param_type& p) {
    191     m->WriteInt64(static_cast<int64>(p));
    192   }
    193   static bool Read(const Message* m, PickleIterator* iter,
    194                    param_type* r) {
    195     return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
    196   }
    197   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    198 };
    199 
    200 template <>
    201 struct ParamTraits<unsigned long long> {
    202   typedef unsigned long long param_type;
    203   static void Write(Message* m, const param_type& p) {
    204     m->WriteInt64(p);
    205   }
    206   static bool Read(const Message* m, PickleIterator* iter,
    207                    param_type* r) {
    208     return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
    209   }
    210   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    211 };
    212 
    213 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values.  Clients
    214 // should be sure to check the sanity of these values after receiving them over
    215 // IPC.
    216 template <>
    217 struct IPC_EXPORT ParamTraits<float> {
    218   typedef float param_type;
    219   static void Write(Message* m, const param_type& p);
    220   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    221   static void Log(const param_type& p, std::string* l);
    222 };
    223 
    224 template <>
    225 struct IPC_EXPORT ParamTraits<double> {
    226   typedef double param_type;
    227   static void Write(Message* m, const param_type& p);
    228   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    229   static void Log(const param_type& p, std::string* l);
    230 };
    231 
    232 // STL ParamTraits -------------------------------------------------------------
    233 
    234 template <>
    235 struct ParamTraits<std::string> {
    236   typedef std::string param_type;
    237   static void Write(Message* m, const param_type& p) {
    238     m->WriteString(p);
    239   }
    240   static bool Read(const Message* m, PickleIterator* iter,
    241                    param_type* r) {
    242     return m->ReadString(iter, r);
    243   }
    244   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    245 };
    246 
    247 template <>
    248 struct ParamTraits<std::wstring> {
    249   typedef std::wstring param_type;
    250   static void Write(Message* m, const param_type& p) {
    251     m->WriteWString(p);
    252   }
    253   static bool Read(const Message* m, PickleIterator* iter,
    254                    param_type* r) {
    255     return m->ReadWString(iter, r);
    256   }
    257   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    258 };
    259 
    260 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
    261 // need this trait.
    262 #if !defined(WCHAR_T_IS_UTF16)
    263 template <>
    264 struct ParamTraits<string16> {
    265   typedef string16 param_type;
    266   static void Write(Message* m, const param_type& p) {
    267     m->WriteString16(p);
    268   }
    269   static bool Read(const Message* m, PickleIterator* iter,
    270                    param_type* r) {
    271     return m->ReadString16(iter, r);
    272   }
    273   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    274 };
    275 #endif
    276 
    277 template <>
    278 struct IPC_EXPORT ParamTraits<std::vector<char> > {
    279   typedef std::vector<char> param_type;
    280   static void Write(Message* m, const param_type& p);
    281   static bool Read(const Message*, PickleIterator* iter, param_type* r);
    282   static void Log(const param_type& p, std::string* l);
    283 };
    284 
    285 template <>
    286 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
    287   typedef std::vector<unsigned char> param_type;
    288   static void Write(Message* m, const param_type& p);
    289   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    290   static void Log(const param_type& p, std::string* l);
    291 };
    292 
    293 template <>
    294 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
    295   typedef std::vector<bool> param_type;
    296   static void Write(Message* m, const param_type& p);
    297   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    298   static void Log(const param_type& p, std::string* l);
    299 };
    300 
    301 template <class P>
    302 struct ParamTraits<std::vector<P> > {
    303   typedef std::vector<P> param_type;
    304   static void Write(Message* m, const param_type& p) {
    305     WriteParam(m, static_cast<int>(p.size()));
    306     for (size_t i = 0; i < p.size(); i++)
    307       WriteParam(m, p[i]);
    308   }
    309   static bool Read(const Message* m, PickleIterator* iter,
    310                    param_type* r) {
    311     int size;
    312     // ReadLength() checks for < 0 itself.
    313     if (!m->ReadLength(iter, &size))
    314       return false;
    315     // Resizing beforehand is not safe, see BUG 1006367 for details.
    316     if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
    317       return false;
    318     r->resize(size);
    319     for (int i = 0; i < size; i++) {
    320       if (!ReadParam(m, iter, &(*r)[i]))
    321         return false;
    322     }
    323     return true;
    324   }
    325   static void Log(const param_type& p, std::string* l) {
    326     for (size_t i = 0; i < p.size(); ++i) {
    327       if (i != 0)
    328         l->append(" ");
    329       LogParam((p[i]), l);
    330     }
    331   }
    332 };
    333 
    334 template <class P>
    335 struct ParamTraits<std::set<P> > {
    336   typedef std::set<P> param_type;
    337   static void Write(Message* m, const param_type& p) {
    338     WriteParam(m, static_cast<int>(p.size()));
    339     typename param_type::const_iterator iter;
    340     for (iter = p.begin(); iter != p.end(); ++iter)
    341       WriteParam(m, *iter);
    342   }
    343   static bool Read(const Message* m, PickleIterator* iter,
    344                    param_type* r) {
    345     int size;
    346     if (!m->ReadLength(iter, &size))
    347       return false;
    348     for (int i = 0; i < size; ++i) {
    349       P item;
    350       if (!ReadParam(m, iter, &item))
    351         return false;
    352       r->insert(item);
    353     }
    354     return true;
    355   }
    356   static void Log(const param_type& p, std::string* l) {
    357     l->append("<std::set>");
    358   }
    359 };
    360 
    361 template <class K, class V>
    362 struct ParamTraits<std::map<K, V> > {
    363   typedef std::map<K, V> param_type;
    364   static void Write(Message* m, const param_type& p) {
    365     WriteParam(m, static_cast<int>(p.size()));
    366     typename param_type::const_iterator iter;
    367     for (iter = p.begin(); iter != p.end(); ++iter) {
    368       WriteParam(m, iter->first);
    369       WriteParam(m, iter->second);
    370     }
    371   }
    372   static bool Read(const Message* m, PickleIterator* iter,
    373                    param_type* r) {
    374     int size;
    375     if (!ReadParam(m, iter, &size) || size < 0)
    376       return false;
    377     for (int i = 0; i < size; ++i) {
    378       K k;
    379       if (!ReadParam(m, iter, &k))
    380         return false;
    381       V& value = (*r)[k];
    382       if (!ReadParam(m, iter, &value))
    383         return false;
    384     }
    385     return true;
    386   }
    387   static void Log(const param_type& p, std::string* l) {
    388     l->append("<std::map>");
    389   }
    390 };
    391 
    392 template <class A, class B>
    393 struct ParamTraits<std::pair<A, B> > {
    394   typedef std::pair<A, B> param_type;
    395   static void Write(Message* m, const param_type& p) {
    396     WriteParam(m, p.first);
    397     WriteParam(m, p.second);
    398   }
    399   static bool Read(const Message* m, PickleIterator* iter,
    400                    param_type* r) {
    401     return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
    402   }
    403   static void Log(const param_type& p, std::string* l) {
    404     l->append("(");
    405     LogParam(p.first, l);
    406     l->append(", ");
    407     LogParam(p.second, l);
    408     l->append(")");
    409   }
    410 };
    411 
    412 // Base ParamTraits ------------------------------------------------------------
    413 
    414 template <>
    415 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
    416   typedef base::DictionaryValue param_type;
    417   static void Write(Message* m, const param_type& p);
    418   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    419   static void Log(const param_type& p, std::string* l);
    420 };
    421 
    422 #if defined(OS_POSIX)
    423 // FileDescriptors may be serialised over IPC channels on POSIX. On the
    424 // receiving side, the FileDescriptor is a valid duplicate of the file
    425 // descriptor which was transmitted: *it is not just a copy of the integer like
    426 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
    427 // this case, the receiving end will see a value of -1. *Zero is a valid file
    428 // descriptor*.
    429 //
    430 // The received file descriptor will have the |auto_close| flag set to true. The
    431 // code which handles the message is responsible for taking ownership of it.
    432 // File descriptors are OS resources and must be closed when no longer needed.
    433 //
    434 // When sending a file descriptor, the file descriptor must be valid at the time
    435 // of transmission. Since transmission is not synchronous, one should consider
    436 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
    437 // flag, which causes the file descriptor to be closed after writing.
    438 template<>
    439 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
    440   typedef base::FileDescriptor param_type;
    441   static void Write(Message* m, const param_type& p);
    442   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    443   static void Log(const param_type& p, std::string* l);
    444 };
    445 #endif  // defined(OS_POSIX)
    446 
    447 template <>
    448 struct IPC_EXPORT ParamTraits<base::FilePath> {
    449   typedef base::FilePath param_type;
    450   static void Write(Message* m, const param_type& p);
    451   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    452   static void Log(const param_type& p, std::string* l);
    453 };
    454 
    455 template <>
    456 struct IPC_EXPORT ParamTraits<base::ListValue> {
    457   typedef base::ListValue param_type;
    458   static void Write(Message* m, const param_type& p);
    459   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    460   static void Log(const param_type& p, std::string* l);
    461 };
    462 
    463 template <>
    464 struct IPC_EXPORT ParamTraits<base::NullableString16> {
    465   typedef base::NullableString16 param_type;
    466   static void Write(Message* m, const param_type& p);
    467   static bool Read(const Message* m, PickleIterator* iter,
    468                    param_type* r);
    469   static void Log(const param_type& p, std::string* l);
    470 };
    471 
    472 template <>
    473 struct IPC_EXPORT ParamTraits<base::PlatformFileInfo> {
    474   typedef base::PlatformFileInfo param_type;
    475   static void Write(Message* m, const param_type& p);
    476   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    477   static void Log(const param_type& p, std::string* l);
    478 };
    479 
    480 template <>
    481 struct SimilarTypeTraits<base::PlatformFileError> {
    482   typedef int Type;
    483 };
    484 
    485 #if defined(OS_WIN)
    486 template <>
    487 struct SimilarTypeTraits<HWND> {
    488   typedef HANDLE Type;
    489 };
    490 #endif  // defined(OS_WIN)
    491 
    492 template <>
    493 struct IPC_EXPORT ParamTraits<base::Time> {
    494   typedef base::Time param_type;
    495   static void Write(Message* m, const param_type& p);
    496   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    497   static void Log(const param_type& p, std::string* l);
    498 };
    499 
    500 template <>
    501 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
    502   typedef base::TimeDelta param_type;
    503   static void Write(Message* m, const param_type& p);
    504   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    505   static void Log(const param_type& p, std::string* l);
    506 };
    507 
    508 template <>
    509 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
    510   typedef base::TimeTicks param_type;
    511   static void Write(Message* m, const param_type& p);
    512   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    513   static void Log(const param_type& p, std::string* l);
    514 };
    515 
    516 template <>
    517 struct ParamTraits<Tuple0> {
    518   typedef Tuple0 param_type;
    519   static void Write(Message* m, const param_type& p) {
    520   }
    521   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    522     return true;
    523   }
    524   static void Log(const param_type& p, std::string* l) {
    525   }
    526 };
    527 
    528 template <class A>
    529 struct ParamTraits< Tuple1<A> > {
    530   typedef Tuple1<A> param_type;
    531   static void Write(Message* m, const param_type& p) {
    532     WriteParam(m, p.a);
    533   }
    534   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    535     return ReadParam(m, iter, &r->a);
    536   }
    537   static void Log(const param_type& p, std::string* l) {
    538     LogParam(p.a, l);
    539   }
    540 };
    541 
    542 template <class A, class B>
    543 struct ParamTraits< Tuple2<A, B> > {
    544   typedef Tuple2<A, B> param_type;
    545   static void Write(Message* m, const param_type& p) {
    546     WriteParam(m, p.a);
    547     WriteParam(m, p.b);
    548   }
    549   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    550     return (ReadParam(m, iter, &r->a) &&
    551             ReadParam(m, iter, &r->b));
    552   }
    553   static void Log(const param_type& p, std::string* l) {
    554     LogParam(p.a, l);
    555     l->append(", ");
    556     LogParam(p.b, l);
    557   }
    558 };
    559 
    560 template <class A, class B, class C>
    561 struct ParamTraits< Tuple3<A, B, C> > {
    562   typedef Tuple3<A, B, C> param_type;
    563   static void Write(Message* m, const param_type& p) {
    564     WriteParam(m, p.a);
    565     WriteParam(m, p.b);
    566     WriteParam(m, p.c);
    567   }
    568   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    569     return (ReadParam(m, iter, &r->a) &&
    570             ReadParam(m, iter, &r->b) &&
    571             ReadParam(m, iter, &r->c));
    572   }
    573   static void Log(const param_type& p, std::string* l) {
    574     LogParam(p.a, l);
    575     l->append(", ");
    576     LogParam(p.b, l);
    577     l->append(", ");
    578     LogParam(p.c, l);
    579   }
    580 };
    581 
    582 template <class A, class B, class C, class D>
    583 struct ParamTraits< Tuple4<A, B, C, D> > {
    584   typedef Tuple4<A, B, C, D> param_type;
    585   static void Write(Message* m, const param_type& p) {
    586     WriteParam(m, p.a);
    587     WriteParam(m, p.b);
    588     WriteParam(m, p.c);
    589     WriteParam(m, p.d);
    590   }
    591   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    592     return (ReadParam(m, iter, &r->a) &&
    593             ReadParam(m, iter, &r->b) &&
    594             ReadParam(m, iter, &r->c) &&
    595             ReadParam(m, iter, &r->d));
    596   }
    597   static void Log(const param_type& p, std::string* l) {
    598     LogParam(p.a, l);
    599     l->append(", ");
    600     LogParam(p.b, l);
    601     l->append(", ");
    602     LogParam(p.c, l);
    603     l->append(", ");
    604     LogParam(p.d, l);
    605   }
    606 };
    607 
    608 template <class A, class B, class C, class D, class E>
    609 struct ParamTraits< Tuple5<A, B, C, D, E> > {
    610   typedef Tuple5<A, B, C, D, E> param_type;
    611   static void Write(Message* m, const param_type& p) {
    612     WriteParam(m, p.a);
    613     WriteParam(m, p.b);
    614     WriteParam(m, p.c);
    615     WriteParam(m, p.d);
    616     WriteParam(m, p.e);
    617   }
    618   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    619     return (ReadParam(m, iter, &r->a) &&
    620             ReadParam(m, iter, &r->b) &&
    621             ReadParam(m, iter, &r->c) &&
    622             ReadParam(m, iter, &r->d) &&
    623             ReadParam(m, iter, &r->e));
    624   }
    625   static void Log(const param_type& p, std::string* l) {
    626     LogParam(p.a, l);
    627     l->append(", ");
    628     LogParam(p.b, l);
    629     l->append(", ");
    630     LogParam(p.c, l);
    631     l->append(", ");
    632     LogParam(p.d, l);
    633     l->append(", ");
    634     LogParam(p.e, l);
    635   }
    636 };
    637 
    638 template<class P>
    639 struct ParamTraits<ScopedVector<P> > {
    640   typedef ScopedVector<P> param_type;
    641   static void Write(Message* m, const param_type& p) {
    642     WriteParam(m, static_cast<int>(p.size()));
    643     for (size_t i = 0; i < p.size(); i++)
    644       WriteParam(m, *p[i]);
    645   }
    646   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    647     int size = 0;
    648     if (!m->ReadLength(iter, &size))
    649       return false;
    650     if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
    651       return false;
    652     r->resize(size);
    653     for (int i = 0; i < size; i++) {
    654       (*r)[i] = new P();
    655       if (!ReadParam(m, iter, (*r)[i]))
    656         return false;
    657     }
    658     return true;
    659   }
    660   static void Log(const param_type& p, std::string* l) {
    661     for (size_t i = 0; i < p.size(); ++i) {
    662       if (i != 0)
    663         l->append(" ");
    664       LogParam(*p[i], l);
    665     }
    666   }
    667 };
    668 
    669 // IPC types ParamTraits -------------------------------------------------------
    670 
    671 // A ChannelHandle is basically a platform-inspecific wrapper around the
    672 // fact that IPC endpoints are handled specially on POSIX.  See above comments
    673 // on FileDescriptor for more background.
    674 template<>
    675 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
    676   typedef ChannelHandle param_type;
    677   static void Write(Message* m, const param_type& p);
    678   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    679   static void Log(const param_type& p, std::string* l);
    680 };
    681 
    682 template <>
    683 struct IPC_EXPORT ParamTraits<LogData> {
    684   typedef LogData param_type;
    685   static void Write(Message* m, const param_type& p);
    686   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    687   static void Log(const param_type& p, std::string* l);
    688 };
    689 
    690 template <>
    691 struct IPC_EXPORT ParamTraits<Message> {
    692   static void Write(Message* m, const Message& p);
    693   static bool Read(const Message* m, PickleIterator* iter, Message* r);
    694   static void Log(const Message& p, std::string* l);
    695 };
    696 
    697 // Windows ParamTraits ---------------------------------------------------------
    698 
    699 #if defined(OS_WIN)
    700 template <>
    701 struct IPC_EXPORT ParamTraits<HANDLE> {
    702   typedef HANDLE param_type;
    703   static void Write(Message* m, const param_type& p);
    704   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    705   static void Log(const param_type& p, std::string* l);
    706 };
    707 
    708 template <>
    709 struct IPC_EXPORT ParamTraits<LOGFONT> {
    710   typedef LOGFONT param_type;
    711   static void Write(Message* m, const param_type& p);
    712   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    713   static void Log(const param_type& p, std::string* l);
    714 };
    715 
    716 template <>
    717 struct IPC_EXPORT ParamTraits<MSG> {
    718   typedef MSG param_type;
    719   static void Write(Message* m, const param_type& p);
    720   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    721   static void Log(const param_type& p, std::string* l);
    722 };
    723 #endif  // defined(OS_WIN)
    724 
    725 //-----------------------------------------------------------------------------
    726 // Generic message subclasses
    727 
    728 // Used for asynchronous messages.
    729 template <class ParamType>
    730 class MessageSchema {
    731  public:
    732   typedef ParamType Param;
    733   typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
    734 
    735   static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
    736   static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
    737 };
    738 
    739 // defined in ipc_logging.cc
    740 IPC_EXPORT void GenerateLogData(const std::string& channel,
    741                                 const Message& message,
    742                                 LogData* data, bool get_params);
    743 
    744 
    745 #if defined(IPC_MESSAGE_LOG_ENABLED)
    746 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
    747   const std::string& output_params = msg->output_params();
    748   if (!l->empty() && !output_params.empty())
    749     l->append(", ");
    750 
    751   l->append(output_params);
    752 }
    753 
    754 template <class ReplyParamType>
    755 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
    756                                     const Message* msg) {
    757   if (msg->received_time() != 0) {
    758     std::string output_params;
    759     LogParam(reply_params, &output_params);
    760     msg->set_output_params(output_params);
    761   }
    762 }
    763 
    764 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
    765   if (msg->sent_time()) {
    766     // Don't log the sync message after dispatch, as we don't have the
    767     // output parameters at that point.  Instead, save its data and log it
    768     // with the outgoing reply message when it's sent.
    769     LogData* data = new LogData;
    770     GenerateLogData("", *msg, data, true);
    771     msg->set_dont_log();
    772     reply->set_sync_log_data(data);
    773   }
    774 }
    775 #else
    776 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
    777 
    778 template <class ReplyParamType>
    779 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
    780                                     const Message* msg) {}
    781 
    782 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
    783 #endif
    784 
    785 // This class assumes that its template argument is a RefTuple (a Tuple with
    786 // reference elements). This would go into ipc_message_utils_impl.h, but it is
    787 // also used by chrome_frame.
    788 template <class RefTuple>
    789 class ParamDeserializer : public MessageReplyDeserializer {
    790  public:
    791   explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
    792 
    793   bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
    794     return ReadParam(&msg, &iter, &out_);
    795   }
    796 
    797   RefTuple out_;
    798 };
    799 
    800 // Used for synchronous messages.
    801 template <class SendParamType, class ReplyParamType>
    802 class SyncMessageSchema {
    803  public:
    804   typedef SendParamType SendParam;
    805   typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
    806   typedef ReplyParamType ReplyParam;
    807 
    808   static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
    809   static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
    810   static bool ReadReplyParam(
    811       const Message* msg,
    812       typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
    813 
    814   template<class T, class S, class Method>
    815   static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
    816                                      const Message* msg, T* obj, S* sender,
    817                                      Method func) {
    818     Message* reply = SyncMessage::GenerateReply(msg);
    819     if (ok) {
    820       typename TupleTypes<ReplyParam>::ValueTuple reply_params;
    821       DispatchToMethod(obj, func, send_params, &reply_params);
    822       WriteParam(reply, reply_params);
    823       LogReplyParamsToMessage(reply_params, msg);
    824     } else {
    825       NOTREACHED() << "Error deserializing message " << msg->type();
    826       reply->set_reply_error();
    827     }
    828     sender->Send(reply);
    829     return ok;
    830   }
    831 
    832   template<class T, class Method>
    833   static bool DispatchDelayReplyWithSendParams(bool ok,
    834                                                const SendParam& send_params,
    835                                                const Message* msg, T* obj,
    836                                                Method func) {
    837     Message* reply = SyncMessage::GenerateReply(msg);
    838     if (ok) {
    839       Tuple1<Message&> t = MakeRefTuple(*reply);
    840       ConnectMessageAndReply(msg, reply);
    841       DispatchToMethod(obj, func, send_params, &t);
    842     } else {
    843       NOTREACHED() << "Error deserializing message " << msg->type();
    844       reply->set_reply_error();
    845       obj->Send(reply);
    846     }
    847     return ok;
    848   }
    849 
    850   template<typename TA>
    851   static void WriteReplyParams(Message* reply, TA a) {
    852     ReplyParam p(a);
    853     WriteParam(reply, p);
    854   }
    855 
    856   template<typename TA, typename TB>
    857   static void WriteReplyParams(Message* reply, TA a, TB b) {
    858     ReplyParam p(a, b);
    859     WriteParam(reply, p);
    860   }
    861 
    862   template<typename TA, typename TB, typename TC>
    863   static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
    864     ReplyParam p(a, b, c);
    865     WriteParam(reply, p);
    866   }
    867 
    868   template<typename TA, typename TB, typename TC, typename TD>
    869   static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
    870     ReplyParam p(a, b, c, d);
    871     WriteParam(reply, p);
    872   }
    873 
    874   template<typename TA, typename TB, typename TC, typename TD, typename TE>
    875   static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
    876     ReplyParam p(a, b, c, d, e);
    877     WriteParam(reply, p);
    878   }
    879 };
    880 
    881 }  // namespace IPC
    882 
    883 #endif  // IPC_IPC_MESSAGE_UTILS_H_
    884