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     m->WriteFloat(p);
    221   }
    222   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    223     return m->ReadFloat(iter, r);
    224   }
    225   static void Log(const param_type& p, std::string* l);
    226 };
    227 
    228 template <>
    229 struct IPC_EXPORT ParamTraits<double> {
    230   typedef double param_type;
    231   static void Write(Message* m, const param_type& p);
    232   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    233   static void Log(const param_type& p, std::string* l);
    234 };
    235 
    236 // STL ParamTraits -------------------------------------------------------------
    237 
    238 template <>
    239 struct ParamTraits<std::string> {
    240   typedef std::string param_type;
    241   static void Write(Message* m, const param_type& p) {
    242     m->WriteString(p);
    243   }
    244   static bool Read(const Message* m, PickleIterator* iter,
    245                    param_type* r) {
    246     return m->ReadString(iter, r);
    247   }
    248   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    249 };
    250 
    251 template <>
    252 struct ParamTraits<std::wstring> {
    253   typedef std::wstring param_type;
    254   static void Write(Message* m, const param_type& p) {
    255     m->WriteWString(p);
    256   }
    257   static bool Read(const Message* m, PickleIterator* iter,
    258                    param_type* r) {
    259     return m->ReadWString(iter, r);
    260   }
    261   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    262 };
    263 
    264 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
    265 // need this trait.
    266 #if !defined(WCHAR_T_IS_UTF16)
    267 template <>
    268 struct ParamTraits<base::string16> {
    269   typedef base::string16 param_type;
    270   static void Write(Message* m, const param_type& p) {
    271     m->WriteString16(p);
    272   }
    273   static bool Read(const Message* m, PickleIterator* iter,
    274                    param_type* r) {
    275     return m->ReadString16(iter, r);
    276   }
    277   IPC_EXPORT static void Log(const param_type& p, std::string* l);
    278 };
    279 #endif
    280 
    281 template <>
    282 struct IPC_EXPORT ParamTraits<std::vector<char> > {
    283   typedef std::vector<char> param_type;
    284   static void Write(Message* m, const param_type& p);
    285   static bool Read(const Message*, PickleIterator* iter, param_type* r);
    286   static void Log(const param_type& p, std::string* l);
    287 };
    288 
    289 template <>
    290 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
    291   typedef std::vector<unsigned char> param_type;
    292   static void Write(Message* m, const param_type& p);
    293   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    294   static void Log(const param_type& p, std::string* l);
    295 };
    296 
    297 template <>
    298 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
    299   typedef std::vector<bool> param_type;
    300   static void Write(Message* m, const param_type& p);
    301   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    302   static void Log(const param_type& p, std::string* l);
    303 };
    304 
    305 template <class P>
    306 struct ParamTraits<std::vector<P> > {
    307   typedef std::vector<P> param_type;
    308   static void Write(Message* m, const param_type& p) {
    309     WriteParam(m, static_cast<int>(p.size()));
    310     for (size_t i = 0; i < p.size(); i++)
    311       WriteParam(m, p[i]);
    312   }
    313   static bool Read(const Message* m, PickleIterator* iter,
    314                    param_type* r) {
    315     int size;
    316     // ReadLength() checks for < 0 itself.
    317     if (!m->ReadLength(iter, &size))
    318       return false;
    319     // Resizing beforehand is not safe, see BUG 1006367 for details.
    320     if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
    321       return false;
    322     r->resize(size);
    323     for (int i = 0; i < size; i++) {
    324       if (!ReadParam(m, iter, &(*r)[i]))
    325         return false;
    326     }
    327     return true;
    328   }
    329   static void Log(const param_type& p, std::string* l) {
    330     for (size_t i = 0; i < p.size(); ++i) {
    331       if (i != 0)
    332         l->append(" ");
    333       LogParam((p[i]), l);
    334     }
    335   }
    336 };
    337 
    338 template <class P>
    339 struct ParamTraits<std::set<P> > {
    340   typedef std::set<P> param_type;
    341   static void Write(Message* m, const param_type& p) {
    342     WriteParam(m, static_cast<int>(p.size()));
    343     typename param_type::const_iterator iter;
    344     for (iter = p.begin(); iter != p.end(); ++iter)
    345       WriteParam(m, *iter);
    346   }
    347   static bool Read(const Message* m, PickleIterator* iter,
    348                    param_type* r) {
    349     int size;
    350     if (!m->ReadLength(iter, &size))
    351       return false;
    352     for (int i = 0; i < size; ++i) {
    353       P item;
    354       if (!ReadParam(m, iter, &item))
    355         return false;
    356       r->insert(item);
    357     }
    358     return true;
    359   }
    360   static void Log(const param_type& p, std::string* l) {
    361     l->append("<std::set>");
    362   }
    363 };
    364 
    365 template <class K, class V>
    366 struct ParamTraits<std::map<K, V> > {
    367   typedef std::map<K, V> param_type;
    368   static void Write(Message* m, const param_type& p) {
    369     WriteParam(m, static_cast<int>(p.size()));
    370     typename param_type::const_iterator iter;
    371     for (iter = p.begin(); iter != p.end(); ++iter) {
    372       WriteParam(m, iter->first);
    373       WriteParam(m, iter->second);
    374     }
    375   }
    376   static bool Read(const Message* m, PickleIterator* iter,
    377                    param_type* r) {
    378     int size;
    379     if (!ReadParam(m, iter, &size) || size < 0)
    380       return false;
    381     for (int i = 0; i < size; ++i) {
    382       K k;
    383       if (!ReadParam(m, iter, &k))
    384         return false;
    385       V& value = (*r)[k];
    386       if (!ReadParam(m, iter, &value))
    387         return false;
    388     }
    389     return true;
    390   }
    391   static void Log(const param_type& p, std::string* l) {
    392     l->append("<std::map>");
    393   }
    394 };
    395 
    396 template <class A, class B>
    397 struct ParamTraits<std::pair<A, B> > {
    398   typedef std::pair<A, B> param_type;
    399   static void Write(Message* m, const param_type& p) {
    400     WriteParam(m, p.first);
    401     WriteParam(m, p.second);
    402   }
    403   static bool Read(const Message* m, PickleIterator* iter,
    404                    param_type* r) {
    405     return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
    406   }
    407   static void Log(const param_type& p, std::string* l) {
    408     l->append("(");
    409     LogParam(p.first, l);
    410     l->append(", ");
    411     LogParam(p.second, l);
    412     l->append(")");
    413   }
    414 };
    415 
    416 // Base ParamTraits ------------------------------------------------------------
    417 
    418 template <>
    419 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
    420   typedef base::DictionaryValue param_type;
    421   static void Write(Message* m, const param_type& p);
    422   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    423   static void Log(const param_type& p, std::string* l);
    424 };
    425 
    426 #if defined(OS_POSIX)
    427 // FileDescriptors may be serialised over IPC channels on POSIX. On the
    428 // receiving side, the FileDescriptor is a valid duplicate of the file
    429 // descriptor which was transmitted: *it is not just a copy of the integer like
    430 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
    431 // this case, the receiving end will see a value of -1. *Zero is a valid file
    432 // descriptor*.
    433 //
    434 // The received file descriptor will have the |auto_close| flag set to true. The
    435 // code which handles the message is responsible for taking ownership of it.
    436 // File descriptors are OS resources and must be closed when no longer needed.
    437 //
    438 // When sending a file descriptor, the file descriptor must be valid at the time
    439 // of transmission. Since transmission is not synchronous, one should consider
    440 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
    441 // flag, which causes the file descriptor to be closed after writing.
    442 template<>
    443 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
    444   typedef base::FileDescriptor param_type;
    445   static void Write(Message* m, const param_type& p);
    446   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    447   static void Log(const param_type& p, std::string* l);
    448 };
    449 #endif  // defined(OS_POSIX)
    450 
    451 template <>
    452 struct IPC_EXPORT ParamTraits<base::FilePath> {
    453   typedef base::FilePath param_type;
    454   static void Write(Message* m, const param_type& p);
    455   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    456   static void Log(const param_type& p, std::string* l);
    457 };
    458 
    459 template <>
    460 struct IPC_EXPORT ParamTraits<base::ListValue> {
    461   typedef base::ListValue param_type;
    462   static void Write(Message* m, const param_type& p);
    463   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    464   static void Log(const param_type& p, std::string* l);
    465 };
    466 
    467 template <>
    468 struct IPC_EXPORT ParamTraits<base::NullableString16> {
    469   typedef base::NullableString16 param_type;
    470   static void Write(Message* m, const param_type& p);
    471   static bool Read(const Message* m, PickleIterator* iter,
    472                    param_type* r);
    473   static void Log(const param_type& p, std::string* l);
    474 };
    475 
    476 template <>
    477 struct IPC_EXPORT ParamTraits<base::PlatformFileInfo> {
    478   typedef base::PlatformFileInfo param_type;
    479   static void Write(Message* m, const param_type& p);
    480   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    481   static void Log(const param_type& p, std::string* l);
    482 };
    483 
    484 template <>
    485 struct SimilarTypeTraits<base::PlatformFileError> {
    486   typedef int Type;
    487 };
    488 
    489 #if defined(OS_WIN)
    490 template <>
    491 struct SimilarTypeTraits<HWND> {
    492   typedef HANDLE Type;
    493 };
    494 #endif  // defined(OS_WIN)
    495 
    496 template <>
    497 struct IPC_EXPORT ParamTraits<base::Time> {
    498   typedef base::Time param_type;
    499   static void Write(Message* m, const param_type& p);
    500   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    501   static void Log(const param_type& p, std::string* l);
    502 };
    503 
    504 template <>
    505 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
    506   typedef base::TimeDelta param_type;
    507   static void Write(Message* m, const param_type& p);
    508   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    509   static void Log(const param_type& p, std::string* l);
    510 };
    511 
    512 template <>
    513 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
    514   typedef base::TimeTicks param_type;
    515   static void Write(Message* m, const param_type& p);
    516   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    517   static void Log(const param_type& p, std::string* l);
    518 };
    519 
    520 template <>
    521 struct ParamTraits<Tuple0> {
    522   typedef Tuple0 param_type;
    523   static void Write(Message* m, const param_type& p) {
    524   }
    525   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    526     return true;
    527   }
    528   static void Log(const param_type& p, std::string* l) {
    529   }
    530 };
    531 
    532 template <class A>
    533 struct ParamTraits< Tuple1<A> > {
    534   typedef Tuple1<A> param_type;
    535   static void Write(Message* m, const param_type& p) {
    536     WriteParam(m, p.a);
    537   }
    538   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    539     return ReadParam(m, iter, &r->a);
    540   }
    541   static void Log(const param_type& p, std::string* l) {
    542     LogParam(p.a, l);
    543   }
    544 };
    545 
    546 template <class A, class B>
    547 struct ParamTraits< Tuple2<A, B> > {
    548   typedef Tuple2<A, B> param_type;
    549   static void Write(Message* m, const param_type& p) {
    550     WriteParam(m, p.a);
    551     WriteParam(m, p.b);
    552   }
    553   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    554     return (ReadParam(m, iter, &r->a) &&
    555             ReadParam(m, iter, &r->b));
    556   }
    557   static void Log(const param_type& p, std::string* l) {
    558     LogParam(p.a, l);
    559     l->append(", ");
    560     LogParam(p.b, l);
    561   }
    562 };
    563 
    564 template <class A, class B, class C>
    565 struct ParamTraits< Tuple3<A, B, C> > {
    566   typedef Tuple3<A, B, C> param_type;
    567   static void Write(Message* m, const param_type& p) {
    568     WriteParam(m, p.a);
    569     WriteParam(m, p.b);
    570     WriteParam(m, p.c);
    571   }
    572   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    573     return (ReadParam(m, iter, &r->a) &&
    574             ReadParam(m, iter, &r->b) &&
    575             ReadParam(m, iter, &r->c));
    576   }
    577   static void Log(const param_type& p, std::string* l) {
    578     LogParam(p.a, l);
    579     l->append(", ");
    580     LogParam(p.b, l);
    581     l->append(", ");
    582     LogParam(p.c, l);
    583   }
    584 };
    585 
    586 template <class A, class B, class C, class D>
    587 struct ParamTraits< Tuple4<A, B, C, D> > {
    588   typedef Tuple4<A, B, C, D> param_type;
    589   static void Write(Message* m, const param_type& p) {
    590     WriteParam(m, p.a);
    591     WriteParam(m, p.b);
    592     WriteParam(m, p.c);
    593     WriteParam(m, p.d);
    594   }
    595   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    596     return (ReadParam(m, iter, &r->a) &&
    597             ReadParam(m, iter, &r->b) &&
    598             ReadParam(m, iter, &r->c) &&
    599             ReadParam(m, iter, &r->d));
    600   }
    601   static void Log(const param_type& p, std::string* l) {
    602     LogParam(p.a, l);
    603     l->append(", ");
    604     LogParam(p.b, l);
    605     l->append(", ");
    606     LogParam(p.c, l);
    607     l->append(", ");
    608     LogParam(p.d, l);
    609   }
    610 };
    611 
    612 template <class A, class B, class C, class D, class E>
    613 struct ParamTraits< Tuple5<A, B, C, D, E> > {
    614   typedef Tuple5<A, B, C, D, E> param_type;
    615   static void Write(Message* m, const param_type& p) {
    616     WriteParam(m, p.a);
    617     WriteParam(m, p.b);
    618     WriteParam(m, p.c);
    619     WriteParam(m, p.d);
    620     WriteParam(m, p.e);
    621   }
    622   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    623     return (ReadParam(m, iter, &r->a) &&
    624             ReadParam(m, iter, &r->b) &&
    625             ReadParam(m, iter, &r->c) &&
    626             ReadParam(m, iter, &r->d) &&
    627             ReadParam(m, iter, &r->e));
    628   }
    629   static void Log(const param_type& p, std::string* l) {
    630     LogParam(p.a, l);
    631     l->append(", ");
    632     LogParam(p.b, l);
    633     l->append(", ");
    634     LogParam(p.c, l);
    635     l->append(", ");
    636     LogParam(p.d, l);
    637     l->append(", ");
    638     LogParam(p.e, l);
    639   }
    640 };
    641 
    642 template<class P>
    643 struct ParamTraits<ScopedVector<P> > {
    644   typedef ScopedVector<P> param_type;
    645   static void Write(Message* m, const param_type& p) {
    646     WriteParam(m, static_cast<int>(p.size()));
    647     for (size_t i = 0; i < p.size(); i++)
    648       WriteParam(m, *p[i]);
    649   }
    650   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
    651     int size = 0;
    652     if (!m->ReadLength(iter, &size))
    653       return false;
    654     if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
    655       return false;
    656     r->resize(size);
    657     for (int i = 0; i < size; i++) {
    658       (*r)[i] = new P();
    659       if (!ReadParam(m, iter, (*r)[i]))
    660         return false;
    661     }
    662     return true;
    663   }
    664   static void Log(const param_type& p, std::string* l) {
    665     for (size_t i = 0; i < p.size(); ++i) {
    666       if (i != 0)
    667         l->append(" ");
    668       LogParam(*p[i], l);
    669     }
    670   }
    671 };
    672 
    673 // IPC types ParamTraits -------------------------------------------------------
    674 
    675 // A ChannelHandle is basically a platform-inspecific wrapper around the
    676 // fact that IPC endpoints are handled specially on POSIX.  See above comments
    677 // on FileDescriptor for more background.
    678 template<>
    679 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
    680   typedef ChannelHandle param_type;
    681   static void Write(Message* m, const param_type& p);
    682   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    683   static void Log(const param_type& p, std::string* l);
    684 };
    685 
    686 template <>
    687 struct IPC_EXPORT ParamTraits<LogData> {
    688   typedef LogData param_type;
    689   static void Write(Message* m, const param_type& p);
    690   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    691   static void Log(const param_type& p, std::string* l);
    692 };
    693 
    694 template <>
    695 struct IPC_EXPORT ParamTraits<Message> {
    696   static void Write(Message* m, const Message& p);
    697   static bool Read(const Message* m, PickleIterator* iter, Message* r);
    698   static void Log(const Message& p, std::string* l);
    699 };
    700 
    701 // Windows ParamTraits ---------------------------------------------------------
    702 
    703 #if defined(OS_WIN)
    704 template <>
    705 struct IPC_EXPORT ParamTraits<HANDLE> {
    706   typedef HANDLE param_type;
    707   static void Write(Message* m, const param_type& p);
    708   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    709   static void Log(const param_type& p, std::string* l);
    710 };
    711 
    712 template <>
    713 struct IPC_EXPORT ParamTraits<LOGFONT> {
    714   typedef LOGFONT param_type;
    715   static void Write(Message* m, const param_type& p);
    716   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    717   static void Log(const param_type& p, std::string* l);
    718 };
    719 
    720 template <>
    721 struct IPC_EXPORT ParamTraits<MSG> {
    722   typedef MSG param_type;
    723   static void Write(Message* m, const param_type& p);
    724   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
    725   static void Log(const param_type& p, std::string* l);
    726 };
    727 #endif  // defined(OS_WIN)
    728 
    729 //-----------------------------------------------------------------------------
    730 // Generic message subclasses
    731 
    732 // Used for asynchronous messages.
    733 template <class ParamType>
    734 class MessageSchema {
    735  public:
    736   typedef ParamType Param;
    737   typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
    738 
    739   static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
    740   static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
    741 };
    742 
    743 // defined in ipc_logging.cc
    744 IPC_EXPORT void GenerateLogData(const std::string& channel,
    745                                 const Message& message,
    746                                 LogData* data, bool get_params);
    747 
    748 
    749 #if defined(IPC_MESSAGE_LOG_ENABLED)
    750 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
    751   const std::string& output_params = msg->output_params();
    752   if (!l->empty() && !output_params.empty())
    753     l->append(", ");
    754 
    755   l->append(output_params);
    756 }
    757 
    758 template <class ReplyParamType>
    759 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
    760                                     const Message* msg) {
    761   if (msg->received_time() != 0) {
    762     std::string output_params;
    763     LogParam(reply_params, &output_params);
    764     msg->set_output_params(output_params);
    765   }
    766 }
    767 
    768 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
    769   if (msg->sent_time()) {
    770     // Don't log the sync message after dispatch, as we don't have the
    771     // output parameters at that point.  Instead, save its data and log it
    772     // with the outgoing reply message when it's sent.
    773     LogData* data = new LogData;
    774     GenerateLogData("", *msg, data, true);
    775     msg->set_dont_log();
    776     reply->set_sync_log_data(data);
    777   }
    778 }
    779 #else
    780 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
    781 
    782 template <class ReplyParamType>
    783 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
    784                                     const Message* msg) {}
    785 
    786 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
    787 #endif
    788 
    789 // This class assumes that its template argument is a RefTuple (a Tuple with
    790 // reference elements). This would go into ipc_message_utils_impl.h, but it is
    791 // also used by chrome_frame.
    792 template <class RefTuple>
    793 class ParamDeserializer : public MessageReplyDeserializer {
    794  public:
    795   explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
    796 
    797   bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
    798     return ReadParam(&msg, &iter, &out_);
    799   }
    800 
    801   RefTuple out_;
    802 };
    803 
    804 // Used for synchronous messages.
    805 template <class SendParamType, class ReplyParamType>
    806 class SyncMessageSchema {
    807  public:
    808   typedef SendParamType SendParam;
    809   typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
    810   typedef ReplyParamType ReplyParam;
    811 
    812   static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
    813   static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
    814   static bool ReadReplyParam(
    815       const Message* msg,
    816       typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
    817 
    818   template<class T, class S, class Method>
    819   static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
    820                                      const Message* msg, T* obj, S* sender,
    821                                      Method func) {
    822     Message* reply = SyncMessage::GenerateReply(msg);
    823     if (ok) {
    824       typename TupleTypes<ReplyParam>::ValueTuple reply_params;
    825       DispatchToMethod(obj, func, send_params, &reply_params);
    826       WriteParam(reply, reply_params);
    827       LogReplyParamsToMessage(reply_params, msg);
    828     } else {
    829       NOTREACHED() << "Error deserializing message " << msg->type();
    830       reply->set_reply_error();
    831     }
    832     sender->Send(reply);
    833     return ok;
    834   }
    835 
    836   template<class T, class Method>
    837   static bool DispatchDelayReplyWithSendParams(bool ok,
    838                                                const SendParam& send_params,
    839                                                const Message* msg, T* obj,
    840                                                Method func) {
    841     Message* reply = SyncMessage::GenerateReply(msg);
    842     if (ok) {
    843       Tuple1<Message&> t = MakeRefTuple(*reply);
    844       ConnectMessageAndReply(msg, reply);
    845       DispatchToMethod(obj, func, send_params, &t);
    846     } else {
    847       NOTREACHED() << "Error deserializing message " << msg->type();
    848       reply->set_reply_error();
    849       obj->Send(reply);
    850     }
    851     return ok;
    852   }
    853 
    854   template<typename TA>
    855   static void WriteReplyParams(Message* reply, TA a) {
    856     ReplyParam p(a);
    857     WriteParam(reply, p);
    858   }
    859 
    860   template<typename TA, typename TB>
    861   static void WriteReplyParams(Message* reply, TA a, TB b) {
    862     ReplyParam p(a, b);
    863     WriteParam(reply, p);
    864   }
    865 
    866   template<typename TA, typename TB, typename TC>
    867   static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
    868     ReplyParam p(a, b, c);
    869     WriteParam(reply, p);
    870   }
    871 
    872   template<typename TA, typename TB, typename TC, typename TD>
    873   static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
    874     ReplyParam p(a, b, c, d);
    875     WriteParam(reply, p);
    876   }
    877 
    878   template<typename TA, typename TB, typename TC, typename TD, typename TE>
    879   static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
    880     ReplyParam p(a, b, c, d, e);
    881     WriteParam(reply, p);
    882   }
    883 };
    884 
    885 }  // namespace IPC
    886 
    887 #endif  // IPC_IPC_MESSAGE_UTILS_H_
    888