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