ipc/chromium/src/chrome/common/ipc_message_utils.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2006-2008 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.
     5 #ifndef CHROME_COMMON_IPC_MESSAGE_UTILS_H_
     6 #define CHROME_COMMON_IPC_MESSAGE_UTILS_H_
     8 #include <string>
     9 #include <vector>
    10 #include <map>
    12 #include "base/file_path.h"
    13 #include "base/string_util.h"
    14 #include "base/string16.h"
    15 #include "base/tuple.h"
    16 #include "base/time.h"
    18 #if defined(OS_POSIX)
    19 #include "chrome/common/file_descriptor_set_posix.h"
    20 #endif
    21 #include "chrome/common/ipc_sync_message.h"
    22 #include "chrome/common/transport_dib.h"
    24 namespace IPC {
    26 //-----------------------------------------------------------------------------
    27 // An iterator class for reading the fields contained within a Message.
    29 class MessageIterator {
    30  public:
    31   explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
    32   }
    33   int NextInt() const {
    34     int val;
    35     if (!msg_.ReadInt(&iter_, &val))
    36       NOTREACHED();
    37     return val;
    38   }
    39   intptr_t NextIntPtr() const {
    40     intptr_t val;
    41     if (!msg_.ReadIntPtr(&iter_, &val))
    42       NOTREACHED();
    43     return val;
    44   }
    45   const std::string NextString() const {
    46     std::string val;
    47     if (!msg_.ReadString(&iter_, &val))
    48       NOTREACHED();
    49     return val;
    50   }
    51   const std::wstring NextWString() const {
    52     std::wstring val;
    53     if (!msg_.ReadWString(&iter_, &val))
    54       NOTREACHED();
    55     return val;
    56   }
    57   const void NextData(const char** data, int* length) const {
    58     if (!msg_.ReadData(&iter_, data, length)) {
    59       NOTREACHED();
    60     }
    61   }
    62  private:
    63   const Message& msg_;
    64   mutable void* iter_;
    65 };
    67 //-----------------------------------------------------------------------------
    68 // ParamTraits specializations, etc.
    69 //
    70 // The full set of types ParamTraits is specialized upon contains *possibly*
    71 // repeated types: unsigned long may be uint32_t or size_t, unsigned long long
    72 // may be uint64_t or size_t, nsresult may be uint32_t, and so on.  You can't
    73 // have ParamTraits<unsigned int> *and* ParamTraits<uint32_t> if unsigned int
    74 // is uint32_t -- that's multiple definitions, and you can only have one.
    75 //
    76 // You could use #ifs and macro conditions to avoid duplicates, but they'd be
    77 // hairy: heavily dependent upon OS and compiler author choices, forced to
    78 // address all conflicts by hand.  Happily there's a better way.  The basic
    79 // idea looks like this, where T -> U represents T inheriting from U:
    80 //
    81 // class ParamTraits<P>
    82 // |
    83 // --> class ParamTraits1<P>
    84 //     |
    85 //     --> class ParamTraits2<P>
    86 //         |
    87 //         --> class ParamTraitsN<P> // or however many levels
    88 //
    89 // The default specialization of ParamTraits{M}<P> is an empty class that
    90 // inherits from ParamTraits{M + 1}<P> (or nothing in the base case).
    91 //
    92 // Now partition the set of parameter types into sets without duplicates.
    93 // Assign each set of types to a level M.  Then specialize ParamTraitsM for
    94 // each of those types.  A reference to ParamTraits<P> will consist of some
    95 // number of empty classes inheriting in sequence, ending in a non-empty
    96 // ParamTraits{N}<P>.  It's okay for the parameter types to be duplicative:
    97 // either name of a type will resolve to the same ParamTraits{N}<P>.
    98 //
    99 // The nice thing is that because templates are instantiated lazily, if we
   100 // indeed have uint32_t == unsigned int, say, with the former in level N and
   101 // the latter in M > N, ParamTraitsM<unsigned int> won't be created (as long as
   102 // nobody uses ParamTraitsM<unsigned int>, but why would you), and no duplicate
   103 // code will be compiled or extra symbols generated.  It's as efficient at
   104 // runtime as manually figuring out and avoiding conflicts by #ifs.
   105 //
   106 // The scheme we follow below names the various classes according to the types
   107 // in them, and the number of ParamTraits levels is larger, but otherwise it's
   108 // exactly the above idea.
   109 //
   111 template <class P> struct ParamTraits;
   113 template <class P>
   114 static inline void WriteParam(Message* m, const P& p) {
   115   ParamTraits<P>::Write(m, p);
   116 }
   118 template <class P>
   119 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
   120                                                 P* p) {
   121   return ParamTraits<P>::Read(m, iter, p);
   122 }
   124 template <class P>
   125 static inline void LogParam(const P& p, std::wstring* l) {
   126   ParamTraits<P>::Log(p, l);
   127 }
   129 // Fundamental types.
   131 template <class P>
   132 struct ParamTraitsFundamental {};
   134 template <>
   135 struct ParamTraitsFundamental<bool> {
   136   typedef bool param_type;
   137   static void Write(Message* m, const param_type& p) {
   138     m->WriteBool(p);
   139   }
   140   static bool Read(const Message* m, void** iter, param_type* r) {
   141     return m->ReadBool(iter, r);
   142   }
   143   static void Log(const param_type& p, std::wstring* l) {
   144     l->append(p ? L"true" : L"false");
   145   }
   146 };
   148 template <>
   149 struct ParamTraitsFundamental<int> {
   150   typedef int param_type;
   151   static void Write(Message* m, const param_type& p) {
   152     m->WriteInt(p);
   153   }
   154   static bool Read(const Message* m, void** iter, param_type* r) {
   155     return m->ReadInt(iter, r);
   156   }
   157   static void Log(const param_type& p, std::wstring* l) {
   158     l->append(StringPrintf(L"%d", p));
   159   }
   160 };
   162 template <>
   163 struct ParamTraitsFundamental<long> {
   164   typedef long param_type;
   165   static void Write(Message* m, const param_type& p) {
   166     m->WriteLong(p);
   167   }
   168   static bool Read(const Message* m, void** iter, param_type* r) {
   169     return m->ReadLong(iter, r);
   170   }
   171   static void Log(const param_type& p, std::wstring* l) {
   172     l->append(StringPrintf(L"%l", p));
   173   }
   174 };
   176 template <>
   177 struct ParamTraitsFundamental<unsigned long> {
   178   typedef unsigned long param_type;
   179   static void Write(Message* m, const param_type& p) {
   180     m->WriteULong(p);
   181   }
   182   static bool Read(const Message* m, void** iter, param_type* r) {
   183     return m->ReadULong(iter, r);
   184   }
   185   static void Log(const param_type& p, std::wstring* l) {
   186     l->append(StringPrintf(L"%ul", p));
   187   }
   188 };
   190 template <>
   191 struct ParamTraitsFundamental<long long> {
   192   typedef long long param_type;
   193   static void Write(Message* m, const param_type& p) {
   194     m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
   195  }
   196   static bool Read(const Message* m, void** iter, param_type* r) {
   197     const char *data;
   198     int data_size = 0;
   199     bool result = m->ReadData(iter, &data, &data_size);
   200     if (result && data_size == sizeof(param_type)) {
   201       memcpy(r, data, sizeof(param_type));
   202     } else {
   203       result = false;
   204       NOTREACHED();
   205     }
   206     return result;
   207   }
   208   static void Log(const param_type& p, std::wstring* l) {
   209     l->append(StringPrintf(L"%ll", p));
   210   }
   211 };
   213 template <>
   214 struct ParamTraitsFundamental<unsigned long long> {
   215   typedef unsigned long long param_type;
   216   static void Write(Message* m, const param_type& p) {
   217     m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
   218  }
   219   static bool Read(const Message* m, void** iter, param_type* r) {
   220     const char *data;
   221     int data_size = 0;
   222     bool result = m->ReadData(iter, &data, &data_size);
   223     if (result && data_size == sizeof(param_type)) {
   224       memcpy(r, data, sizeof(param_type));
   225     } else {
   226       result = false;
   227       NOTREACHED();
   228     }
   229     return result;
   230   }
   231   static void Log(const param_type& p, std::wstring* l) {
   232     l->append(StringPrintf(L"%ull", p));
   233   }
   234 };
   236 template <>
   237 struct ParamTraitsFundamental<double> {
   238   typedef double param_type;
   239   static void Write(Message* m, const param_type& p) {
   240     m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
   241   }
   242   static bool Read(const Message* m, void** iter, param_type* r) {
   243     const char *data;
   244     int data_size = 0;
   245     bool result = m->ReadData(iter, &data, &data_size);
   246     if (result && data_size == sizeof(param_type)) {
   247       memcpy(r, data, sizeof(param_type));
   248     } else {
   249       result = false;
   250       NOTREACHED();
   251     }
   253     return result;
   254   }
   255   static void Log(const param_type& p, std::wstring* l) {
   256     l->append(StringPrintf(L"e", p));
   257   }
   258 };
   260 // Fixed-size <stdint.h> types.
   262 template <class P>
   263 struct ParamTraitsFixed : ParamTraitsFundamental<P> {};
   265 template <>
   266 struct ParamTraitsFixed<int16_t> {
   267   typedef int16_t param_type;
   268   static void Write(Message* m, const param_type& p) {
   269     m->WriteInt16(p);
   270   }
   271   static bool Read(const Message* m, void** iter, param_type* r) {
   272     return m->ReadInt16(iter, r);
   273   }
   274   static void Log(const param_type& p, std::wstring* l) {
   275     l->append(StringPrintf(L"%hd", p));
   276   }
   277 };
   279 template <>
   280 struct ParamTraitsFixed<uint16_t> {
   281   typedef uint16_t param_type;
   282   static void Write(Message* m, const param_type& p) {
   283     m->WriteUInt16(p);
   284   }
   285   static bool Read(const Message* m, void** iter, param_type* r) {
   286     return m->ReadUInt16(iter, r);
   287   }
   288   static void Log(const param_type& p, std::wstring* l) {
   289     l->append(StringPrintf(L"%hu", p));
   290   }
   291 };
   293 template <>
   294 struct ParamTraitsFixed<uint32_t> {
   295   typedef uint32_t param_type;
   296   static void Write(Message* m, const param_type& p) {
   297     m->WriteUInt32(p);
   298   }
   299   static bool Read(const Message* m, void** iter, param_type* r) {
   300     return m->ReadUInt32(iter, r);
   301   }
   302   static void Log(const param_type& p, std::wstring* l) {
   303     l->append(StringPrintf(L"%u", p));
   304   }
   305 };
   307 template <>
   308 struct ParamTraitsFixed<int64_t> {
   309   typedef int64_t param_type;
   310   static void Write(Message* m, const param_type& p) {
   311     m->WriteInt64(p);
   312   }
   313   static bool Read(const Message* m, void** iter, param_type* r) {
   314     return m->ReadInt64(iter, r);
   315   }
   316   static void Log(const param_type& p, std::wstring* l) {
   317     l->append(StringPrintf(L"%" PRId64L, p));
   318   }
   319 };
   321 template <>
   322 struct ParamTraitsFixed<uint64_t> {
   323   typedef uint64_t param_type;
   324   static void Write(Message* m, const param_type& p) {
   325     m->WriteInt64(static_cast<int64_t>(p));
   326   }
   327   static bool Read(const Message* m, void** iter, param_type* r) {
   328     return m->ReadInt64(iter, reinterpret_cast<int64_t*>(r));
   329   }
   330   static void Log(const param_type& p, std::wstring* l) {
   331     l->append(StringPrintf(L"%" PRIu64L, p));
   332   }
   333 };
   335 // Other standard C types.
   337 template <class P>
   338 struct ParamTraitsLibC : ParamTraitsFixed<P> {};
   340 template <>
   341 struct ParamTraitsLibC<size_t> {
   342   typedef size_t param_type;
   343   static void Write(Message* m, const param_type& p) {
   344     m->WriteSize(p);
   345   }
   346   static bool Read(const Message* m, void** iter, param_type* r) {
   347     return m->ReadSize(iter, r);
   348   }
   349   static void Log(const param_type& p, std::wstring* l) {
   350     l->append(StringPrintf(L"%u", p));
   351   }
   352 };
   354 // std::* types.
   356 template <class P>
   357 struct ParamTraitsStd : ParamTraitsLibC<P> {};
   359 template <>
   360 struct ParamTraitsStd<std::string> {
   361   typedef std::string param_type;
   362   static void Write(Message* m, const param_type& p) {
   363     m->WriteString(p);
   364   }
   365   static bool Read(const Message* m, void** iter, param_type* r) {
   366     return m->ReadString(iter, r);
   367   }
   368   static void Log(const param_type& p, std::wstring* l) {
   369     l->append(UTF8ToWide(p));
   370   }
   371 };
   373 template <>
   374 struct ParamTraitsStd<std::wstring> {
   375   typedef std::wstring param_type;
   376   static void Write(Message* m, const param_type& p) {
   377     m->WriteWString(p);
   378   }
   379   static bool Read(const Message* m, void** iter, param_type* r) {
   380     return m->ReadWString(iter, r);
   381   }
   382   static void Log(const param_type& p, std::wstring* l) {
   383     l->append(p);
   384   }
   385 };
   387 template <>
   388 struct ParamTraitsStd<std::vector<unsigned char> > {
   389   typedef std::vector<unsigned char> param_type;
   390   static void Write(Message* m, const param_type& p) {
   391     if (p.size() == 0) {
   392       m->WriteData(NULL, 0);
   393     } else {
   394       m->WriteData(reinterpret_cast<const char*>(&p.front()),
   395                    static_cast<int>(p.size()));
   396     }
   397   }
   398   static bool Read(const Message* m, void** iter, param_type* r) {
   399     const char *data;
   400     int data_size = 0;
   401     if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
   402       return false;
   403     r->resize(data_size);
   404     if (data_size)
   405       memcpy(&r->front(), data, data_size);
   406     return true;
   407   }
   408   static void Log(const param_type& p, std::wstring* l) {
   409     for (size_t i = 0; i < p.size(); ++i)
   410       l->push_back(p[i]);
   411   }
   412 };
   414 template <>
   415 struct ParamTraitsStd<std::vector<char> > {
   416   typedef std::vector<char> param_type;
   417   static void Write(Message* m, const param_type& p) {
   418     if (p.size() == 0) {
   419       m->WriteData(NULL, 0);
   420     } else {
   421       m->WriteData(&p.front(), static_cast<int>(p.size()));
   422     }
   423   }
   424   static bool Read(const Message* m, void** iter, param_type* r) {
   425     const char *data;
   426     int data_size = 0;
   427     if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
   428       return false;
   429     r->resize(data_size);
   430     if (data_size)
   431       memcpy(&r->front(), data, data_size);
   432     return true;
   433   }
   434   static void Log(const param_type& p, std::wstring* l) {
   435     for (size_t i = 0; i < p.size(); ++i)
   436       l->push_back(p[i]);
   437   }
   438 };
   440 template <class P>
   441 struct ParamTraitsStd<std::vector<P> > {
   442   typedef std::vector<P> param_type;
   443   static void Write(Message* m, const param_type& p) {
   444     WriteParam(m, static_cast<int>(p.size()));
   445     for (size_t i = 0; i < p.size(); i++)
   446       WriteParam(m, p[i]);
   447   }
   448   static bool Read(const Message* m, void** iter, param_type* r) {
   449     int size;
   450     if (!m->ReadLength(iter, &size))
   451       return false;
   452     // Resizing beforehand is not safe, see BUG 1006367 for details.
   453     if (m->IteratorHasRoomFor(*iter, size * sizeof(P))) {
   454       r->resize(size);
   455       for (int i = 0; i < size; i++) {
   456         if (!ReadParam(m, iter, &(*r)[i]))
   457           return false;
   458       }
   459     } else {
   460       for (int i = 0; i < size; i++) {
   461         P element;
   462         if (!ReadParam(m, iter, &element))
   463           return false;
   464         r->push_back(element);
   465       }
   466     }
   467     return true;
   468   }
   469   static void Log(const param_type& p, std::wstring* l) {
   470     for (size_t i = 0; i < p.size(); ++i) {
   471       if (i != 0)
   472         l->append(L" ");
   474       LogParam((p[i]), l);
   475     }
   476   }
   477 };
   479 template <class K, class V>
   480 struct ParamTraitsStd<std::map<K, V> > {
   481   typedef std::map<K, V> param_type;
   482   static void Write(Message* m, const param_type& p) {
   483     WriteParam(m, static_cast<int>(p.size()));
   484     typename param_type::const_iterator iter;
   485     for (iter = p.begin(); iter != p.end(); ++iter) {
   486       WriteParam(m, iter->first);
   487       WriteParam(m, iter->second);
   488     }
   489   }
   490   static bool Read(const Message* m, void** iter, param_type* r) {
   491     int size;
   492     if (!ReadParam(m, iter, &size) || size < 0)
   493       return false;
   494     for (int i = 0; i < size; ++i) {
   495       K k;
   496       if (!ReadParam(m, iter, &k))
   497         return false;
   498       V& value = (*r)[k];
   499       if (!ReadParam(m, iter, &value))
   500         return false;
   501     }
   502     return true;
   503   }
   504   static void Log(const param_type& p, std::wstring* l) {
   505     l->append(L"<std::map>");
   506   }
   507 };
   509 // Windows-specific types.
   511 template <class P>
   512 struct ParamTraitsWindows : ParamTraitsStd<P> {};
   514 #if defined(OS_WIN)
   515 template <>
   516 struct ParamTraitsWindows<LOGFONT> {
   517   typedef LOGFONT param_type;
   518   static void Write(Message* m, const param_type& p) {
   519     m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
   520   }
   521   static bool Read(const Message* m, void** iter, param_type* r) {
   522     const char *data;
   523     int data_size = 0;
   524     bool result = m->ReadData(iter, &data, &data_size);
   525     if (result && data_size == sizeof(LOGFONT)) {
   526       memcpy(r, data, sizeof(LOGFONT));
   527     } else {
   528       result = false;
   529       NOTREACHED();
   530     }
   532     return result;
   533   }
   534   static void Log(const param_type& p, std::wstring* l) {
   535     l->append(StringPrintf(L"<LOGFONT>"));
   536   }
   537 };
   539 template <>
   540 struct ParamTraitsWindows<MSG> {
   541   typedef MSG param_type;
   542   static void Write(Message* m, const param_type& p) {
   543     m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
   544   }
   545   static bool Read(const Message* m, void** iter, param_type* r) {
   546     const char *data;
   547     int data_size = 0;
   548     bool result = m->ReadData(iter, &data, &data_size);
   549     if (result && data_size == sizeof(MSG)) {
   550       memcpy(r, data, sizeof(MSG));
   551     } else {
   552       result = false;
   553       NOTREACHED();
   554     }
   556     return result;
   557   }
   558 };
   560 template <>
   561 struct ParamTraitsWindows<HANDLE> {
   562   typedef HANDLE param_type;
   563   static void Write(Message* m, const param_type& p) {
   564     m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
   565   }
   566   static bool Read(const Message* m, void** iter, param_type* r) {
   567     DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
   568     return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
   569   }
   570   static void Log(const param_type& p, std::wstring* l) {
   571     l->append(StringPrintf(L"0x%X", p));
   572   }
   573 };
   575 template <>
   576 struct ParamTraitsWindows<HCURSOR> {
   577   typedef HCURSOR param_type;
   578   static void Write(Message* m, const param_type& p) {
   579     m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
   580   }
   581   static bool Read(const Message* m, void** iter, param_type* r) {
   582     DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
   583     return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
   584   }
   585   static void Log(const param_type& p, std::wstring* l) {
   586     l->append(StringPrintf(L"0x%X", p));
   587   }
   588 };
   590 template <>
   591 struct ParamTraitsWindows<HWND> {
   592   typedef HWND param_type;
   593   static void Write(Message* m, const param_type& p) {
   594     m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
   595   }
   596   static bool Read(const Message* m, void** iter, param_type* r) {
   597     DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
   598     return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
   599   }
   600   static void Log(const param_type& p, std::wstring* l) {
   601     l->append(StringPrintf(L"0x%X", p));
   602   }
   603 };
   605 template <>
   606 struct ParamTraitsWindows<HACCEL> {
   607   typedef HACCEL param_type;
   608   static void Write(Message* m, const param_type& p) {
   609     m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
   610   }
   611   static bool Read(const Message* m, void** iter, param_type* r) {
   612     DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
   613     return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
   614   }
   615 };
   617 template <>
   618 struct ParamTraitsWindows<POINT> {
   619   typedef POINT param_type;
   620   static void Write(Message* m, const param_type& p) {
   621     m->WriteInt(p.x);
   622     m->WriteInt(p.y);
   623   }
   624   static bool Read(const Message* m, void** iter, param_type* r) {
   625     int x, y;
   626     if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
   627       return false;
   628     r->x = x;
   629     r->y = y;
   630     return true;
   631   }
   632   static void Log(const param_type& p, std::wstring* l) {
   633     l->append(StringPrintf(L"(%d, %d)", p.x, p.y));
   634   }
   635 };
   637 template <>
   638 struct ParamTraitsWindows<XFORM> {
   639   typedef XFORM param_type;
   640   static void Write(Message* m, const param_type& p) {
   641     m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
   642   }
   643   static bool Read(const Message* m, void** iter, param_type* r) {
   644     const char *data;
   645     int data_size = 0;
   646     bool result = m->ReadData(iter, &data, &data_size);
   647     if (result && data_size == sizeof(XFORM)) {
   648       memcpy(r, data, sizeof(XFORM));
   649     } else {
   650       result = false;
   651       NOTREACHED();
   652     }
   654     return result;
   655   }
   656   static void Log(const param_type& p, std::wstring* l) {
   657     l->append(L"<XFORM>");
   658   }
   659 };
   660 #endif  // defined(OS_WIN)
   662 // Various ipc/chromium types.
   664 template <class P>
   665 struct ParamTraitsIPC : ParamTraitsWindows<P> {};
   667 template <>
   668 struct ParamTraitsIPC<base::Time> {
   669   typedef base::Time param_type;
   670   static inline void Write(Message* m, const param_type& p);
   671   static inline bool Read(const Message* m, void** iter, param_type* r);
   672   static inline void Log(const param_type& p, std::wstring* l);
   673 };
   675 #if defined(OS_POSIX)
   676 // FileDescriptors may be serialised over IPC channels on POSIX. On the
   677 // receiving side, the FileDescriptor is a valid duplicate of the file
   678 // descriptor which was transmitted: *it is not just a copy of the integer like
   679 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
   680 // this case, the receiving end will see a value of -1. *Zero is a valid file
   681 // descriptor*.
   682 //
   683 // The received file descriptor will have the |auto_close| flag set to true. The
   684 // code which handles the message is responsible for taking ownership of it.
   685 // File descriptors are OS resources and must be closed when no longer needed.
   686 //
   687 // When sending a file descriptor, the file descriptor must be valid at the time
   688 // of transmission. Since transmission is not synchronous, one should consider
   689 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
   690 // flag, which causes the file descriptor to be closed after writing.
   691 template<>
   692 struct ParamTraitsIPC<base::FileDescriptor> {
   693   typedef base::FileDescriptor param_type;
   694   static void Write(Message* m, const param_type& p) {
   695     const bool valid = p.fd >= 0;
   696     WriteParam(m, valid);
   698     if (valid) {
   699       if (!m->WriteFileDescriptor(p)) {
   700         NOTREACHED() << "Too many file descriptors for one message!";
   701       }
   702     }
   703   }
   704   static bool Read(const Message* m, void** iter, param_type* r) {
   705     bool valid;
   706     if (!ReadParam(m, iter, &valid))
   707       return false;
   709     if (!valid) {
   710       r->fd = -1;
   711       r->auto_close = false;
   712       return true;
   713     }
   715     return m->ReadFileDescriptor(iter, r);
   716   }
   717   static void Log(const param_type& p, std::wstring* l) {
   718     if (p.auto_close) {
   719       l->append(StringPrintf(L"FD(%d auto-close)", p.fd));
   720     } else {
   721       l->append(StringPrintf(L"FD(%d)", p.fd));
   722     }
   723   }
   724 };
   725 #endif // defined(OS_POSIX)
   727 template <>
   728 struct ParamTraitsIPC<FilePath> {
   729   typedef FilePath param_type;
   730   static void Write(Message* m, const param_type& p);
   731   static bool Read(const Message* m, void** iter, param_type* r);
   732   static void Log(const param_type& p, std::wstring* l);
   733 };
   735 struct LogData {
   736   std::wstring channel;
   737   int32_t routing_id;
   738   uint16_t type;
   739   std::wstring flags;
   740   int64_t sent;  // Time that the message was sent (i.e. at Send()).
   741   int64_t receive;  // Time before it was dispatched (i.e. before calling
   742                   // OnMessageReceived).
   743   int64_t dispatch;  // Time after it was dispatched (i.e. after calling
   744                    // OnMessageReceived).
   745   std::wstring message_name;
   746   std::wstring params;
   747 };
   749 template <>
   750 struct ParamTraitsIPC<LogData> {
   751   typedef LogData param_type;
   752   static void Write(Message* m, const param_type& p) {
   753     WriteParam(m, p.channel);
   754     WriteParam(m, p.routing_id);
   755     WriteParam(m, static_cast<int>(p.type));
   756     WriteParam(m, p.flags);
   757     WriteParam(m, p.sent);
   758     WriteParam(m, p.receive);
   759     WriteParam(m, p.dispatch);
   760     WriteParam(m, p.params);
   761   }
   762   static bool Read(const Message* m, void** iter, param_type* r) {
   763     int type = 0;
   764     bool result =
   765       ReadParam(m, iter, &r->channel) &&
   766       ReadParam(m, iter, &r->routing_id) &&
   767       ReadParam(m, iter, &type) &&
   768       ReadParam(m, iter, &r->flags) &&
   769       ReadParam(m, iter, &r->sent) &&
   770       ReadParam(m, iter, &r->receive) &&
   771       ReadParam(m, iter, &r->dispatch) &&
   772       ReadParam(m, iter, &r->params);
   773     r->type = static_cast<uint16_t>(type);
   774     return result;
   775   }
   776   static void Log(const param_type& p, std::wstring* l) {
   777     // Doesn't make sense to implement this!
   778   }
   779 };
   781 #if defined(OS_WIN)
   782 template<>
   783 struct ParamTraitsIPC<TransportDIB::Id> {
   784   typedef TransportDIB::Id param_type;
   785   static void Write(Message* m, const param_type& p) {
   786     WriteParam(m, p.handle);
   787     WriteParam(m, p.sequence_num);
   788   }
   789   static bool Read(const Message* m, void** iter, param_type* r) {
   790     return (ReadParam(m, iter, &r->handle) &&
   791             ReadParam(m, iter, &r->sequence_num));
   792   }
   793   static void Log(const param_type& p, std::wstring* l) {
   794     l->append(L"TransportDIB(");
   795     LogParam(p.handle, l);
   796     l->append(L", ");
   797     LogParam(p.sequence_num, l);
   798     l->append(L")");
   799   }
   800 };
   801 #endif
   803 template <>
   804 struct ParamTraitsIPC<Message> {
   805   static void Write(Message* m, const Message& p) {
   806     m->WriteInt(p.size());
   807     m->WriteData(reinterpret_cast<const char*>(p.data()), p.size());
   808   }
   809   static bool Read(const Message* m, void** iter, Message* r) {
   810     int size;
   811     if (!m->ReadInt(iter, &size))
   812       return false;
   813     const char* data;
   814     if (!m->ReadData(iter, &data, &size))
   815       return false;
   816     *r = Message(data, size);
   817     return true;
   818   }
   819   static void Log(const Message& p, std::wstring* l) {
   820     l->append(L"<IPC::Message>");
   821   }
   822 };
   824 template <>
   825 struct ParamTraitsIPC<Tuple0> {
   826   typedef Tuple0 param_type;
   827   static void Write(Message* m, const param_type& p) {
   828   }
   829   static bool Read(const Message* m, void** iter, param_type* r) {
   830     return true;
   831   }
   832   static void Log(const param_type& p, std::wstring* l) {
   833   }
   834 };
   836 template <class A>
   837 struct ParamTraitsIPC< Tuple1<A> > {
   838   typedef Tuple1<A> param_type;
   839   static void Write(Message* m, const param_type& p) {
   840     WriteParam(m, p.a);
   841   }
   842   static bool Read(const Message* m, void** iter, param_type* r) {
   843     return ReadParam(m, iter, &r->a);
   844   }
   845   static void Log(const param_type& p, std::wstring* l) {
   846     LogParam(p.a, l);
   847   }
   848 };
   850 template <class A, class B>
   851 struct ParamTraitsIPC< Tuple2<A, B> > {
   852   typedef Tuple2<A, B> param_type;
   853   static void Write(Message* m, const param_type& p) {
   854     WriteParam(m, p.a);
   855     WriteParam(m, p.b);
   856   }
   857   static bool Read(const Message* m, void** iter, param_type* r) {
   858     return (ReadParam(m, iter, &r->a) &&
   859             ReadParam(m, iter, &r->b));
   860   }
   861   static void Log(const param_type& p, std::wstring* l) {
   862     LogParam(p.a, l);
   863     l->append(L", ");
   864     LogParam(p.b, l);
   865   }
   866 };
   868 template <class A, class B, class C>
   869 struct ParamTraitsIPC< Tuple3<A, B, C> > {
   870   typedef Tuple3<A, B, C> param_type;
   871   static void Write(Message* m, const param_type& p) {
   872     WriteParam(m, p.a);
   873     WriteParam(m, p.b);
   874     WriteParam(m, p.c);
   875   }
   876   static bool Read(const Message* m, void** iter, param_type* r) {
   877     return (ReadParam(m, iter, &r->a) &&
   878             ReadParam(m, iter, &r->b) &&
   879             ReadParam(m, iter, &r->c));
   880   }
   881   static void Log(const param_type& p, std::wstring* l) {
   882     LogParam(p.a, l);
   883     l->append(L", ");
   884     LogParam(p.b, l);
   885     l->append(L", ");
   886     LogParam(p.c, l);
   887   }
   888 };
   890 template <class A, class B, class C, class D>
   891 struct ParamTraitsIPC< Tuple4<A, B, C, D> > {
   892   typedef Tuple4<A, B, C, D> param_type;
   893   static void Write(Message* m, const param_type& p) {
   894     WriteParam(m, p.a);
   895     WriteParam(m, p.b);
   896     WriteParam(m, p.c);
   897     WriteParam(m, p.d);
   898   }
   899   static bool Read(const Message* m, void** iter, param_type* r) {
   900     return (ReadParam(m, iter, &r->a) &&
   901             ReadParam(m, iter, &r->b) &&
   902             ReadParam(m, iter, &r->c) &&
   903             ReadParam(m, iter, &r->d));
   904   }
   905   static void Log(const param_type& p, std::wstring* l) {
   906     LogParam(p.a, l);
   907     l->append(L", ");
   908     LogParam(p.b, l);
   909     l->append(L", ");
   910     LogParam(p.c, l);
   911     l->append(L", ");
   912     LogParam(p.d, l);
   913   }
   914 };
   916 template <class A, class B, class C, class D, class E>
   917 struct ParamTraitsIPC< Tuple5<A, B, C, D, E> > {
   918   typedef Tuple5<A, B, C, D, E> param_type;
   919   static void Write(Message* m, const param_type& p) {
   920     WriteParam(m, p.a);
   921     WriteParam(m, p.b);
   922     WriteParam(m, p.c);
   923     WriteParam(m, p.d);
   924     WriteParam(m, p.e);
   925   }
   926   static bool Read(const Message* m, void** iter, param_type* r) {
   927     return (ReadParam(m, iter, &r->a) &&
   928             ReadParam(m, iter, &r->b) &&
   929             ReadParam(m, iter, &r->c) &&
   930             ReadParam(m, iter, &r->d) &&
   931             ReadParam(m, iter, &r->e));
   932   }
   933   static void Log(const param_type& p, std::wstring* l) {
   934     LogParam(p.a, l);
   935     l->append(L", ");
   936     LogParam(p.b, l);
   937     l->append(L", ");
   938     LogParam(p.c, l);
   939     l->append(L", ");
   940     LogParam(p.d, l);
   941     l->append(L", ");
   942     LogParam(p.e, l);
   943   }
   944 };
   946 template <class A, class B, class C, class D, class E, class F>
   947 struct ParamTraitsIPC< Tuple6<A, B, C, D, E, F> > {
   948   typedef Tuple6<A, B, C, D, E, F> param_type;
   949   static void Write(Message* m, const param_type& p) {
   950     WriteParam(m, p.a);
   951     WriteParam(m, p.b);
   952     WriteParam(m, p.c);
   953     WriteParam(m, p.d);
   954     WriteParam(m, p.e);
   955     WriteParam(m, p.f);
   956   }
   957   static bool Read(const Message* m, void** iter, param_type* r) {
   958     return (ReadParam(m, iter, &r->a) &&
   959             ReadParam(m, iter, &r->b) &&
   960             ReadParam(m, iter, &r->c) &&
   961             ReadParam(m, iter, &r->d) &&
   962             ReadParam(m, iter, &r->e) &&
   963             ReadParam(m, iter, &r->f));
   964   }
   965   static void Log(const param_type& p, std::wstring* l) {
   966     LogParam(p.a, l);
   967     l->append(L", ");
   968     LogParam(p.b, l);
   969     l->append(L", ");
   970     LogParam(p.c, l);
   971     l->append(L", ");
   972     LogParam(p.d, l);
   973     l->append(L", ");
   974     LogParam(p.e, l);
   975     l->append(L", ");
   976     LogParam(p.f, l);
   977   }
   978 };
   980 // Mozilla-specific types.
   982 template <class P>
   983 struct ParamTraitsMozilla : ParamTraitsIPC<P> {};
   985 template <>
   986 struct ParamTraitsMozilla<nsresult> {
   987   typedef nsresult param_type;
   988   static void Write(Message* m, const param_type& p) {
   989     m->WriteUInt32(static_cast<uint32_t>(p));
   990   }
   991   static bool Read(const Message* m, void** iter, param_type* r) {
   992     return m->ReadUInt32(iter, reinterpret_cast<uint32_t*>(r));
   993   }
   994   static void Log(const param_type& p, std::wstring* l) {
   995     l->append(StringPrintf(L"%u", static_cast<uint32_t>(p)));
   996   }
   997 };
   999 // Finally, ParamTraits itself.
  1001 template <class P> struct ParamTraits : ParamTraitsMozilla<P> {};
  1003 // Now go back and define inlines dependent upon various ParamTraits<P>.
  1004 inline void
  1005 ParamTraitsIPC<base::Time>::Write(Message* m, const param_type& p) {
  1006   ParamTraits<int64_t>::Write(m, p.ToInternalValue());
  1008 inline bool
  1009 ParamTraitsIPC<base::Time>::Read(const Message* m, void** iter, param_type* r) {
  1010   int64_t value;
  1011   if (!ParamTraits<int64_t>::Read(m, iter, &value))
  1012     return false;
  1013   *r = base::Time::FromInternalValue(value);
  1014   return true;
  1016 inline void
  1017 ParamTraitsIPC<base::Time>::Log(const param_type& p, std::wstring* l) {
  1018   ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
  1021 inline void
  1022 ParamTraitsIPC<FilePath>::Write(Message* m, const param_type& p) {
  1023   ParamTraits<FilePath::StringType>::Write(m, p.value());
  1025 inline bool
  1026 ParamTraitsIPC<FilePath>::Read(const Message* m, void** iter, param_type* r) {
  1027   FilePath::StringType value;
  1028   if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
  1029     return false;
  1030   *r = FilePath(value);
  1031   return true;
  1033 inline void
  1034 ParamTraitsIPC<FilePath>::Log(const param_type& p, std::wstring* l) {
  1035   ParamTraits<FilePath::StringType>::Log(p.value(), l);
  1038 //-----------------------------------------------------------------------------
  1039 // Generic message subclasses
  1041 // Used for asynchronous messages.
  1042 template <class ParamType>
  1043 class MessageWithTuple : public Message {
  1044  public:
  1045   typedef ParamType Param;
  1047   MessageWithTuple(int32_t routing_id, uint16_t type, const Param& p)
  1048       : Message(routing_id, type, PRIORITY_NORMAL) {
  1049     WriteParam(this, p);
  1052   static bool Read(const Message* msg, Param* p) {
  1053     void* iter = NULL;
  1054     bool rv = ReadParam(msg, &iter, p);
  1055     DCHECK(rv) << "Error deserializing message " << msg->type();
  1056     return rv;
  1059   // Generic dispatcher.  Should cover most cases.
  1060   template<class T, class Method>
  1061   static bool Dispatch(const Message* msg, T* obj, Method func) {
  1062     Param p;
  1063     if (Read(msg, &p)) {
  1064       DispatchToMethod(obj, func, p);
  1065       return true;
  1067     return false;
  1070   // The following dispatchers exist for the case where the callback function
  1071   // needs the message as well.  They assume that "Param" is a type of Tuple
  1072   // (except the one arg case, as there is no Tuple1).
  1073   template<class T, typename TA>
  1074   static bool Dispatch(const Message* msg, T* obj,
  1075                        void (T::*func)(const Message&, TA)) {
  1076     Param p;
  1077     if (Read(msg, &p)) {
  1078       (obj->*func)(*msg, p);
  1079       return true;
  1081     return false;
  1084   template<class T, typename TA, typename TB>
  1085   static bool Dispatch(const Message* msg, T* obj,
  1086                        void (T::*func)(const Message&, TA, TB)) {
  1087     Param p;
  1088     if (Read(msg, &p)) {
  1089       (obj->*func)(*msg, p.a, p.b);
  1090       return true;
  1092     return false;
  1095   template<class T, typename TA, typename TB, typename TC>
  1096   static bool Dispatch(const Message* msg, T* obj,
  1097                        void (T::*func)(const Message&, TA, TB, TC)) {
  1098     Param p;
  1099     if (Read(msg, &p)) {
  1100       (obj->*func)(*msg, p.a, p.b, p.c);
  1101       return true;
  1103     return false;
  1106   template<class T, typename TA, typename TB, typename TC, typename TD>
  1107   static bool Dispatch(const Message* msg, T* obj,
  1108                        void (T::*func)(const Message&, TA, TB, TC, TD)) {
  1109     Param p;
  1110     if (Read(msg, &p)) {
  1111       (obj->*func)(*msg, p.a, p.b, p.c, p.d);
  1112       return true;
  1114     return false;
  1117   template<class T, typename TA, typename TB, typename TC, typename TD,
  1118            typename TE>
  1119   static bool Dispatch(const Message* msg, T* obj,
  1120                        void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
  1121     Param p;
  1122     if (Read(msg, &p)) {
  1123       (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
  1124       return true;
  1126     return false;
  1129   static void Log(const Message* msg, std::wstring* l) {
  1130     Param p;
  1131     if (Read(msg, &p))
  1132       LogParam(p, l);
  1135   // Functions used to do manual unpacking.  Only used by the automation code,
  1136   // these should go away once that code uses SyncChannel.
  1137   template<typename TA, typename TB>
  1138   static bool Read(const IPC::Message* msg, TA* a, TB* b) {
  1139     ParamType params;
  1140     if (!Read(msg, &params))
  1141       return false;
  1142     *a = params.a;
  1143     *b = params.b;
  1144     return true;
  1147   template<typename TA, typename TB, typename TC>
  1148   static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
  1149     ParamType params;
  1150     if (!Read(msg, &params))
  1151       return false;
  1152     *a = params.a;
  1153     *b = params.b;
  1154     *c = params.c;
  1155     return true;
  1158   template<typename TA, typename TB, typename TC, typename TD>
  1159   static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
  1160     ParamType params;
  1161     if (!Read(msg, &params))
  1162       return false;
  1163     *a = params.a;
  1164     *b = params.b;
  1165     *c = params.c;
  1166     *d = params.d;
  1167     return true;
  1170   template<typename TA, typename TB, typename TC, typename TD, typename TE>
  1171   static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
  1172     ParamType params;
  1173     if (!Read(msg, &params))
  1174       return false;
  1175     *a = params.a;
  1176     *b = params.b;
  1177     *c = params.c;
  1178     *d = params.d;
  1179     *e = params.e;
  1180     return true;
  1182 };
  1184 // This class assumes that its template argument is a RefTuple (a Tuple with
  1185 // reference elements).
  1186 template <class RefTuple>
  1187 class ParamDeserializer : public MessageReplyDeserializer {
  1188  public:
  1189   explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
  1191   bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
  1192     return ReadParam(&msg, &iter, &out_);
  1195   RefTuple out_;
  1196 };
  1198 // defined in ipc_logging.cc
  1199 void GenerateLogData(const std::wstring& channel, const Message& message,
  1200                      LogData* data);
  1202 // Used for synchronous messages.
  1203 template <class SendParamType, class ReplyParamType>
  1204 class MessageWithReply : public SyncMessage {
  1205  public:
  1206   typedef SendParamType SendParam;
  1207   typedef ReplyParamType ReplyParam;
  1209   MessageWithReply(int32_t routing_id, uint16_t type,
  1210                    const SendParam& send, const ReplyParam& reply)
  1211       : SyncMessage(routing_id, type, PRIORITY_NORMAL,
  1212                     new ParamDeserializer<ReplyParam>(reply)) {
  1213     WriteParam(this, send);
  1216   static void Log(const Message* msg, std::wstring* l) {
  1217     if (msg->is_sync()) {
  1218       SendParam p;
  1219       void* iter = SyncMessage::GetDataIterator(msg);
  1220       if (ReadParam(msg, &iter, &p))
  1221         LogParam(p, l);
  1223 #if defined(IPC_MESSAGE_LOG_ENABLED)
  1224       const std::wstring& output_params = msg->output_params();
  1225       if (!l->empty() && !output_params.empty())
  1226         l->append(L", ");
  1228       l->append(output_params);
  1229 #endif
  1230     } else {
  1231       // This is an outgoing reply.  Now that we have the output parameters, we
  1232       // can finally log the message.
  1233       typename ReplyParam::ValueTuple p;
  1234       void* iter = SyncMessage::GetDataIterator(msg);
  1235       if (ReadParam(msg, &iter, &p))
  1236         LogParam(p, l);
  1240   template<class T, class Method>
  1241   static bool Dispatch(const Message* msg, T* obj, Method func) {
  1242     SendParam send_params;
  1243     void* iter = GetDataIterator(msg);
  1244     Message* reply = GenerateReply(msg);
  1245     bool error;
  1246     if (ReadParam(msg, &iter, &send_params)) {
  1247       typename ReplyParam::ValueTuple reply_params;
  1248       DispatchToMethod(obj, func, send_params, &reply_params);
  1249       WriteParam(reply, reply_params);
  1250       error = false;
  1251 #ifdef IPC_MESSAGE_LOG_ENABLED
  1252       if (msg->received_time() != 0) {
  1253         std::wstring output_params;
  1254         LogParam(reply_params, &output_params);
  1255         msg->set_output_params(output_params);
  1257 #endif
  1258     } else {
  1259       NOTREACHED() << "Error deserializing message " << msg->type();
  1260       reply->set_reply_error();
  1261       error = true;
  1264     obj->Send(reply);
  1265     return !error;
  1268   template<class T, class Method>
  1269   static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
  1270     SendParam send_params;
  1271     void* iter = GetDataIterator(msg);
  1272     Message* reply = GenerateReply(msg);
  1273     bool error;
  1274     if (ReadParam(msg, &iter, &send_params)) {
  1275       Tuple1<Message&> t = MakeRefTuple(*reply);
  1277 #ifdef IPC_MESSAGE_LOG_ENABLED
  1278       if (msg->sent_time()) {
  1279         // Don't log the sync message after dispatch, as we don't have the
  1280         // output parameters at that point.  Instead, save its data and log it
  1281         // with the outgoing reply message when it's sent.
  1282         LogData* data = new LogData;
  1283         GenerateLogData(L"", *msg, data);
  1284         msg->set_dont_log();
  1285         reply->set_sync_log_data(data);
  1287 #endif
  1288       DispatchToMethod(obj, func, send_params, &t);
  1289       error = false;
  1290     } else {
  1291       NOTREACHED() << "Error deserializing message " << msg->type();
  1292       reply->set_reply_error();
  1293       obj->Send(reply);
  1294       error = true;
  1296     return !error;
  1299   template<typename TA>
  1300   static void WriteReplyParams(Message* reply, TA a) {
  1301     ReplyParam p(a);
  1302     WriteParam(reply, p);
  1305   template<typename TA, typename TB>
  1306   static void WriteReplyParams(Message* reply, TA a, TB b) {
  1307     ReplyParam p(a, b);
  1308     WriteParam(reply, p);
  1311   template<typename TA, typename TB, typename TC>
  1312   static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
  1313     ReplyParam p(a, b, c);
  1314     WriteParam(reply, p);
  1317   template<typename TA, typename TB, typename TC, typename TD>
  1318   static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
  1319     ReplyParam p(a, b, c, d);
  1320     WriteParam(reply, p);
  1323   template<typename TA, typename TB, typename TC, typename TD, typename TE>
  1324   static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
  1325     ReplyParam p(a, b, c, d, e);
  1326     WriteParam(reply, p);
  1328 };
  1330 //-----------------------------------------------------------------------------
  1332 }  // namespace IPC
  1334 #endif  // CHROME_COMMON_IPC_MESSAGE_UTILS_H_

mercurial