blob: cf0dcbc1cc06c2409bc26bf35ab30fb0bb1b7c02 [file] [log] [blame]
jochen@chromium.org30c8e912012-01-29 19:57:33 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +09002// 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
jhawkins@chromium.org63c75eb2010-03-09 09:38:41 +09008#include <algorithm>
agl@chromium.org1c6dcf22009-07-23 08:57:21 +09009#include <map>
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +090010#include <set>
tfarina@chromium.org439aef62011-03-21 10:07:01 +090011#include <string>
12#include <vector>
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090013
jdduke@chromium.org556db8b2014-03-19 05:48:35 +090014#include "base/containers/small_map.h"
rvargas@chromium.org9e469f62014-01-28 06:36:00 +090015#include "base/files/file.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090016#include "base/format_macros.h"
jdduke@chromium.orgc6d80f02014-05-20 11:34:56 +090017#include "base/memory/scoped_ptr.h"
hashimoto@chromium.orgbbf7c502012-11-14 15:35:52 +090018#include "base/memory/scoped_vector.h"
avi@chromium.orge7eaf392013-06-11 15:32:18 +090019#include "base/strings/string16.h"
20#include "base/strings/string_util.h"
21#include "base/strings/stringprintf.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090022#include "base/tuple.h"
tsepez@chromium.org4afe8f72012-10-24 08:03:35 +090023#include "ipc/ipc_message_start.h"
erg@google.comb16c8a62010-08-25 05:29:02 +090024#include "ipc/ipc_param_traits.h"
erg@google.combfae8592010-08-17 09:24:54 +090025#include "ipc/ipc_sync_message.h"
erg@google.comcab37e72010-08-14 05:43:58 +090026
erg@google.come6ffcb52010-08-18 03:38:24 +090027#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.
erg@google.comcb9c43f2010-08-20 05:23:25 +090034#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
erg@google.come6ffcb52010-08-18 03:38:24 +090041#define IPC_MSG_NOINLINE __attribute__((noinline));
erg@google.comcb9c43f2010-08-20 05:23:25 +090042#endif
erg@google.come6ffcb52010-08-18 03:38:24 +090043#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
erg@google.come6ffcb52010-08-18 03:38:24 +090050namespace base {
dmazzoni@chromium.org13e53652011-07-13 04:15:03 +090051class DictionaryValue;
brettw@chromium.orga7086942013-02-02 14:12:33 +090052class FilePath;
dmazzoni@chromium.org13e53652011-07-13 04:15:03 +090053class ListValue;
avi@chromium.orgd8179652013-06-13 22:47:46 +090054class NullableString16;
erg@google.come6ffcb52010-08-18 03:38:24 +090055class Time;
apatrick@chromium.org519c1c62010-10-22 07:04:52 +090056class TimeDelta;
isherman@chromium.org9952aaf2011-09-03 05:42:04 +090057class TimeTicks;
miu85c35562015-05-30 08:57:12 +090058class TraceTicks;
erg@google.come6ffcb52010-08-18 03:38:24 +090059struct FileDescriptor;
60}
61
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090062namespace IPC {
63
erg@google.come6ffcb52010-08-18 03:38:24 +090064struct ChannelHandle;
65
brettw@chromium.orgce352e52012-06-05 06:18:25 +090066// -----------------------------------------------------------------------------
67// How we send IPC message logs across channels.
68struct IPC_EXPORT LogData {
69 LogData();
70 ~LogData();
71
72 std::string channel;
73 int32 routing_id;
74 uint32 type; // "User-defined" message type, from ipc_message.h.
75 std::string flags;
76 int64 sent; // Time that the message was sent (i.e. at Send()).
77 int64 receive; // Time before it was dispatched (i.e. before calling
78 // OnMessageReceived).
79 int64 dispatch; // Time after it was dispatched (i.e. after calling
80 // OnMessageReceived).
81 std::string message_name;
82 std::string params;
83};
84
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090085//-----------------------------------------------------------------------------
viettrungluu@chromium.orgc3ad0512012-12-18 05:23:47 +090086
tsepez@chromium.org1ac46132011-02-12 03:46:19 +090087// A dummy struct to place first just to allow leading commas for all
88// members in the macro-generated constructor initializer lists.
89struct NoParams {
90};
91
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090092template <class P>
93static inline void WriteParam(Message* m, const P& p) {
aa@chromium.org1605b6d2009-08-14 14:43:53 +090094 typedef typename SimilarTypeTraits<P>::Type Type;
thakis@chromium.orgb13bd1d2010-06-17 03:39:53 +090095 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090096}
97
98template <class P>
jbates@chromium.org0fc87362012-03-08 05:42:56 +090099static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m,
brettwa4879472015-06-02 16:02:47 +0900100 base::PickleIterator* iter,
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900101 P* p) {
aa@chromium.org1605b6d2009-08-14 14:43:53 +0900102 typedef typename SimilarTypeTraits<P>::Type Type;
103 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900104}
105
106template <class P>
erg@google.com8aca7272010-08-19 03:33:57 +0900107static inline void LogParam(const P& p, std::string* l) {
aa@chromium.org1605b6d2009-08-14 14:43:53 +0900108 typedef typename SimilarTypeTraits<P>::Type Type;
thakis@chromium.orgb13bd1d2010-06-17 03:39:53 +0900109 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900110}
111
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900112// Primitive ParamTraits -------------------------------------------------------
113
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900114template <>
115struct ParamTraits<bool> {
116 typedef bool param_type;
117 static void Write(Message* m, const param_type& p) {
118 m->WriteBool(p);
119 }
brettwa4879472015-06-02 16:02:47 +0900120 static bool Read(const Message* m, base::PickleIterator* iter,
121 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900122 return iter->ReadBool(r);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900123 }
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900124 IPC_EXPORT static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900125};
126
127template <>
tsepez@chromium.org09eb95f2013-07-13 08:12:28 +0900128struct IPC_EXPORT ParamTraits<unsigned char> {
jschuh@chromium.orgccd324a2013-07-13 13:42:10 +0900129 typedef unsigned char param_type;
tsepez@chromium.org09eb95f2013-07-13 08:12:28 +0900130 static void Write(Message* m, const param_type& p);
131 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
132 static void Log(const param_type& p, std::string* l);
133};
134
135template <>
136struct IPC_EXPORT ParamTraits<unsigned short> {
137 typedef unsigned short param_type;
138 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900139 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
tsepez@chromium.org09eb95f2013-07-13 08:12:28 +0900140 static void Log(const param_type& p, std::string* l);
141};
142
143template <>
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900144struct ParamTraits<int> {
145 typedef int param_type;
146 static void Write(Message* m, const param_type& p) {
147 m->WriteInt(p);
148 }
brettwa4879472015-06-02 16:02:47 +0900149 static bool Read(const Message* m, base::PickleIterator* iter,
150 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900151 return iter->ReadInt(r);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900152 }
darin@chromium.org80e4c5e2011-08-16 05:41:46 +0900153 IPC_EXPORT static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900154};
155
156template <>
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900157struct ParamTraits<unsigned int> {
158 typedef unsigned int param_type;
159 static void Write(Message* m, const param_type& p) {
160 m->WriteInt(p);
161 }
brettwa4879472015-06-02 16:02:47 +0900162 static bool Read(const Message* m, base::PickleIterator* iter,
163 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900164 return iter->ReadInt(reinterpret_cast<int*>(r));
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900165 }
darin@chromium.org80e4c5e2011-08-16 05:41:46 +0900166 IPC_EXPORT static void Log(const param_type& p, std::string* l);
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900167};
168
169template <>
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900170struct ParamTraits<long> {
171 typedef long param_type;
172 static void Write(Message* m, const param_type& p) {
mdm@chromium.org69bca9d2012-03-23 09:03:10 +0900173 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900174 }
brettwa4879472015-06-02 16:02:47 +0900175 static bool Read(const Message* m, base::PickleIterator* iter,
176 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900177 return iter->ReadLong(r);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900178 }
darin@chromium.org80e4c5e2011-08-16 05:41:46 +0900179 IPC_EXPORT static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900180};
181
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900182template <>
183struct ParamTraits<unsigned long> {
184 typedef unsigned long param_type;
185 static void Write(Message* m, const param_type& p) {
mdm@chromium.org69bca9d2012-03-23 09:03:10 +0900186 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900187 }
brettwa4879472015-06-02 16:02:47 +0900188 static bool Read(const Message* m, base::PickleIterator* iter,
189 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900190 return iter->ReadLong(reinterpret_cast<long*>(r));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900191 }
darin@chromium.org80e4c5e2011-08-16 05:41:46 +0900192 IPC_EXPORT static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900193};
194
195template <>
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900196struct ParamTraits<long long> {
197 typedef long long param_type;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900198 static void Write(Message* m, const param_type& p) {
199 m->WriteInt64(static_cast<int64>(p));
200 }
brettwa4879472015-06-02 16:02:47 +0900201 static bool Read(const Message* m, base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900202 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900203 return iter->ReadInt64(reinterpret_cast<int64*>(r));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900204 }
darin@chromium.org80e4c5e2011-08-16 05:41:46 +0900205 IPC_EXPORT static void Log(const param_type& p, std::string* l);
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900206};
207
208template <>
209struct ParamTraits<unsigned long long> {
210 typedef unsigned long long param_type;
211 static void Write(Message* m, const param_type& p) {
212 m->WriteInt64(p);
213 }
brettwa4879472015-06-02 16:02:47 +0900214 static bool Read(const Message* m, base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900215 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900216 return iter->ReadInt64(reinterpret_cast<int64*>(r));
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900217 }
darin@chromium.org80e4c5e2011-08-16 05:41:46 +0900218 IPC_EXPORT static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900219};
220
jeremy@chromium.org4be619f2010-06-17 12:29:26 +0900221// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
222// should be sure to check the sanity of these values after receiving them over
223// IPC.
224template <>
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900225struct IPC_EXPORT ParamTraits<float> {
jeremy@chromium.org4be619f2010-06-17 12:29:26 +0900226 typedef float param_type;
piman@chromium.orgdd413b42013-10-31 18:27:31 +0900227 static void Write(Message* m, const param_type& p) {
228 m->WriteFloat(p);
229 }
brettwa4879472015-06-02 16:02:47 +0900230 static bool Read(const Message* m, base::PickleIterator* iter,
231 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900232 return iter->ReadFloat(r);
piman@chromium.orgdd413b42013-10-31 18:27:31 +0900233 }
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900234 static void Log(const param_type& p, std::string* l);
jeremy@chromium.org4be619f2010-06-17 12:29:26 +0900235};
236
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900237template <>
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900238struct IPC_EXPORT ParamTraits<double> {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900239 typedef double param_type;
tsepez@chromium.org3081fac2012-05-31 06:15:57 +0900240 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900241 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
tsepez@chromium.org3081fac2012-05-31 06:15:57 +0900242 static void Log(const param_type& p, std::string* l);
243};
244
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900245// STL ParamTraits -------------------------------------------------------------
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900246
247template <>
248struct ParamTraits<std::string> {
249 typedef std::string param_type;
250 static void Write(Message* m, const param_type& p) {
251 m->WriteString(p);
252 }
brettwa4879472015-06-02 16:02:47 +0900253 static bool Read(const Message* m, base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900254 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900255 return iter->ReadString(r);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900256 }
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900257 IPC_EXPORT static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900258};
259
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900260template <>
brettw@chromium.org5b040852013-12-03 09:39:26 +0900261struct ParamTraits<base::string16> {
262 typedef base::string16 param_type;
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900263 static void Write(Message* m, const param_type& p) {
264 m->WriteString16(p);
265 }
brettwa4879472015-06-02 16:02:47 +0900266 static bool Read(const Message* m, base::PickleIterator* iter,
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900267 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900268 return iter->ReadString16(r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900269 }
270 IPC_EXPORT static void Log(const param_type& p, std::string* l);
271};
evan@chromium.orga6590362009-07-28 06:09:07 +0900272
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900273template <>
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900274struct IPC_EXPORT ParamTraits<std::vector<char> > {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900275 typedef std::vector<char> param_type;
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900276 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900277 static bool Read(const Message*, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900278 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900279};
280
bauerb@chromium.org17246c72011-10-06 03:55:42 +0900281template <>
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900282struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
283 typedef std::vector<unsigned char> param_type;
284 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900285 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900286 static void Log(const param_type& p, std::string* l);
287};
288
289template <>
290struct IPC_EXPORT ParamTraits<std::vector<bool> > {
bauerb@chromium.org17246c72011-10-06 03:55:42 +0900291 typedef std::vector<bool> param_type;
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900292 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900293 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900294 static void Log(const param_type& p, std::string* l);
bauerb@chromium.org17246c72011-10-06 03:55:42 +0900295};
296
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900297template <class P>
298struct ParamTraits<std::vector<P> > {
299 typedef std::vector<P> param_type;
300 static void Write(Message* m, const param_type& p) {
301 WriteParam(m, static_cast<int>(p.size()));
302 for (size_t i = 0; i < p.size(); i++)
303 WriteParam(m, p[i]);
304 }
brettwa4879472015-06-02 16:02:47 +0900305 static bool Read(const Message* m, base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900306 param_type* r) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900307 int size;
cevans@chromium.org7600d942009-12-31 14:17:23 +0900308 // ReadLength() checks for < 0 itself.
avic9f0ad02014-12-29 08:31:48 +0900309 if (!iter->ReadLength(&size))
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900310 return false;
311 // Resizing beforehand is not safe, see BUG 1006367 for details.
cevans@chromium.org7600d942009-12-31 14:17:23 +0900312 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
313 return false;
314 r->resize(size);
315 for (int i = 0; i < size; i++) {
316 if (!ReadParam(m, iter, &(*r)[i]))
317 return false;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900318 }
319 return true;
320 }
erg@google.com8aca7272010-08-19 03:33:57 +0900321 static void Log(const param_type& p, std::string* l) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900322 for (size_t i = 0; i < p.size(); ++i) {
323 if (i != 0)
erg@google.com8aca7272010-08-19 03:33:57 +0900324 l->append(" ");
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900325 LogParam((p[i]), l);
326 }
327 }
328};
329
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +0900330template <class P>
331struct ParamTraits<std::set<P> > {
332 typedef std::set<P> param_type;
333 static void Write(Message* m, const param_type& p) {
334 WriteParam(m, static_cast<int>(p.size()));
335 typename param_type::const_iterator iter;
336 for (iter = p.begin(); iter != p.end(); ++iter)
337 WriteParam(m, *iter);
338 }
brettwa4879472015-06-02 16:02:47 +0900339 static bool Read(const Message* m, base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900340 param_type* r) {
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +0900341 int size;
avic9f0ad02014-12-29 08:31:48 +0900342 if (!iter->ReadLength(&size))
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +0900343 return false;
344 for (int i = 0; i < size; ++i) {
345 P item;
346 if (!ReadParam(m, iter, &item))
347 return false;
348 r->insert(item);
349 }
350 return true;
351 }
erg@google.com8aca7272010-08-19 03:33:57 +0900352 static void Log(const param_type& p, std::string* l) {
353 l->append("<std::set>");
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +0900354 }
355};
356
jkarlin45b11f92014-09-24 20:42:37 +0900357template <class K, class V, class C, class A>
358struct ParamTraits<std::map<K, V, C, A> > {
359 typedef std::map<K, V, C, A> param_type;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900360 static void Write(Message* m, const param_type& p) {
361 WriteParam(m, static_cast<int>(p.size()));
362 typename param_type::const_iterator iter;
363 for (iter = p.begin(); iter != p.end(); ++iter) {
364 WriteParam(m, iter->first);
365 WriteParam(m, iter->second);
366 }
367 }
brettwa4879472015-06-02 16:02:47 +0900368 static bool Read(const Message* m, base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900369 param_type* r) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900370 int size;
371 if (!ReadParam(m, iter, &size) || size < 0)
372 return false;
373 for (int i = 0; i < size; ++i) {
374 K k;
375 if (!ReadParam(m, iter, &k))
376 return false;
377 V& value = (*r)[k];
378 if (!ReadParam(m, iter, &value))
379 return false;
380 }
381 return true;
382 }
erg@google.com8aca7272010-08-19 03:33:57 +0900383 static void Log(const param_type& p, std::string* l) {
384 l->append("<std::map>");
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900385 }
386};
387
jam@chromium.org0aa05022009-08-04 11:00:56 +0900388template <class A, class B>
389struct ParamTraits<std::pair<A, B> > {
390 typedef std::pair<A, B> param_type;
391 static void Write(Message* m, const param_type& p) {
392 WriteParam(m, p.first);
393 WriteParam(m, p.second);
394 }
brettwa4879472015-06-02 16:02:47 +0900395 static bool Read(const Message* m, base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900396 param_type* r) {
jam@chromium.org0aa05022009-08-04 11:00:56 +0900397 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
398 }
erg@google.com8aca7272010-08-19 03:33:57 +0900399 static void Log(const param_type& p, std::string* l) {
400 l->append("(");
jam@chromium.org0aa05022009-08-04 11:00:56 +0900401 LogParam(p.first, l);
erg@google.com8aca7272010-08-19 03:33:57 +0900402 l->append(", ");
jam@chromium.org0aa05022009-08-04 11:00:56 +0900403 LogParam(p.second, l);
erg@google.com8aca7272010-08-19 03:33:57 +0900404 l->append(")");
jam@chromium.org0aa05022009-08-04 11:00:56 +0900405 }
406};
407
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900408// Base ParamTraits ------------------------------------------------------------
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900409
410template <>
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900411struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
412 typedef base::DictionaryValue param_type;
erg@google.come6ffcb52010-08-18 03:38:24 +0900413 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900414 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
erg@google.com8aca7272010-08-19 03:33:57 +0900415 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900416};
417
418#if defined(OS_POSIX)
419// FileDescriptors may be serialised over IPC channels on POSIX. On the
420// receiving side, the FileDescriptor is a valid duplicate of the file
421// descriptor which was transmitted: *it is not just a copy of the integer like
422// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
423// this case, the receiving end will see a value of -1. *Zero is a valid file
424// descriptor*.
425//
426// The received file descriptor will have the |auto_close| flag set to true. The
427// code which handles the message is responsible for taking ownership of it.
428// File descriptors are OS resources and must be closed when no longer needed.
429//
430// When sending a file descriptor, the file descriptor must be valid at the time
431// of transmission. Since transmission is not synchronous, one should consider
432// dup()ing any file descriptors to be transmitted and setting the |auto_close|
433// flag, which causes the file descriptor to be closed after writing.
434template<>
darin@chromium.org80e4c5e2011-08-16 05:41:46 +0900435struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900436 typedef base::FileDescriptor param_type;
erg@google.come6ffcb52010-08-18 03:38:24 +0900437 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900438 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
erg@google.com8aca7272010-08-19 03:33:57 +0900439 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900440};
jhawkins@chromium.org63c75eb2010-03-09 09:38:41 +0900441#endif // defined(OS_POSIX)
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900442
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900443template <>
brettw@chromium.orga7086942013-02-02 14:12:33 +0900444struct IPC_EXPORT ParamTraits<base::FilePath> {
445 typedef base::FilePath param_type;
erg@google.come6ffcb52010-08-18 03:38:24 +0900446 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900447 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
erg@google.com8aca7272010-08-19 03:33:57 +0900448 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900449};
450
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900451template <>
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900452struct IPC_EXPORT ParamTraits<base::ListValue> {
453 typedef base::ListValue param_type;
erg@google.com20b66e32010-10-01 05:06:30 +0900454 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900455 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900456 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900457};
458
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900459template <>
avi@chromium.orgd8179652013-06-13 22:47:46 +0900460struct IPC_EXPORT ParamTraits<base::NullableString16> {
461 typedef base::NullableString16 param_type;
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900462 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900463 static bool Read(const Message* m, base::PickleIterator* iter,
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900464 param_type* r);
465 static void Log(const param_type& p, std::string* l);
466};
467
468template <>
rvargas@chromium.org9e469f62014-01-28 06:36:00 +0900469struct IPC_EXPORT ParamTraits<base::File::Info> {
470 typedef base::File::Info param_type;
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900471 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900472 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900473 static void Log(const param_type& p, std::string* l);
474};
475
476template <>
rvargas@chromium.org9e469f62014-01-28 06:36:00 +0900477struct SimilarTypeTraits<base::File::Error> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900478 typedef int Type;
479};
480
grt@chromium.orgb9abb172013-03-01 06:46:11 +0900481#if defined(OS_WIN)
482template <>
483struct SimilarTypeTraits<HWND> {
484 typedef HANDLE Type;
485};
486#endif // defined(OS_WIN)
487
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900488template <>
489struct IPC_EXPORT ParamTraits<base::Time> {
490 typedef base::Time param_type;
491 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900492 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900493 static void Log(const param_type& p, std::string* l);
494};
495
496template <>
497struct IPC_EXPORT ParamTraits<base::TimeDelta> {
498 typedef base::TimeDelta param_type;
499 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900500 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900501 static void Log(const param_type& p, std::string* l);
502};
503
504template <>
505struct IPC_EXPORT ParamTraits<base::TimeTicks> {
506 typedef base::TimeTicks param_type;
507 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900508 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900509 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900510};
511
512template <>
miu85c35562015-05-30 08:57:12 +0900513struct IPC_EXPORT ParamTraits<base::TraceTicks> {
514 typedef base::TraceTicks param_type;
515 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900516 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
miu85c35562015-05-30 08:57:12 +0900517 static void Log(const param_type& p, std::string* l);
518};
519
520template <>
brettw79a90902015-05-30 07:15:47 +0900521struct ParamTraits<base::Tuple<>> {
522 typedef base::Tuple<> param_type;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900523 static void Write(Message* m, const param_type& p) {
524 }
brettwa4879472015-06-02 16:02:47 +0900525 static bool Read(const Message* m, base::PickleIterator* iter,
526 param_type* r) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900527 return true;
528 }
erg@google.com8aca7272010-08-19 03:33:57 +0900529 static void Log(const param_type& p, std::string* l) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900530 }
531};
532
533template <class A>
brettw79a90902015-05-30 07:15:47 +0900534struct ParamTraits<base::Tuple<A>> {
535 typedef base::Tuple<A> param_type;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900536 static void Write(Message* m, const param_type& p) {
brettw79a90902015-05-30 07:15:47 +0900537 WriteParam(m, base::get<0>(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900538 }
brettwa4879472015-06-02 16:02:47 +0900539 static bool Read(const Message* m, base::PickleIterator* iter,
540 param_type* r) {
brettw79a90902015-05-30 07:15:47 +0900541 return ReadParam(m, iter, &base::get<0>(*r));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900542 }
erg@google.com8aca7272010-08-19 03:33:57 +0900543 static void Log(const param_type& p, std::string* l) {
brettw79a90902015-05-30 07:15:47 +0900544 LogParam(base::get<0>(p), l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900545 }
546};
547
548template <class A, class B>
brettw79a90902015-05-30 07:15:47 +0900549struct ParamTraits<base::Tuple<A, B>> {
550 typedef base::Tuple<A, B> param_type;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900551 static void Write(Message* m, const param_type& p) {
brettw79a90902015-05-30 07:15:47 +0900552 WriteParam(m, base::get<0>(p));
553 WriteParam(m, base::get<1>(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900554 }
brettwa4879472015-06-02 16:02:47 +0900555 static bool Read(const Message* m, base::PickleIterator* iter,
556 param_type* r) {
brettw79a90902015-05-30 07:15:47 +0900557 return (ReadParam(m, iter, &base::get<0>(*r)) &&
558 ReadParam(m, iter, &base::get<1>(*r)));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900559 }
erg@google.com8aca7272010-08-19 03:33:57 +0900560 static void Log(const param_type& p, std::string* l) {
brettw79a90902015-05-30 07:15:47 +0900561 LogParam(base::get<0>(p), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900562 l->append(", ");
brettw79a90902015-05-30 07:15:47 +0900563 LogParam(base::get<1>(p), l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900564 }
565};
566
567template <class A, class B, class C>
brettw79a90902015-05-30 07:15:47 +0900568struct ParamTraits<base::Tuple<A, B, C>> {
569 typedef base::Tuple<A, B, C> param_type;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900570 static void Write(Message* m, const param_type& p) {
brettw79a90902015-05-30 07:15:47 +0900571 WriteParam(m, base::get<0>(p));
572 WriteParam(m, base::get<1>(p));
573 WriteParam(m, base::get<2>(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900574 }
brettwa4879472015-06-02 16:02:47 +0900575 static bool Read(const Message* m, base::PickleIterator* iter,
576 param_type* r) {
brettw79a90902015-05-30 07:15:47 +0900577 return (ReadParam(m, iter, &base::get<0>(*r)) &&
578 ReadParam(m, iter, &base::get<1>(*r)) &&
579 ReadParam(m, iter, &base::get<2>(*r)));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900580 }
erg@google.com8aca7272010-08-19 03:33:57 +0900581 static void Log(const param_type& p, std::string* l) {
brettw79a90902015-05-30 07:15:47 +0900582 LogParam(base::get<0>(p), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900583 l->append(", ");
brettw79a90902015-05-30 07:15:47 +0900584 LogParam(base::get<1>(p), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900585 l->append(", ");
brettw79a90902015-05-30 07:15:47 +0900586 LogParam(base::get<2>(p), l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900587 }
588};
589
590template <class A, class B, class C, class D>
brettw79a90902015-05-30 07:15:47 +0900591struct ParamTraits<base::Tuple<A, B, C, D>> {
592 typedef base::Tuple<A, B, C, D> param_type;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900593 static void Write(Message* m, const param_type& p) {
brettw79a90902015-05-30 07:15:47 +0900594 WriteParam(m, base::get<0>(p));
595 WriteParam(m, base::get<1>(p));
596 WriteParam(m, base::get<2>(p));
597 WriteParam(m, base::get<3>(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900598 }
brettwa4879472015-06-02 16:02:47 +0900599 static bool Read(const Message* m, base::PickleIterator* iter,
600 param_type* r) {
brettw79a90902015-05-30 07:15:47 +0900601 return (ReadParam(m, iter, &base::get<0>(*r)) &&
602 ReadParam(m, iter, &base::get<1>(*r)) &&
603 ReadParam(m, iter, &base::get<2>(*r)) &&
604 ReadParam(m, iter, &base::get<3>(*r)));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900605 }
erg@google.com8aca7272010-08-19 03:33:57 +0900606 static void Log(const param_type& p, std::string* l) {
brettw79a90902015-05-30 07:15:47 +0900607 LogParam(base::get<0>(p), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900608 l->append(", ");
brettw79a90902015-05-30 07:15:47 +0900609 LogParam(base::get<1>(p), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900610 l->append(", ");
brettw79a90902015-05-30 07:15:47 +0900611 LogParam(base::get<2>(p), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900612 l->append(", ");
brettw79a90902015-05-30 07:15:47 +0900613 LogParam(base::get<3>(p), l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900614 }
615};
616
617template <class A, class B, class C, class D, class E>
brettw79a90902015-05-30 07:15:47 +0900618struct ParamTraits<base::Tuple<A, B, C, D, E>> {
619 typedef base::Tuple<A, B, C, D, E> param_type;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900620 static void Write(Message* m, const param_type& p) {
brettw79a90902015-05-30 07:15:47 +0900621 WriteParam(m, base::get<0>(p));
622 WriteParam(m, base::get<1>(p));
623 WriteParam(m, base::get<2>(p));
624 WriteParam(m, base::get<3>(p));
625 WriteParam(m, base::get<4>(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900626 }
brettwa4879472015-06-02 16:02:47 +0900627 static bool Read(const Message* m, base::PickleIterator* iter,
628 param_type* r) {
brettw79a90902015-05-30 07:15:47 +0900629 return (ReadParam(m, iter, &base::get<0>(*r)) &&
630 ReadParam(m, iter, &base::get<1>(*r)) &&
631 ReadParam(m, iter, &base::get<2>(*r)) &&
632 ReadParam(m, iter, &base::get<3>(*r)) &&
633 ReadParam(m, iter, &base::get<4>(*r)));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900634 }
erg@google.com8aca7272010-08-19 03:33:57 +0900635 static void Log(const param_type& p, std::string* l) {
brettw79a90902015-05-30 07:15:47 +0900636 LogParam(base::get<0>(p), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900637 l->append(", ");
brettw79a90902015-05-30 07:15:47 +0900638 LogParam(base::get<1>(p), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900639 l->append(", ");
brettw79a90902015-05-30 07:15:47 +0900640 LogParam(base::get<2>(p), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900641 l->append(", ");
brettw79a90902015-05-30 07:15:47 +0900642 LogParam(base::get<3>(p), l);
erg@google.com8aca7272010-08-19 03:33:57 +0900643 l->append(", ");
brettw79a90902015-05-30 07:15:47 +0900644 LogParam(base::get<4>(p), l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900645 }
646};
647
hashimoto@chromium.orgbbf7c502012-11-14 15:35:52 +0900648template<class P>
649struct ParamTraits<ScopedVector<P> > {
650 typedef ScopedVector<P> param_type;
651 static void Write(Message* m, const param_type& p) {
652 WriteParam(m, static_cast<int>(p.size()));
653 for (size_t i = 0; i < p.size(); i++)
654 WriteParam(m, *p[i]);
655 }
brettwa4879472015-06-02 16:02:47 +0900656 static bool Read(const Message* m, base::PickleIterator* iter,
657 param_type* r) {
hashimoto@chromium.orgbbf7c502012-11-14 15:35:52 +0900658 int size = 0;
avic9f0ad02014-12-29 08:31:48 +0900659 if (!iter->ReadLength(&size))
hashimoto@chromium.orgbbf7c502012-11-14 15:35:52 +0900660 return false;
661 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
662 return false;
663 r->resize(size);
664 for (int i = 0; i < size; i++) {
665 (*r)[i] = new P();
666 if (!ReadParam(m, iter, (*r)[i]))
667 return false;
668 }
669 return true;
670 }
671 static void Log(const param_type& p, std::string* l) {
672 for (size_t i = 0; i < p.size(); ++i) {
673 if (i != 0)
674 l->append(" ");
675 LogParam(*p[i], l);
676 }
677 }
678};
679
jdduke@chromium.org556db8b2014-03-19 05:48:35 +0900680template <typename NormalMap,
681 int kArraySize,
682 typename EqualKey,
683 typename MapInit>
684struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
685 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
686 typedef typename param_type::key_type K;
687 typedef typename param_type::data_type V;
688 static void Write(Message* m, const param_type& p) {
689 WriteParam(m, static_cast<int>(p.size()));
690 typename param_type::const_iterator iter;
691 for (iter = p.begin(); iter != p.end(); ++iter) {
692 WriteParam(m, iter->first);
693 WriteParam(m, iter->second);
694 }
695 }
brettwa4879472015-06-02 16:02:47 +0900696 static bool Read(const Message* m, base::PickleIterator* iter,
697 param_type* r) {
jdduke@chromium.org556db8b2014-03-19 05:48:35 +0900698 int size;
avic9f0ad02014-12-29 08:31:48 +0900699 if (!iter->ReadLength(&size))
jdduke@chromium.org556db8b2014-03-19 05:48:35 +0900700 return false;
701 for (int i = 0; i < size; ++i) {
702 K key;
703 if (!ReadParam(m, iter, &key))
704 return false;
705 V& value = (*r)[key];
706 if (!ReadParam(m, iter, &value))
707 return false;
708 }
709 return true;
710 }
711 static void Log(const param_type& p, std::string* l) {
712 l->append("<base::SmallMap>");
713 }
714};
715
jdduke@chromium.orgc6d80f02014-05-20 11:34:56 +0900716template <class P>
717struct ParamTraits<scoped_ptr<P> > {
718 typedef scoped_ptr<P> param_type;
719 static void Write(Message* m, const param_type& p) {
720 bool valid = !!p;
721 WriteParam(m, valid);
722 if (valid)
723 WriteParam(m, *p);
724 }
brettwa4879472015-06-02 16:02:47 +0900725 static bool Read(const Message* m, base::PickleIterator* iter,
726 param_type* r) {
jdduke@chromium.orgc6d80f02014-05-20 11:34:56 +0900727 bool valid = false;
728 if (!ReadParam(m, iter, &valid))
729 return false;
730
731 if (!valid) {
732 r->reset();
733 return true;
734 }
735
736 param_type temp(new P());
737 if (!ReadParam(m, iter, temp.get()))
738 return false;
739
740 r->swap(temp);
741 return true;
742 }
743 static void Log(const param_type& p, std::string* l) {
744 if (p)
745 LogParam(*p, l);
746 else
747 l->append("NULL");
748 }
749};
750
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900751// IPC types ParamTraits -------------------------------------------------------
752
753// A ChannelHandle is basically a platform-inspecific wrapper around the
754// fact that IPC endpoints are handled specially on POSIX. See above comments
755// on FileDescriptor for more background.
756template<>
757struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
758 typedef ChannelHandle param_type;
759 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900760 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900761 static void Log(const param_type& p, std::string* l);
762};
763
764template <>
765struct IPC_EXPORT ParamTraits<LogData> {
766 typedef LogData param_type;
767 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900768 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900769 static void Log(const param_type& p, std::string* l);
770};
771
772template <>
773struct IPC_EXPORT ParamTraits<Message> {
774 static void Write(Message* m, const Message& p);
brettwa4879472015-06-02 16:02:47 +0900775 static bool Read(const Message* m, base::PickleIterator* iter, Message* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900776 static void Log(const Message& p, std::string* l);
777};
778
779// Windows ParamTraits ---------------------------------------------------------
780
781#if defined(OS_WIN)
782template <>
783struct IPC_EXPORT ParamTraits<HANDLE> {
784 typedef HANDLE param_type;
785 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900786 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900787 static void Log(const param_type& p, std::string* l);
788};
789
790template <>
791struct IPC_EXPORT ParamTraits<LOGFONT> {
792 typedef LOGFONT param_type;
793 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900794 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900795 static void Log(const param_type& p, std::string* l);
796};
797
798template <>
799struct IPC_EXPORT ParamTraits<MSG> {
800 typedef MSG param_type;
801 static void Write(Message* m, const param_type& p);
brettwa4879472015-06-02 16:02:47 +0900802 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900803 static void Log(const param_type& p, std::string* l);
804};
805#endif // defined(OS_WIN)
806
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900807//-----------------------------------------------------------------------------
808// Generic message subclasses
809
810// Used for asynchronous messages.
811template <class ParamType>
darin@chromium.orgb4587d52011-08-27 06:27:30 +0900812class MessageSchema {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900813 public:
814 typedef ParamType Param;
brettw79a90902015-05-30 07:15:47 +0900815 typedef typename base::TupleTypes<ParamType>::ParamTuple RefParam;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900816
darin@chromium.orgb4587d52011-08-27 06:27:30 +0900817 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
erg@google.come6ffcb52010-08-18 03:38:24 +0900818 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900819};
820
erg@google.come6ffcb52010-08-18 03:38:24 +0900821// defined in ipc_logging.cc
darin@chromium.org80e4c5e2011-08-16 05:41:46 +0900822IPC_EXPORT void GenerateLogData(const std::string& channel,
823 const Message& message,
scottbyer@chromium.orgf0cf0b72011-10-21 04:34:43 +0900824 LogData* data, bool get_params);
erg@google.come6ffcb52010-08-18 03:38:24 +0900825
826
827#if defined(IPC_MESSAGE_LOG_ENABLED)
erg@google.com8aca7272010-08-19 03:33:57 +0900828inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
829 const std::string& output_params = msg->output_params();
erg@google.come6ffcb52010-08-18 03:38:24 +0900830 if (!l->empty() && !output_params.empty())
erg@google.com8aca7272010-08-19 03:33:57 +0900831 l->append(", ");
erg@google.come6ffcb52010-08-18 03:38:24 +0900832
833 l->append(output_params);
834}
835
836template <class ReplyParamType>
837inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
838 const Message* msg) {
839 if (msg->received_time() != 0) {
erg@google.com8aca7272010-08-19 03:33:57 +0900840 std::string output_params;
erg@google.come6ffcb52010-08-18 03:38:24 +0900841 LogParam(reply_params, &output_params);
842 msg->set_output_params(output_params);
843 }
844}
845
846inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
847 if (msg->sent_time()) {
848 // Don't log the sync message after dispatch, as we don't have the
849 // output parameters at that point. Instead, save its data and log it
850 // with the outgoing reply message when it's sent.
851 LogData* data = new LogData;
scottbyer@chromium.orgf0cf0b72011-10-21 04:34:43 +0900852 GenerateLogData("", *msg, data, true);
erg@google.come6ffcb52010-08-18 03:38:24 +0900853 msg->set_dont_log();
854 reply->set_sync_log_data(data);
855 }
856}
857#else
erg@google.com8aca7272010-08-19 03:33:57 +0900858inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
erg@google.come6ffcb52010-08-18 03:38:24 +0900859
860template <class ReplyParamType>
861inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
862 const Message* msg) {}
863
864inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
865#endif
866
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900867// This class assumes that its template argument is a RefTuple (a Tuple with
erg@google.come6ffcb52010-08-18 03:38:24 +0900868// reference elements). This would go into ipc_message_utils_impl.h, but it is
869// also used by chrome_frame.
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900870template <class RefTuple>
871class ParamDeserializer : public MessageReplyDeserializer {
872 public:
873 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
874
dmichaela5a9c962014-12-18 10:53:14 +0900875 bool SerializeOutputParameters(const IPC::Message& msg,
brettwa4879472015-06-02 16:02:47 +0900876 base::PickleIterator iter) override {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900877 return ReadParam(&msg, &iter, &out_);
878 }
879
880 RefTuple out_;
881};
882
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900883// Used for synchronous messages.
884template <class SendParamType, class ReplyParamType>
darin@chromium.orgb4587d52011-08-27 06:27:30 +0900885class SyncMessageSchema {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900886 public:
887 typedef SendParamType SendParam;
brettw79a90902015-05-30 07:15:47 +0900888 typedef typename base::TupleTypes<SendParam>::ParamTuple RefSendParam;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900889 typedef ReplyParamType ReplyParam;
890
darin@chromium.orgb4587d52011-08-27 06:27:30 +0900891 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
erg@google.come6ffcb52010-08-18 03:38:24 +0900892 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
893 static bool ReadReplyParam(
894 const Message* msg,
brettw79a90902015-05-30 07:15:47 +0900895 typename base::TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900896
jam@chromium.org82f52f82010-12-22 05:03:24 +0900897 template<class T, class S, class Method>
darin@chromium.orgb4587d52011-08-27 06:27:30 +0900898 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
899 const Message* msg, T* obj, S* sender,
900 Method func) {
901 Message* reply = SyncMessage::GenerateReply(msg);
902 if (ok) {
brettw79a90902015-05-30 07:15:47 +0900903 typename base::TupleTypes<ReplyParam>::ValueTuple reply_params;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900904 DispatchToMethod(obj, func, send_params, &reply_params);
905 WriteParam(reply, reply_params);
erg@google.come6ffcb52010-08-18 03:38:24 +0900906 LogReplyParamsToMessage(reply_params, msg);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900907 } else {
908 NOTREACHED() << "Error deserializing message " << msg->type();
909 reply->set_reply_error();
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900910 }
jam@chromium.org82f52f82010-12-22 05:03:24 +0900911 sender->Send(reply);
darin@chromium.orgb4587d52011-08-27 06:27:30 +0900912 return ok;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900913 }
914
915 template<class T, class Method>
darin@chromium.orgb4587d52011-08-27 06:27:30 +0900916 static bool DispatchDelayReplyWithSendParams(bool ok,
917 const SendParam& send_params,
918 const Message* msg, T* obj,
919 Method func) {
920 Message* reply = SyncMessage::GenerateReply(msg);
921 if (ok) {
brettw79a90902015-05-30 07:15:47 +0900922 base::Tuple<Message&> t = base::MakeRefTuple(*reply);
erg@google.come6ffcb52010-08-18 03:38:24 +0900923 ConnectMessageAndReply(msg, reply);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900924 DispatchToMethod(obj, func, send_params, &t);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900925 } else {
926 NOTREACHED() << "Error deserializing message " << msg->type();
927 reply->set_reply_error();
928 obj->Send(reply);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900929 }
darin@chromium.orgb4587d52011-08-27 06:27:30 +0900930 return ok;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900931 }
932
mikhail.pozdnyakov4c5bdf12015-03-26 21:24:40 +0900933 template <typename... Ts>
934 static void WriteReplyParams(Message* reply, Ts... args) {
935 ReplyParam p(args...);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900936 WriteParam(reply, p);
937 }
938};
939
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900940} // namespace IPC
941
942#endif // IPC_IPC_MESSAGE_UTILS_H_