blob: 2df1c23c98dad520964f57090e4263b3b7cab1b9 [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
avi2f68ea02015-12-27 02:30:50 +09008#include <limits.h>
avi42ebda42015-12-22 11:39:04 +09009#include <stddef.h>
tfarina1cbfa082015-09-05 03:47:57 +090010#include <stdint.h>
11
jhawkins@chromium.org63c75eb2010-03-09 09:38:41 +090012#include <algorithm>
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090013#include <map>
danakjc3fb6c52016-04-23 13:21:09 +090014#include <memory>
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +090015#include <set>
tfarina@chromium.org439aef62011-03-21 10:07:01 +090016#include <string>
tzika088e352016-03-08 14:47:44 +090017#include <tuple>
Stuart Langley80d7b642017-11-02 12:54:44 +090018#include <unordered_map>
tfarina@chromium.org439aef62011-03-21 10:07:01 +090019#include <vector>
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090020
Ken Rockote6f96f82018-01-23 11:44:39 +090021#include "base/component_export.h"
brettwd3d9de02017-04-20 15:10:20 +090022#include "base/containers/flat_map.h"
jdduke@chromium.org556db8b2014-03-19 05:48:35 +090023#include "base/containers/small_map.h"
miletusd41fe222015-07-24 04:42:36 +090024#include "base/containers/stack_container.h"
rvargas@chromium.org9e469f62014-01-28 06:36:00 +090025#include "base/files/file.h"
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090026#include "base/format_macros.h"
Klaus Weidner22df7652017-11-03 15:24:57 +090027#include "base/memory/shared_memory_handle.h"
brettwd3d9de02017-04-20 15:10:20 +090028#include "base/numerics/safe_conversions.h"
bmcquade11758372016-07-01 22:13:50 +090029#include "base/optional.h"
avi@chromium.orge7eaf392013-06-11 15:32:18 +090030#include "base/strings/string16.h"
31#include "base/strings/string_util.h"
32#include "base/strings/stringprintf.h"
avi42ebda42015-12-22 11:39:04 +090033#include "build/build_config.h"
tsepez@chromium.org4afe8f72012-10-24 08:03:35 +090034#include "ipc/ipc_message_start.h"
erg@google.comb16c8a62010-08-25 05:29:02 +090035#include "ipc/ipc_param_traits.h"
erg@google.combfae8592010-08-17 09:24:54 +090036#include "ipc/ipc_sync_message.h"
erg@google.comcab37e72010-08-14 05:43:58 +090037
erg@google.come6ffcb52010-08-18 03:38:24 +090038namespace base {
dmazzoni@chromium.org13e53652011-07-13 04:15:03 +090039class DictionaryValue;
brettw@chromium.orga7086942013-02-02 14:12:33 +090040class FilePath;
dmazzoni@chromium.org13e53652011-07-13 04:15:03 +090041class ListValue;
avi@chromium.orgd8179652013-06-13 22:47:46 +090042class NullableString16;
erg@google.come6ffcb52010-08-18 03:38:24 +090043class Time;
apatrick@chromium.org519c1c62010-10-22 07:04:52 +090044class TimeDelta;
isherman@chromium.org9952aaf2011-09-03 05:42:04 +090045class TimeTicks;
tguilbert76e690d2016-09-20 06:11:25 +090046class UnguessableToken;
erg@google.come6ffcb52010-08-18 03:38:24 +090047struct FileDescriptor;
48}
49
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090050namespace IPC {
51
erg@google.come6ffcb52010-08-18 03:38:24 +090052struct ChannelHandle;
53
erikchen9a454c12017-04-29 11:24:36 +090054#if defined(OS_WIN)
55class PlatformFileForTransit;
56#endif
57
brettw@chromium.orgce352e52012-06-05 06:18:25 +090058// -----------------------------------------------------------------------------
59// How we send IPC message logs across channels.
Ken Rockote6f96f82018-01-23 11:44:39 +090060struct COMPONENT_EXPORT(IPC) LogData {
brettw@chromium.orgce352e52012-06-05 06:18:25 +090061 LogData();
vmpstrd661bf72016-03-25 05:22:54 +090062 LogData(const LogData& other);
brettw@chromium.orgce352e52012-06-05 06:18:25 +090063 ~LogData();
64
65 std::string channel;
tfarina1cbfa082015-09-05 03:47:57 +090066 int32_t routing_id;
67 uint32_t type; // "User-defined" message type, from ipc_message.h.
brettw@chromium.orgce352e52012-06-05 06:18:25 +090068 std::string flags;
tfarina1cbfa082015-09-05 03:47:57 +090069 int64_t sent; // Time that the message was sent (i.e. at Send()).
70 int64_t receive; // Time before it was dispatched (i.e. before calling
71 // OnMessageReceived).
72 int64_t dispatch; // Time after it was dispatched (i.e. after calling
73 // OnMessageReceived).
brettw@chromium.orgce352e52012-06-05 06:18:25 +090074 std::string message_name;
75 std::string params;
76};
77
agl@chromium.org1c6dcf22009-07-23 08:57:21 +090078//-----------------------------------------------------------------------------
viettrungluu@chromium.orgc3ad0512012-12-18 05:23:47 +090079
tsepez@chromium.org1ac46132011-02-12 03:46:19 +090080// A dummy struct to place first just to allow leading commas for all
81// members in the macro-generated constructor initializer lists.
82struct NoParams {
83};
84
dskibaa789c212016-04-07 00:51:06 +090085// Specializations are checked by 'IPC checker' part of find-bad-constructs
86// Clang plugin (see WriteParam() below for the details).
87template <typename... Ts>
88struct CheckedTuple {
89 typedef std::tuple<Ts...> Tuple;
90};
91
dskibaa789c212016-04-07 00:51:06 +090092// This function is checked by 'IPC checker' part of find-bad-constructs
93// Clang plugin to make it's not called on the following types:
94// 1. long / unsigned long (but not typedefs to)
95// 2. intmax_t, uintmax_t, intptr_t, uintptr_t, wint_t,
96// size_t, rsize_t, ssize_t, ptrdiff_t, dev_t, off_t, clock_t,
97// time_t, suseconds_t (including typedefs to)
98// 3. Any template referencing types above (e.g. std::vector<size_t>)
rockot15c8ac42016-02-05 11:12:32 +090099template <class P>
rockot6dbfea52016-02-04 05:20:16 +0900100static inline void WriteParam(base::Pickle* m, const P& p) {
aa@chromium.org1605b6d2009-08-14 14:43:53 +0900101 typedef typename SimilarTypeTraits<P>::Type Type;
thakis@chromium.orgb13bd1d2010-06-17 03:39:53 +0900102 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900103}
104
105template <class P>
rockot6dbfea52016-02-04 05:20:16 +0900106static inline bool WARN_UNUSED_RESULT ReadParam(const base::Pickle* m,
107 base::PickleIterator* iter,
108 P* p) {
aa@chromium.org1605b6d2009-08-14 14:43:53 +0900109 typedef typename SimilarTypeTraits<P>::Type Type;
110 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900111}
112
113template <class P>
erg@google.com8aca7272010-08-19 03:33:57 +0900114static inline void LogParam(const P& p, std::string* l) {
aa@chromium.org1605b6d2009-08-14 14:43:53 +0900115 typedef typename SimilarTypeTraits<P>::Type Type;
thakis@chromium.orgb13bd1d2010-06-17 03:39:53 +0900116 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900117}
118
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900119// Primitive ParamTraits -------------------------------------------------------
120
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900121template <>
122struct ParamTraits<bool> {
123 typedef bool param_type;
rockot6dbfea52016-02-04 05:20:16 +0900124 static void Write(base::Pickle* m, const param_type& p) { m->WriteBool(p); }
125 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900126 base::PickleIterator* iter,
brettwa4879472015-06-02 16:02:47 +0900127 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900128 return iter->ReadBool(r);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900129 }
Ken Rockote6f96f82018-01-23 11:44:39 +0900130 COMPONENT_EXPORT(IPC) static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900131};
132
133template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900134struct COMPONENT_EXPORT(IPC) ParamTraits<signed char> {
ortuno6e3f7b32015-10-30 09:46:20 +0900135 typedef signed char param_type;
rockot6dbfea52016-02-04 05:20:16 +0900136 static void Write(base::Pickle* m, const param_type& p);
137 static bool Read(const base::Pickle* m,
138 base::PickleIterator* iter,
139 param_type* r);
ortuno6e3f7b32015-10-30 09:46:20 +0900140 static void Log(const param_type& p, std::string* l);
141};
142
143template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900144struct COMPONENT_EXPORT(IPC) ParamTraits<unsigned char> {
jschuh@chromium.orgccd324a2013-07-13 13:42:10 +0900145 typedef unsigned char param_type;
rockot6dbfea52016-02-04 05:20:16 +0900146 static void Write(base::Pickle* m, const param_type& p);
147 static bool Read(const base::Pickle* m,
148 base::PickleIterator* iter,
149 param_type* r);
tsepez@chromium.org09eb95f2013-07-13 08:12:28 +0900150 static void Log(const param_type& p, std::string* l);
151};
152
153template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900154struct COMPONENT_EXPORT(IPC) ParamTraits<unsigned short> {
tsepez@chromium.org09eb95f2013-07-13 08:12:28 +0900155 typedef unsigned short param_type;
rockot6dbfea52016-02-04 05:20:16 +0900156 static void Write(base::Pickle* m, const param_type& p);
157 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900158 base::PickleIterator* iter,
159 param_type* r);
tsepez@chromium.org09eb95f2013-07-13 08:12:28 +0900160 static void Log(const param_type& p, std::string* l);
161};
162
163template <>
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900164struct ParamTraits<int> {
165 typedef int param_type;
rockot6dbfea52016-02-04 05:20:16 +0900166 static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); }
167 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900168 base::PickleIterator* iter,
brettwa4879472015-06-02 16:02:47 +0900169 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900170 return iter->ReadInt(r);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900171 }
Ken Rockote6f96f82018-01-23 11:44:39 +0900172 COMPONENT_EXPORT(IPC) static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900173};
174
175template <>
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900176struct ParamTraits<unsigned int> {
177 typedef unsigned int param_type;
rockot6dbfea52016-02-04 05:20:16 +0900178 static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); }
179 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900180 base::PickleIterator* iter,
brettwa4879472015-06-02 16:02:47 +0900181 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900182 return iter->ReadInt(reinterpret_cast<int*>(r));
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900183 }
Ken Rockote6f96f82018-01-23 11:44:39 +0900184 COMPONENT_EXPORT(IPC) static void Log(const param_type& p, std::string* l);
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900185};
186
jam923e5462016-02-11 05:13:39 +0900187// long isn't safe to send over IPC because it's 4 bytes on 32 bit builds but
188// 8 bytes on 64 bit builds. So if a 32 bit and 64 bit process have a channel
189// that would cause problem.
190// We need to keep this on for a few configs:
191// 1) Windows because DWORD is typedef'd to it, which is fine because we have
192// very few IPCs that cross this boundary.
193// 2) We also need to keep it for Linux for two reasons: int64_t is typedef'd
194// to long, and gfx::PluginWindow is long and is used in one GPU IPC.
Scott Graham3bf3a7e2017-06-20 08:09:33 +0900195// 3) Android 64 bit and Fuchsia also have int64_t typedef'd to long.
jam923e5462016-02-11 05:13:39 +0900196// Since we want to support Android 32<>64 bit IPC, as long as we don't have
197// these traits for 32 bit ARM then that'll catch any errors.
Scott Graham3bf3a7e2017-06-20 08:09:33 +0900198#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_FUCHSIA) || \
jam739d8d12016-02-11 09:50:28 +0900199 (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS))
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900200template <>
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900201struct ParamTraits<long> {
202 typedef long param_type;
rockot6dbfea52016-02-04 05:20:16 +0900203 static void Write(base::Pickle* m, const param_type& p) {
jam923e5462016-02-11 05:13:39 +0900204 m->WriteLong(p);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900205 }
rockot6dbfea52016-02-04 05:20:16 +0900206 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900207 base::PickleIterator* iter,
brettwa4879472015-06-02 16:02:47 +0900208 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900209 return iter->ReadLong(r);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900210 }
Ken Rockote6f96f82018-01-23 11:44:39 +0900211 COMPONENT_EXPORT(IPC) static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900212};
213
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900214template <>
215struct ParamTraits<unsigned long> {
216 typedef unsigned long param_type;
rockot6dbfea52016-02-04 05:20:16 +0900217 static void Write(base::Pickle* m, const param_type& p) {
jam923e5462016-02-11 05:13:39 +0900218 m->WriteLong(p);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900219 }
rockot6dbfea52016-02-04 05:20:16 +0900220 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900221 base::PickleIterator* iter,
brettwa4879472015-06-02 16:02:47 +0900222 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900223 return iter->ReadLong(reinterpret_cast<long*>(r));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900224 }
Ken Rockote6f96f82018-01-23 11:44:39 +0900225 COMPONENT_EXPORT(IPC) static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900226};
jam923e5462016-02-11 05:13:39 +0900227#endif
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900228
229template <>
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900230struct ParamTraits<long long> {
231 typedef long long param_type;
rockot6dbfea52016-02-04 05:20:16 +0900232 static void Write(base::Pickle* m, const param_type& p) {
tfarina1cbfa082015-09-05 03:47:57 +0900233 m->WriteInt64(static_cast<int64_t>(p));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900234 }
rockot6dbfea52016-02-04 05:20:16 +0900235 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900236 base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900237 param_type* r) {
tfarina1cbfa082015-09-05 03:47:57 +0900238 return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900239 }
Ken Rockote6f96f82018-01-23 11:44:39 +0900240 COMPONENT_EXPORT(IPC) static void Log(const param_type& p, std::string* l);
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900241};
242
243template <>
244struct ParamTraits<unsigned long long> {
245 typedef unsigned long long param_type;
rockot6dbfea52016-02-04 05:20:16 +0900246 static void Write(base::Pickle* m, const param_type& p) { m->WriteInt64(p); }
247 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900248 base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900249 param_type* r) {
tfarina1cbfa082015-09-05 03:47:57 +0900250 return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
deanm@chromium.org1543aa72009-07-29 04:35:08 +0900251 }
Ken Rockote6f96f82018-01-23 11:44:39 +0900252 COMPONENT_EXPORT(IPC) static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900253};
254
jeremy@chromium.org4be619f2010-06-17 12:29:26 +0900255// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
256// should be sure to check the sanity of these values after receiving them over
257// IPC.
258template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900259struct COMPONENT_EXPORT(IPC) ParamTraits<float> {
jeremy@chromium.org4be619f2010-06-17 12:29:26 +0900260 typedef float param_type;
rockot6dbfea52016-02-04 05:20:16 +0900261 static void Write(base::Pickle* m, const param_type& p) { m->WriteFloat(p); }
262 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900263 base::PickleIterator* iter,
brettwa4879472015-06-02 16:02:47 +0900264 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900265 return iter->ReadFloat(r);
piman@chromium.orgdd413b42013-10-31 18:27:31 +0900266 }
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900267 static void Log(const param_type& p, std::string* l);
jeremy@chromium.org4be619f2010-06-17 12:29:26 +0900268};
269
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900270template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900271struct COMPONENT_EXPORT(IPC) ParamTraits<double> {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900272 typedef double param_type;
rockot6dbfea52016-02-04 05:20:16 +0900273 static void Write(base::Pickle* m, const param_type& p);
274 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900275 base::PickleIterator* iter,
276 param_type* r);
tsepez@chromium.org3081fac2012-05-31 06:15:57 +0900277 static void Log(const param_type& p, std::string* l);
278};
279
ericrk43a3bd52017-02-11 02:49:35 +0900280template <class P, size_t Size>
281struct ParamTraits<P[Size]> {
282 using param_type = P[Size];
ericrk43a3bd52017-02-11 02:49:35 +0900283 static void Write(base::Pickle* m, const param_type& p) {
284 for (const P& element : p)
285 WriteParam(m, element);
286 }
287 static bool Read(const base::Pickle* m,
288 base::PickleIterator* iter,
289 param_type* r) {
290 for (P& element : *r) {
291 if (!ReadParam(m, iter, &element))
292 return false;
293 }
294 return true;
295 }
296 static void Log(const param_type& p, std::string* l) {
297 l->append("[");
298 for (const P& element : p) {
299 if (&element != &p[0])
300 l->append(" ");
301 LogParam(element, l);
302 }
303 l->append("]");
304 }
305};
306
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900307// STL ParamTraits -------------------------------------------------------------
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900308
309template <>
310struct ParamTraits<std::string> {
311 typedef std::string param_type;
rockot6dbfea52016-02-04 05:20:16 +0900312 static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); }
313 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900314 base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900315 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900316 return iter->ReadString(r);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900317 }
Ken Rockote6f96f82018-01-23 11:44:39 +0900318 COMPONENT_EXPORT(IPC) static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900319};
320
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900321template <>
brettw@chromium.org5b040852013-12-03 09:39:26 +0900322struct ParamTraits<base::string16> {
323 typedef base::string16 param_type;
rockot6dbfea52016-02-04 05:20:16 +0900324 static void Write(base::Pickle* m, const param_type& p) {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900325 m->WriteString16(p);
326 }
rockot6dbfea52016-02-04 05:20:16 +0900327 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900328 base::PickleIterator* iter,
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900329 param_type* r) {
avic9f0ad02014-12-29 08:31:48 +0900330 return iter->ReadString16(r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900331 }
Ken Rockote6f96f82018-01-23 11:44:39 +0900332 COMPONENT_EXPORT(IPC) static void Log(const param_type& p, std::string* l);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900333};
evan@chromium.orga6590362009-07-28 06:09:07 +0900334
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900335template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900336struct COMPONENT_EXPORT(IPC) ParamTraits<std::vector<char>> {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900337 typedef std::vector<char> param_type;
rockot6dbfea52016-02-04 05:20:16 +0900338 static void Write(base::Pickle* m, const param_type& p);
339 static bool Read(const base::Pickle*,
brettwf3146202015-06-03 13:29:25 +0900340 base::PickleIterator* iter,
341 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900342 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900343};
344
bauerb@chromium.org17246c72011-10-06 03:55:42 +0900345template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900346struct COMPONENT_EXPORT(IPC) ParamTraits<std::vector<unsigned char>> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900347 typedef std::vector<unsigned char> param_type;
rockot6dbfea52016-02-04 05:20:16 +0900348 static void Write(base::Pickle* m, const param_type& p);
349 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900350 base::PickleIterator* iter,
351 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900352 static void Log(const param_type& p, std::string* l);
353};
354
355template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900356struct COMPONENT_EXPORT(IPC) ParamTraits<std::vector<bool>> {
bauerb@chromium.org17246c72011-10-06 03:55:42 +0900357 typedef std::vector<bool> param_type;
rockot6dbfea52016-02-04 05:20:16 +0900358 static void Write(base::Pickle* m, const param_type& p);
359 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900360 base::PickleIterator* iter,
361 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900362 static void Log(const param_type& p, std::string* l);
bauerb@chromium.org17246c72011-10-06 03:55:42 +0900363};
364
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900365template <class P>
bmcquade11758372016-07-01 22:13:50 +0900366struct ParamTraits<std::vector<P>> {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900367 typedef std::vector<P> param_type;
rockot6dbfea52016-02-04 05:20:16 +0900368 static void Write(base::Pickle* m, const param_type& p) {
Chris Palmer751d0042017-09-26 07:53:22 +0900369 WriteParam(m, base::checked_cast<int>(p.size()));
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900370 for (size_t i = 0; i < p.size(); i++)
371 WriteParam(m, p[i]);
372 }
rockot6dbfea52016-02-04 05:20:16 +0900373 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900374 base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900375 param_type* r) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900376 int size;
cevans@chromium.org7600d942009-12-31 14:17:23 +0900377 // ReadLength() checks for < 0 itself.
avic9f0ad02014-12-29 08:31:48 +0900378 if (!iter->ReadLength(&size))
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900379 return false;
380 // Resizing beforehand is not safe, see BUG 1006367 for details.
cevans@chromium.org7600d942009-12-31 14:17:23 +0900381 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
382 return false;
383 r->resize(size);
384 for (int i = 0; i < size; i++) {
385 if (!ReadParam(m, iter, &(*r)[i]))
386 return false;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900387 }
388 return true;
389 }
erg@google.com8aca7272010-08-19 03:33:57 +0900390 static void Log(const param_type& p, std::string* l) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900391 for (size_t i = 0; i < p.size(); ++i) {
392 if (i != 0)
erg@google.com8aca7272010-08-19 03:33:57 +0900393 l->append(" ");
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900394 LogParam((p[i]), l);
395 }
396 }
397};
398
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +0900399template <class P>
400struct ParamTraits<std::set<P> > {
401 typedef std::set<P> param_type;
rockot6dbfea52016-02-04 05:20:16 +0900402 static void Write(base::Pickle* m, const param_type& p) {
Chris Palmer751d0042017-09-26 07:53:22 +0900403 WriteParam(m, base::checked_cast<int>(p.size()));
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +0900404 typename param_type::const_iterator iter;
405 for (iter = p.begin(); iter != p.end(); ++iter)
406 WriteParam(m, *iter);
407 }
rockot6dbfea52016-02-04 05:20:16 +0900408 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900409 base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900410 param_type* r) {
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +0900411 int size;
avic9f0ad02014-12-29 08:31:48 +0900412 if (!iter->ReadLength(&size))
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +0900413 return false;
414 for (int i = 0; i < size; ++i) {
415 P item;
416 if (!ReadParam(m, iter, &item))
417 return false;
418 r->insert(item);
419 }
420 return true;
421 }
erg@google.com8aca7272010-08-19 03:33:57 +0900422 static void Log(const param_type& p, std::string* l) {
423 l->append("<std::set>");
mirandac@chromium.orgee262ad2010-05-14 04:10:34 +0900424 }
425};
426
jkarlin45b11f92014-09-24 20:42:37 +0900427template <class K, class V, class C, class A>
428struct ParamTraits<std::map<K, V, C, A> > {
429 typedef std::map<K, V, C, A> param_type;
rockot6dbfea52016-02-04 05:20:16 +0900430 static void Write(base::Pickle* m, const param_type& p) {
Chris Palmer751d0042017-09-26 07:53:22 +0900431 WriteParam(m, base::checked_cast<int>(p.size()));
Stuart Langley80d7b642017-11-02 12:54:44 +0900432 for (const auto& iter : p) {
433 WriteParam(m, iter.first);
434 WriteParam(m, iter.second);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900435 }
436 }
rockot6dbfea52016-02-04 05:20:16 +0900437 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900438 base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900439 param_type* r) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900440 int size;
441 if (!ReadParam(m, iter, &size) || size < 0)
442 return false;
443 for (int i = 0; i < size; ++i) {
444 K k;
445 if (!ReadParam(m, iter, &k))
446 return false;
447 V& value = (*r)[k];
448 if (!ReadParam(m, iter, &value))
449 return false;
450 }
451 return true;
452 }
erg@google.com8aca7272010-08-19 03:33:57 +0900453 static void Log(const param_type& p, std::string* l) {
454 l->append("<std::map>");
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900455 }
456};
457
Stuart Langley80d7b642017-11-02 12:54:44 +0900458template <class K, class V, class C, class A>
459struct ParamTraits<std::unordered_map<K, V, C, A>> {
460 typedef std::unordered_map<K, V, C, A> param_type;
461 static void Write(base::Pickle* m, const param_type& p) {
462 WriteParam(m, base::checked_cast<int>(p.size()));
463 for (const auto& iter : p) {
464 WriteParam(m, iter.first);
465 WriteParam(m, iter.second);
466 }
467 }
468 static bool Read(const base::Pickle* m,
469 base::PickleIterator* iter,
470 param_type* r) {
471 int size;
472 if (!ReadParam(m, iter, &size) || size < 0)
473 return false;
474 for (int i = 0; i < size; ++i) {
475 K k;
476 if (!ReadParam(m, iter, &k))
477 return false;
478 V& value = (*r)[k];
479 if (!ReadParam(m, iter, &value))
480 return false;
481 }
482 return true;
483 }
484 static void Log(const param_type& p, std::string* l) {
485 l->append("<std::unordered_map>");
486 }
487};
488
jam@chromium.org0aa05022009-08-04 11:00:56 +0900489template <class A, class B>
490struct ParamTraits<std::pair<A, B> > {
491 typedef std::pair<A, B> param_type;
rockot6dbfea52016-02-04 05:20:16 +0900492 static void Write(base::Pickle* m, const param_type& p) {
jam@chromium.org0aa05022009-08-04 11:00:56 +0900493 WriteParam(m, p.first);
494 WriteParam(m, p.second);
495 }
rockot6dbfea52016-02-04 05:20:16 +0900496 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900497 base::PickleIterator* iter,
jbates@chromium.org0fc87362012-03-08 05:42:56 +0900498 param_type* r) {
jam@chromium.org0aa05022009-08-04 11:00:56 +0900499 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
500 }
erg@google.com8aca7272010-08-19 03:33:57 +0900501 static void Log(const param_type& p, std::string* l) {
502 l->append("(");
jam@chromium.org0aa05022009-08-04 11:00:56 +0900503 LogParam(p.first, l);
erg@google.com8aca7272010-08-19 03:33:57 +0900504 l->append(", ");
jam@chromium.org0aa05022009-08-04 11:00:56 +0900505 LogParam(p.second, l);
erg@google.com8aca7272010-08-19 03:33:57 +0900506 l->append(")");
jam@chromium.org0aa05022009-08-04 11:00:56 +0900507 }
508};
509
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900510// Base ParamTraits ------------------------------------------------------------
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900511
512template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900513struct COMPONENT_EXPORT(IPC) ParamTraits<base::DictionaryValue> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900514 typedef base::DictionaryValue param_type;
rockot6dbfea52016-02-04 05:20:16 +0900515 static void Write(base::Pickle* m, const param_type& p);
516 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900517 base::PickleIterator* iter,
518 param_type* r);
erg@google.com8aca7272010-08-19 03:33:57 +0900519 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900520};
521
522#if defined(OS_POSIX)
523// FileDescriptors may be serialised over IPC channels on POSIX. On the
524// receiving side, the FileDescriptor is a valid duplicate of the file
525// descriptor which was transmitted: *it is not just a copy of the integer like
526// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
527// this case, the receiving end will see a value of -1. *Zero is a valid file
528// descriptor*.
529//
530// The received file descriptor will have the |auto_close| flag set to true. The
531// code which handles the message is responsible for taking ownership of it.
532// File descriptors are OS resources and must be closed when no longer needed.
533//
534// When sending a file descriptor, the file descriptor must be valid at the time
535// of transmission. Since transmission is not synchronous, one should consider
536// dup()ing any file descriptors to be transmitted and setting the |auto_close|
537// flag, which causes the file descriptor to be closed after writing.
Ken Rockote6f96f82018-01-23 11:44:39 +0900538template <>
539struct COMPONENT_EXPORT(IPC) ParamTraits<base::FileDescriptor> {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900540 typedef base::FileDescriptor param_type;
rockot6dbfea52016-02-04 05:20:16 +0900541 static void Write(base::Pickle* m, const param_type& p);
542 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900543 base::PickleIterator* iter,
544 param_type* r);
erg@google.com8aca7272010-08-19 03:33:57 +0900545 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900546};
jhawkins@chromium.org63c75eb2010-03-09 09:38:41 +0900547#endif // defined(OS_POSIX)
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900548
scottmg81491272015-06-20 07:51:00 +0900549template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900550struct COMPONENT_EXPORT(IPC) ParamTraits<base::SharedMemoryHandle> {
scottmg81491272015-06-20 07:51:00 +0900551 typedef base::SharedMemoryHandle param_type;
rockot6dbfea52016-02-04 05:20:16 +0900552 static void Write(base::Pickle* m, const param_type& p);
553 static bool Read(const base::Pickle* m,
554 base::PickleIterator* iter,
555 param_type* r);
scottmg81491272015-06-20 07:51:00 +0900556 static void Log(const param_type& p, std::string* l);
557};
scottmg81491272015-06-20 07:51:00 +0900558
Klaus Weidner22df7652017-11-03 15:24:57 +0900559#if defined(OS_ANDROID)
560template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900561struct COMPONENT_EXPORT(IPC) ParamTraits<base::SharedMemoryHandle::Type> {
Klaus Weidner22df7652017-11-03 15:24:57 +0900562 typedef base::SharedMemoryHandle::Type param_type;
563 static void Write(base::Pickle* m, const param_type& p);
564 static bool Read(const base::Pickle* m,
565 base::PickleIterator* iter,
566 param_type* r);
567 static void Log(const param_type& p, std::string* l);
568};
569#endif
570
erikchen9a454c12017-04-29 11:24:36 +0900571#if defined(OS_WIN)
572template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900573struct COMPONENT_EXPORT(IPC) ParamTraits<PlatformFileForTransit> {
erikchen9a454c12017-04-29 11:24:36 +0900574 typedef PlatformFileForTransit param_type;
erikchen9a454c12017-04-29 11:24:36 +0900575 static void Write(base::Pickle* m, const param_type& p);
576 static bool Read(const base::Pickle* m,
577 base::PickleIterator* iter,
578 param_type* r);
579 static void Log(const param_type& p, std::string* l);
580};
581#endif // defined(OS_WIN)
582
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900583template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900584struct COMPONENT_EXPORT(IPC) ParamTraits<base::FilePath> {
brettw@chromium.orga7086942013-02-02 14:12:33 +0900585 typedef base::FilePath param_type;
rockot6dbfea52016-02-04 05:20:16 +0900586 static void Write(base::Pickle* m, const param_type& p);
587 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900588 base::PickleIterator* iter,
589 param_type* r);
erg@google.com8aca7272010-08-19 03:33:57 +0900590 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900591};
592
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900593template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900594struct COMPONENT_EXPORT(IPC) ParamTraits<base::ListValue> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900595 typedef base::ListValue param_type;
rockot6dbfea52016-02-04 05:20:16 +0900596 static void Write(base::Pickle* m, const param_type& p);
597 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900598 base::PickleIterator* iter,
599 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900600 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900601};
602
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900603template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900604struct COMPONENT_EXPORT(IPC) ParamTraits<base::NullableString16> {
avi@chromium.orgd8179652013-06-13 22:47:46 +0900605 typedef base::NullableString16 param_type;
rockot6dbfea52016-02-04 05:20:16 +0900606 static void Write(base::Pickle* m, const param_type& p);
607 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900608 base::PickleIterator* iter,
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900609 param_type* r);
610 static void Log(const param_type& p, std::string* l);
611};
612
613template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900614struct COMPONENT_EXPORT(IPC) ParamTraits<base::File::Info> {
rvargas@chromium.org9e469f62014-01-28 06:36:00 +0900615 typedef base::File::Info param_type;
rockot6dbfea52016-02-04 05:20:16 +0900616 static void Write(base::Pickle* m, const param_type& p);
617 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900618 base::PickleIterator* iter,
619 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900620 static void Log(const param_type& p, std::string* l);
621};
622
623template <>
rvargas@chromium.org9e469f62014-01-28 06:36:00 +0900624struct SimilarTypeTraits<base::File::Error> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900625 typedef int Type;
626};
627
grt@chromium.orgb9abb172013-03-01 06:46:11 +0900628#if defined(OS_WIN)
629template <>
630struct SimilarTypeTraits<HWND> {
631 typedef HANDLE Type;
632};
633#endif // defined(OS_WIN)
634
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900635template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900636struct COMPONENT_EXPORT(IPC) ParamTraits<base::Time> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900637 typedef base::Time param_type;
rockot6dbfea52016-02-04 05:20:16 +0900638 static void Write(base::Pickle* m, const param_type& p);
639 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900640 base::PickleIterator* iter,
641 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900642 static void Log(const param_type& p, std::string* l);
643};
644
645template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900646struct COMPONENT_EXPORT(IPC) ParamTraits<base::TimeDelta> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900647 typedef base::TimeDelta param_type;
rockot6dbfea52016-02-04 05:20:16 +0900648 static void Write(base::Pickle* m, const param_type& p);
649 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900650 base::PickleIterator* iter,
651 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900652 static void Log(const param_type& p, std::string* l);
653};
654
655template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900656struct COMPONENT_EXPORT(IPC) ParamTraits<base::TimeTicks> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900657 typedef base::TimeTicks param_type;
rockot6dbfea52016-02-04 05:20:16 +0900658 static void Write(base::Pickle* m, const param_type& p);
659 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900660 base::PickleIterator* iter,
661 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900662 static void Log(const param_type& p, std::string* l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900663};
664
665template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900666struct COMPONENT_EXPORT(IPC) ParamTraits<base::UnguessableToken> {
tguilbert76e690d2016-09-20 06:11:25 +0900667 typedef base::UnguessableToken param_type;
tguilbert76e690d2016-09-20 06:11:25 +0900668 static void Write(base::Pickle* m, const param_type& p);
669 static bool Read(const base::Pickle* m,
670 base::PickleIterator* iter,
671 param_type* r);
672 static void Log(const param_type& p, std::string* l);
673};
674
675template <>
tzik51faa092016-02-11 19:24:45 +0900676struct ParamTraits<std::tuple<>> {
677 typedef std::tuple<> param_type;
rockot6dbfea52016-02-04 05:20:16 +0900678 static void Write(base::Pickle* m, const param_type& p) {}
679 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900680 base::PickleIterator* iter,
brettwa4879472015-06-02 16:02:47 +0900681 param_type* r) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900682 return true;
683 }
erg@google.com8aca7272010-08-19 03:33:57 +0900684 static void Log(const param_type& p, std::string* l) {
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900685 }
686};
687
ossue8a97492017-06-22 18:35:39 +0900688template <typename T, int index, int count>
689struct TupleParamTraitsHelper {
690 using Next = TupleParamTraitsHelper<T, index + 1, count>;
691
ossue8a97492017-06-22 18:35:39 +0900692 static void Write(base::Pickle* m, const T& p) {
693 WriteParam(m, std::get<index>(p));
694 Next::Write(m, p);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900695 }
ossue8a97492017-06-22 18:35:39 +0900696
697 static bool Read(const base::Pickle* m, base::PickleIterator* iter, T* r) {
698 return ReadParam(m, iter, &std::get<index>(*r)) && Next::Read(m, iter, r);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900699 }
ossue8a97492017-06-22 18:35:39 +0900700
701 static void Log(const T& p, std::string* l) {
702 LogParam(std::get<index>(p), l);
703 if (index < count - 1)
704 l->append(", ");
705 Next::Log(p, l);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900706 }
707};
708
ossue8a97492017-06-22 18:35:39 +0900709template <typename T, int index>
710struct TupleParamTraitsHelper<T, index, index> {
ossue8a97492017-06-22 18:35:39 +0900711 static void Write(base::Pickle* m, const T& p) {}
712 static bool Read(const base::Pickle* m, base::PickleIterator* iter, T* r) {
713 return true;
rockot15c8ac42016-02-05 11:12:32 +0900714 }
ossue8a97492017-06-22 18:35:39 +0900715 static void Log(const T& p, std::string* l) {}
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900716};
717
ossue8a97492017-06-22 18:35:39 +0900718template <typename... Args>
719struct ParamTraits<std::tuple<Args...>> {
720 using param_type = std::tuple<Args...>;
721 using Helper =
722 TupleParamTraitsHelper<param_type, 0, std::tuple_size<param_type>::value>;
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900723
rockot6dbfea52016-02-04 05:20:16 +0900724 static void Write(base::Pickle* m, const param_type& p) {
ossue8a97492017-06-22 18:35:39 +0900725 Helper::Write(m, p);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900726 }
ossue8a97492017-06-22 18:35:39 +0900727
rockot6dbfea52016-02-04 05:20:16 +0900728 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900729 base::PickleIterator* iter,
brettwa4879472015-06-02 16:02:47 +0900730 param_type* r) {
ossue8a97492017-06-22 18:35:39 +0900731 return Helper::Read(m, iter, r);
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900732 }
ossue8a97492017-06-22 18:35:39 +0900733
734 static void Log(const param_type& p, std::string* l) { Helper::Log(p, l); }
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900735};
736
miletusd41fe222015-07-24 04:42:36 +0900737template <class P, size_t stack_capacity>
738struct ParamTraits<base::StackVector<P, stack_capacity> > {
739 typedef base::StackVector<P, stack_capacity> param_type;
rockot6dbfea52016-02-04 05:20:16 +0900740 static void Write(base::Pickle* m, const param_type& p) {
Chris Palmer751d0042017-09-26 07:53:22 +0900741 WriteParam(m, base::checked_cast<int>(p->size()));
miletusd41fe222015-07-24 04:42:36 +0900742 for (size_t i = 0; i < p->size(); i++)
743 WriteParam(m, p[i]);
744 }
rockot6dbfea52016-02-04 05:20:16 +0900745 static bool Read(const base::Pickle* m,
miletusd41fe222015-07-24 04:42:36 +0900746 base::PickleIterator* iter,
747 param_type* r) {
748 int size;
749 // ReadLength() checks for < 0 itself.
750 if (!iter->ReadLength(&size))
751 return false;
752 // Sanity check for the vector size.
753 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
754 return false;
755 P value;
756 for (int i = 0; i < size; i++) {
757 if (!ReadParam(m, iter, &value))
758 return false;
759 (*r)->push_back(value);
760 }
761 return true;
762 }
763 static void Log(const param_type& p, std::string* l) {
764 for (size_t i = 0; i < p->size(); ++i) {
765 if (i != 0)
766 l->append(" ");
767 LogParam((p[i]), l);
768 }
769 }
770};
771
jdduke@chromium.org556db8b2014-03-19 05:48:35 +0900772template <typename NormalMap,
773 int kArraySize,
774 typename EqualKey,
775 typename MapInit>
brettwd3d9de02017-04-20 15:10:20 +0900776struct ParamTraits<base::small_map<NormalMap, kArraySize, EqualKey, MapInit>> {
777 using param_type = base::small_map<NormalMap, kArraySize, EqualKey, MapInit>;
778 using K = typename param_type::key_type;
779 using V = typename param_type::data_type;
rockot6dbfea52016-02-04 05:20:16 +0900780 static void Write(base::Pickle* m, const param_type& p) {
Chris Palmer751d0042017-09-26 07:53:22 +0900781 WriteParam(m, base::checked_cast<int>(p.size()));
jdduke@chromium.org556db8b2014-03-19 05:48:35 +0900782 typename param_type::const_iterator iter;
783 for (iter = p.begin(); iter != p.end(); ++iter) {
784 WriteParam(m, iter->first);
785 WriteParam(m, iter->second);
786 }
787 }
rockot6dbfea52016-02-04 05:20:16 +0900788 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900789 base::PickleIterator* iter,
brettwa4879472015-06-02 16:02:47 +0900790 param_type* r) {
jdduke@chromium.org556db8b2014-03-19 05:48:35 +0900791 int size;
avic9f0ad02014-12-29 08:31:48 +0900792 if (!iter->ReadLength(&size))
jdduke@chromium.org556db8b2014-03-19 05:48:35 +0900793 return false;
794 for (int i = 0; i < size; ++i) {
795 K key;
796 if (!ReadParam(m, iter, &key))
797 return false;
798 V& value = (*r)[key];
799 if (!ReadParam(m, iter, &value))
800 return false;
801 }
802 return true;
803 }
804 static void Log(const param_type& p, std::string* l) {
brettwd3d9de02017-04-20 15:10:20 +0900805 l->append("<base::small_map>");
806 }
807};
808
809template <class Key, class Mapped, class Compare>
810struct ParamTraits<base::flat_map<Key, Mapped, Compare>> {
811 using param_type = base::flat_map<Key, Mapped, Compare>;
brettwd3d9de02017-04-20 15:10:20 +0900812 static void Write(base::Pickle* m, const param_type& p) {
813 DCHECK(base::IsValueInRangeForNumericType<int>(p.size()));
Chris Palmer751d0042017-09-26 07:53:22 +0900814 WriteParam(m, base::checked_cast<int>(p.size()));
brettwd3d9de02017-04-20 15:10:20 +0900815 for (const auto& iter : p) {
816 WriteParam(m, iter.first);
817 WriteParam(m, iter.second);
818 }
819 }
820 static bool Read(const base::Pickle* m,
821 base::PickleIterator* iter,
822 param_type* r) {
823 int size;
824 if (!iter->ReadLength(&size))
825 return false;
826
827 // Construct by creating in a vector and moving into the flat_map. Properly
828 // serialized flat_maps will be in-order so this will be O(n). Incorrectly
829 // serialized ones will still be handled properly.
830 std::vector<typename param_type::value_type> vect;
831 vect.resize(size);
832 for (int i = 0; i < size; ++i) {
833 if (!ReadParam(m, iter, &vect[i].first))
834 return false;
835 if (!ReadParam(m, iter, &vect[i].second))
836 return false;
837 }
838
839 *r = param_type(std::move(vect), base::KEEP_FIRST_OF_DUPES);
840 return true;
841 }
842 static void Log(const param_type& p, std::string* l) {
843 l->append("<base::flat_map>");
jdduke@chromium.org556db8b2014-03-19 05:48:35 +0900844 }
845};
846
jdduke@chromium.orgc6d80f02014-05-20 11:34:56 +0900847template <class P>
danakjc3fb6c52016-04-23 13:21:09 +0900848struct ParamTraits<std::unique_ptr<P>> {
849 typedef std::unique_ptr<P> param_type;
rockot6dbfea52016-02-04 05:20:16 +0900850 static void Write(base::Pickle* m, const param_type& p) {
jdduke@chromium.orgc6d80f02014-05-20 11:34:56 +0900851 bool valid = !!p;
852 WriteParam(m, valid);
853 if (valid)
854 WriteParam(m, *p);
855 }
rockot6dbfea52016-02-04 05:20:16 +0900856 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900857 base::PickleIterator* iter,
brettwa4879472015-06-02 16:02:47 +0900858 param_type* r) {
jdduke@chromium.orgc6d80f02014-05-20 11:34:56 +0900859 bool valid = false;
860 if (!ReadParam(m, iter, &valid))
861 return false;
862
863 if (!valid) {
864 r->reset();
865 return true;
866 }
867
868 param_type temp(new P());
869 if (!ReadParam(m, iter, temp.get()))
870 return false;
871
872 r->swap(temp);
873 return true;
874 }
875 static void Log(const param_type& p, std::string* l) {
876 if (p)
877 LogParam(*p, l);
878 else
879 l->append("NULL");
880 }
881};
882
bmcquade11758372016-07-01 22:13:50 +0900883template <class P>
884struct ParamTraits<base::Optional<P>> {
885 typedef base::Optional<P> param_type;
bmcquade11758372016-07-01 22:13:50 +0900886 static void Write(base::Pickle* m, const param_type& p) {
887 const bool is_set = static_cast<bool>(p);
888 WriteParam(m, is_set);
889 if (is_set)
890 WriteParam(m, p.value());
891 }
892 static bool Read(const base::Pickle* m,
893 base::PickleIterator* iter,
894 param_type* r) {
895 bool is_set = false;
896 if (!iter->ReadBool(&is_set))
897 return false;
898 if (is_set) {
899 P value;
900 if (!ReadParam(m, iter, &value))
901 return false;
902 *r = std::move(value);
903 }
904 return true;
905 }
906 static void Log(const param_type& p, std::string* l) {
907 if (p)
908 LogParam(p.value(), l);
909 else
910 l->append("(unset)");
911 }
912};
913
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900914// IPC types ParamTraits -------------------------------------------------------
915
916// A ChannelHandle is basically a platform-inspecific wrapper around the
917// fact that IPC endpoints are handled specially on POSIX. See above comments
918// on FileDescriptor for more background.
Ken Rockote6f96f82018-01-23 11:44:39 +0900919template <>
920struct COMPONENT_EXPORT(IPC) ParamTraits<IPC::ChannelHandle> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900921 typedef ChannelHandle param_type;
rockot6dbfea52016-02-04 05:20:16 +0900922 static void Write(base::Pickle* m, const param_type& p);
923 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900924 base::PickleIterator* iter,
925 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900926 static void Log(const param_type& p, std::string* l);
927};
928
929template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900930struct COMPONENT_EXPORT(IPC) ParamTraits<LogData> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900931 typedef LogData param_type;
rockot6dbfea52016-02-04 05:20:16 +0900932 static void Write(base::Pickle* m, const param_type& p);
933 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900934 base::PickleIterator* iter,
935 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900936 static void Log(const param_type& p, std::string* l);
937};
938
939template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900940struct COMPONENT_EXPORT(IPC) ParamTraits<Message> {
rockot6dbfea52016-02-04 05:20:16 +0900941 static void Write(base::Pickle* m, const Message& p);
942 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900943 base::PickleIterator* iter,
944 Message* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900945 static void Log(const Message& p, std::string* l);
946};
947
948// Windows ParamTraits ---------------------------------------------------------
949
950#if defined(OS_WIN)
951template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900952struct COMPONENT_EXPORT(IPC) ParamTraits<HANDLE> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900953 typedef HANDLE param_type;
rockot6dbfea52016-02-04 05:20:16 +0900954 static void Write(base::Pickle* m, const param_type& p);
955 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900956 base::PickleIterator* iter,
957 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900958 static void Log(const param_type& p, std::string* l);
959};
960
961template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900962struct COMPONENT_EXPORT(IPC) ParamTraits<LOGFONT> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900963 typedef LOGFONT param_type;
rockot6dbfea52016-02-04 05:20:16 +0900964 static void Write(base::Pickle* m, const param_type& p);
965 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900966 base::PickleIterator* iter,
967 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900968 static void Log(const param_type& p, std::string* l);
969};
970
971template <>
Ken Rockote6f96f82018-01-23 11:44:39 +0900972struct COMPONENT_EXPORT(IPC) ParamTraits<MSG> {
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900973 typedef MSG param_type;
rockot6dbfea52016-02-04 05:20:16 +0900974 static void Write(base::Pickle* m, const param_type& p);
975 static bool Read(const base::Pickle* m,
brettwf3146202015-06-03 13:29:25 +0900976 base::PickleIterator* iter,
977 param_type* r);
brettw@chromium.orgce352e52012-06-05 06:18:25 +0900978 static void Log(const param_type& p, std::string* l);
979};
980#endif // defined(OS_WIN)
981
agl@chromium.org1c6dcf22009-07-23 08:57:21 +0900982//-----------------------------------------------------------------------------
983// Generic message subclasses
984
erg@google.come6ffcb52010-08-18 03:38:24 +0900985// defined in ipc_logging.cc
Ken Rockote6f96f82018-01-23 11:44:39 +0900986COMPONENT_EXPORT(IPC)
987void GenerateLogData(const Message& message, LogData* data, bool get_params);
erg@google.come6ffcb52010-08-18 03:38:24 +0900988
davidsz3bf38eb2017-05-12 18:19:23 +0900989#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED)
erg@google.com8aca7272010-08-19 03:33:57 +0900990inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
991 const std::string& output_params = msg->output_params();
erg@google.come6ffcb52010-08-18 03:38:24 +0900992 if (!l->empty() && !output_params.empty())
erg@google.com8aca7272010-08-19 03:33:57 +0900993 l->append(", ");
erg@google.come6ffcb52010-08-18 03:38:24 +0900994
995 l->append(output_params);
996}
997
998template <class ReplyParamType>
999inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1000 const Message* msg) {
1001 if (msg->received_time() != 0) {
erg@google.com8aca7272010-08-19 03:33:57 +09001002 std::string output_params;
erg@google.come6ffcb52010-08-18 03:38:24 +09001003 LogParam(reply_params, &output_params);
1004 msg->set_output_params(output_params);
1005 }
1006}
1007
1008inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
1009 if (msg->sent_time()) {
1010 // Don't log the sync message after dispatch, as we don't have the
1011 // output parameters at that point. Instead, save its data and log it
1012 // with the outgoing reply message when it's sent.
1013 LogData* data = new LogData;
sammc65f302f2016-11-15 09:34:36 +09001014 GenerateLogData(*msg, data, true);
erg@google.come6ffcb52010-08-18 03:38:24 +09001015 msg->set_dont_log();
1016 reply->set_sync_log_data(data);
1017 }
1018}
1019#else
erg@google.com8aca7272010-08-19 03:33:57 +09001020inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
erg@google.come6ffcb52010-08-18 03:38:24 +09001021
1022template <class ReplyParamType>
1023inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1024 const Message* msg) {}
1025
1026inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
1027#endif
1028
agl@chromium.org1c6dcf22009-07-23 08:57:21 +09001029} // namespace IPC
1030
1031#endif // IPC_IPC_MESSAGE_UTILS_H_