blob: 40dd6706cb0ee93205a21f1b8c57a7b545935e3a [file] [log] [blame]
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef IPC_IPC_MESSAGE_UTILS_H_
6#define IPC_IPC_MESSAGE_UTILS_H_
7
8#include <limits.h>
9#include <stddef.h>
10#include <stdint.h>
11
12#include <algorithm>
13#include <map>
14#include <memory>
15#include <set>
16#include <string>
17#include <tuple>
18#include <vector>
19
20#include "base/containers/small_map.h"
21#include "base/containers/stack_container.h"
22#include "base/files/file.h"
23#include "base/format_macros.h"
24#include "base/memory/scoped_vector.h"
25#include "base/optional.h"
26#include "base/strings/string16.h"
27#include "base/strings/string_util.h"
28#include "base/strings/stringprintf.h"
29#include "build/build_config.h"
Luis Hector Chavez645501c2016-12-28 10:56:26 -080030#include "ipc/ipc_message_start.h"
31#include "ipc/ipc_param_traits.h"
32#include "ipc/ipc_sync_message.h"
33
34namespace base {
35class DictionaryValue;
36class FilePath;
37class ListValue;
38class NullableString16;
39class Time;
40class TimeDelta;
41class TimeTicks;
Jay Civellicfc1eaa2017-08-21 17:18:10 -070042class UnguessableToken;
Luis Hector Chavez645501c2016-12-28 10:56:26 -080043struct FileDescriptor;
44
45#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
46class SharedMemoryHandle;
47#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
48}
49
50namespace IPC {
51
52struct ChannelHandle;
53
54// -----------------------------------------------------------------------------
55// How we send IPC message logs across channels.
56struct IPC_EXPORT LogData {
57 LogData();
58 LogData(const LogData& other);
59 ~LogData();
60
61 std::string channel;
62 int32_t routing_id;
63 uint32_t type; // "User-defined" message type, from ipc_message.h.
64 std::string flags;
65 int64_t sent; // Time that the message was sent (i.e. at Send()).
66 int64_t receive; // Time before it was dispatched (i.e. before calling
67 // OnMessageReceived).
68 int64_t dispatch; // Time after it was dispatched (i.e. after calling
69 // OnMessageReceived).
70 std::string message_name;
71 std::string params;
72};
73
74//-----------------------------------------------------------------------------
75
76// A dummy struct to place first just to allow leading commas for all
77// members in the macro-generated constructor initializer lists.
78struct NoParams {
79};
80
81// Specializations are checked by 'IPC checker' part of find-bad-constructs
82// Clang plugin (see WriteParam() below for the details).
83template <typename... Ts>
84struct CheckedTuple {
85 typedef std::tuple<Ts...> Tuple;
86};
87
88template <class P>
89static inline void GetParamSize(base::PickleSizer* sizer, const P& p) {
90 typedef typename SimilarTypeTraits<P>::Type Type;
91 ParamTraits<Type>::GetSize(sizer, static_cast<const Type&>(p));
92}
93
94// This function is checked by 'IPC checker' part of find-bad-constructs
95// Clang plugin to make it's not called on the following types:
96// 1. long / unsigned long (but not typedefs to)
97// 2. intmax_t, uintmax_t, intptr_t, uintptr_t, wint_t,
98// size_t, rsize_t, ssize_t, ptrdiff_t, dev_t, off_t, clock_t,
99// time_t, suseconds_t (including typedefs to)
100// 3. Any template referencing types above (e.g. std::vector<size_t>)
101template <class P>
102static inline void WriteParam(base::Pickle* m, const P& p) {
103 typedef typename SimilarTypeTraits<P>::Type Type;
104 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
105}
106
107template <class P>
108static inline bool WARN_UNUSED_RESULT ReadParam(const base::Pickle* m,
109 base::PickleIterator* iter,
110 P* p) {
111 typedef typename SimilarTypeTraits<P>::Type Type;
112 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
113}
114
115template <class P>
116static inline void LogParam(const P& p, std::string* l) {
117 typedef typename SimilarTypeTraits<P>::Type Type;
118 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
119}
120
121// Primitive ParamTraits -------------------------------------------------------
122
123template <>
124struct ParamTraits<bool> {
125 typedef bool param_type;
126 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
127 sizer->AddBool();
128 }
129 static void Write(base::Pickle* m, const param_type& p) { m->WriteBool(p); }
130 static bool Read(const base::Pickle* m,
131 base::PickleIterator* iter,
132 param_type* r) {
133 return iter->ReadBool(r);
134 }
135 IPC_EXPORT static void Log(const param_type& p, std::string* l);
136};
137
138template <>
139struct IPC_EXPORT ParamTraits<signed char> {
140 typedef signed char param_type;
141 static void GetSize(base::PickleSizer* sizer, const param_type& p);
142 static void Write(base::Pickle* m, const param_type& p);
143 static bool Read(const base::Pickle* m,
144 base::PickleIterator* iter,
145 param_type* r);
146 static void Log(const param_type& p, std::string* l);
147};
148
149template <>
150struct IPC_EXPORT ParamTraits<unsigned char> {
151 typedef unsigned char param_type;
152 static void GetSize(base::PickleSizer* sizer, const param_type& p);
153 static void Write(base::Pickle* m, const param_type& p);
154 static bool Read(const base::Pickle* m,
155 base::PickleIterator* iter,
156 param_type* r);
157 static void Log(const param_type& p, std::string* l);
158};
159
160template <>
161struct IPC_EXPORT ParamTraits<unsigned short> {
162 typedef unsigned short param_type;
163 static void GetSize(base::PickleSizer* sizer, const param_type& p);
164 static void Write(base::Pickle* m, const param_type& p);
165 static bool Read(const base::Pickle* m,
166 base::PickleIterator* iter,
167 param_type* r);
168 static void Log(const param_type& p, std::string* l);
169};
170
171template <>
172struct ParamTraits<int> {
173 typedef int param_type;
174 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
175 sizer->AddInt();
176 }
177 static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); }
178 static bool Read(const base::Pickle* m,
179 base::PickleIterator* iter,
180 param_type* r) {
181 return iter->ReadInt(r);
182 }
183 IPC_EXPORT static void Log(const param_type& p, std::string* l);
184};
185
186template <>
187struct ParamTraits<unsigned int> {
188 typedef unsigned int param_type;
189 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
190 sizer->AddInt();
191 }
192 static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); }
193 static bool Read(const base::Pickle* m,
194 base::PickleIterator* iter,
195 param_type* r) {
196 return iter->ReadInt(reinterpret_cast<int*>(r));
197 }
198 IPC_EXPORT static void Log(const param_type& p, std::string* l);
199};
200
201// long isn't safe to send over IPC because it's 4 bytes on 32 bit builds but
202// 8 bytes on 64 bit builds. So if a 32 bit and 64 bit process have a channel
203// that would cause problem.
204// We need to keep this on for a few configs:
205// 1) Windows because DWORD is typedef'd to it, which is fine because we have
206// very few IPCs that cross this boundary.
207// 2) We also need to keep it for Linux for two reasons: int64_t is typedef'd
208// to long, and gfx::PluginWindow is long and is used in one GPU IPC.
209// 3) Android 64 bit also has int64_t typedef'd to long.
210// Since we want to support Android 32<>64 bit IPC, as long as we don't have
211// these traits for 32 bit ARM then that'll catch any errors.
212#if defined(OS_WIN) || defined(OS_LINUX) || \
213 (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS))
214template <>
215struct ParamTraits<long> {
216 typedef long param_type;
217 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
218 sizer->AddLong();
219 }
220 static void Write(base::Pickle* m, const param_type& p) {
221 m->WriteLong(p);
222 }
223 static bool Read(const base::Pickle* m,
224 base::PickleIterator* iter,
225 param_type* r) {
226 return iter->ReadLong(r);
227 }
228 IPC_EXPORT static void Log(const param_type& p, std::string* l);
229};
230
231template <>
232struct ParamTraits<unsigned long> {
233 typedef unsigned long param_type;
234 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
235 sizer->AddLong();
236 }
237 static void Write(base::Pickle* m, const param_type& p) {
238 m->WriteLong(p);
239 }
240 static bool Read(const base::Pickle* m,
241 base::PickleIterator* iter,
242 param_type* r) {
243 return iter->ReadLong(reinterpret_cast<long*>(r));
244 }
245 IPC_EXPORT static void Log(const param_type& p, std::string* l);
246};
247#endif
248
249template <>
250struct ParamTraits<long long> {
251 typedef long long param_type;
252 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
253 sizer->AddInt64();
254 }
255 static void Write(base::Pickle* m, const param_type& p) {
256 m->WriteInt64(static_cast<int64_t>(p));
257 }
258 static bool Read(const base::Pickle* m,
259 base::PickleIterator* iter,
260 param_type* r) {
261 return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
262 }
263 IPC_EXPORT static void Log(const param_type& p, std::string* l);
264};
265
266template <>
267struct ParamTraits<unsigned long long> {
268 typedef unsigned long long param_type;
269 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
270 sizer->AddInt64();
271 }
272 static void Write(base::Pickle* m, const param_type& p) { m->WriteInt64(p); }
273 static bool Read(const base::Pickle* m,
274 base::PickleIterator* iter,
275 param_type* r) {
276 return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
277 }
278 IPC_EXPORT static void Log(const param_type& p, std::string* l);
279};
280
281// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
282// should be sure to check the sanity of these values after receiving them over
283// IPC.
284template <>
285struct IPC_EXPORT ParamTraits<float> {
286 typedef float param_type;
287 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
288 sizer->AddFloat();
289 }
290 static void Write(base::Pickle* m, const param_type& p) { m->WriteFloat(p); }
291 static bool Read(const base::Pickle* m,
292 base::PickleIterator* iter,
293 param_type* r) {
294 return iter->ReadFloat(r);
295 }
296 static void Log(const param_type& p, std::string* l);
297};
298
299template <>
300struct IPC_EXPORT ParamTraits<double> {
301 typedef double param_type;
302 static void GetSize(base::PickleSizer* sizer, const param_type& p);
303 static void Write(base::Pickle* m, const param_type& p);
304 static bool Read(const base::Pickle* m,
305 base::PickleIterator* iter,
306 param_type* r);
307 static void Log(const param_type& p, std::string* l);
308};
309
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700310template <class P, size_t Size>
311struct ParamTraits<P[Size]> {
312 using param_type = P[Size];
313 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
314 for (const P& element : p)
315 GetParamSize(sizer, element);
316 }
317 static void Write(base::Pickle* m, const param_type& p) {
318 for (const P& element : p)
319 WriteParam(m, element);
320 }
321 static bool Read(const base::Pickle* m,
322 base::PickleIterator* iter,
323 param_type* r) {
324 for (P& element : *r) {
325 if (!ReadParam(m, iter, &element))
326 return false;
327 }
328 return true;
329 }
330 static void Log(const param_type& p, std::string* l) {
331 l->append("[");
332 for (const P& element : p) {
333 if (&element != &p[0])
334 l->append(" ");
335 LogParam(element, l);
336 }
337 l->append("]");
338 }
339};
340
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800341// STL ParamTraits -------------------------------------------------------------
342
343template <>
344struct ParamTraits<std::string> {
345 typedef std::string param_type;
346 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
347 sizer->AddString(p);
348 }
349 static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); }
350 static bool Read(const base::Pickle* m,
351 base::PickleIterator* iter,
352 param_type* r) {
353 return iter->ReadString(r);
354 }
355 IPC_EXPORT static void Log(const param_type& p, std::string* l);
356};
357
358template <>
359struct ParamTraits<base::string16> {
360 typedef base::string16 param_type;
361 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
362 sizer->AddString16(p);
363 }
364 static void Write(base::Pickle* m, const param_type& p) {
365 m->WriteString16(p);
366 }
367 static bool Read(const base::Pickle* m,
368 base::PickleIterator* iter,
369 param_type* r) {
370 return iter->ReadString16(r);
371 }
372 IPC_EXPORT static void Log(const param_type& p, std::string* l);
373};
374
375template <>
376struct IPC_EXPORT ParamTraits<std::vector<char> > {
377 typedef std::vector<char> param_type;
378 static void GetSize(base::PickleSizer* sizer, const param_type& p);
379 static void Write(base::Pickle* m, const param_type& p);
380 static bool Read(const base::Pickle*,
381 base::PickleIterator* iter,
382 param_type* r);
383 static void Log(const param_type& p, std::string* l);
384};
385
386template <>
387struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
388 typedef std::vector<unsigned char> param_type;
389 static void GetSize(base::PickleSizer* sizer, const param_type& p);
390 static void Write(base::Pickle* m, const param_type& p);
391 static bool Read(const base::Pickle* m,
392 base::PickleIterator* iter,
393 param_type* r);
394 static void Log(const param_type& p, std::string* l);
395};
396
397template <>
398struct IPC_EXPORT ParamTraits<std::vector<bool> > {
399 typedef std::vector<bool> param_type;
400 static void GetSize(base::PickleSizer* sizer, const param_type& p);
401 static void Write(base::Pickle* m, const param_type& p);
402 static bool Read(const base::Pickle* m,
403 base::PickleIterator* iter,
404 param_type* r);
405 static void Log(const param_type& p, std::string* l);
406};
407
408template <class P>
409struct ParamTraits<std::vector<P>> {
410 typedef std::vector<P> param_type;
411 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
412 GetParamSize(sizer, static_cast<int>(p.size()));
413 for (size_t i = 0; i < p.size(); i++)
414 GetParamSize(sizer, p[i]);
415 }
416 static void Write(base::Pickle* m, const param_type& p) {
417 WriteParam(m, static_cast<int>(p.size()));
418 for (size_t i = 0; i < p.size(); i++)
419 WriteParam(m, p[i]);
420 }
421 static bool Read(const base::Pickle* m,
422 base::PickleIterator* iter,
423 param_type* r) {
424 int size;
425 // ReadLength() checks for < 0 itself.
426 if (!iter->ReadLength(&size))
427 return false;
428 // Resizing beforehand is not safe, see BUG 1006367 for details.
429 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
430 return false;
431 r->resize(size);
432 for (int i = 0; i < size; i++) {
433 if (!ReadParam(m, iter, &(*r)[i]))
434 return false;
435 }
436 return true;
437 }
438 static void Log(const param_type& p, std::string* l) {
439 for (size_t i = 0; i < p.size(); ++i) {
440 if (i != 0)
441 l->append(" ");
442 LogParam((p[i]), l);
443 }
444 }
445};
446
447template <class P>
448struct ParamTraits<std::set<P> > {
449 typedef std::set<P> param_type;
450 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
451 GetParamSize(sizer, static_cast<int>(p.size()));
452 typename param_type::const_iterator iter;
453 for (iter = p.begin(); iter != p.end(); ++iter)
454 GetParamSize(sizer, *iter);
455 }
456 static void Write(base::Pickle* m, const param_type& p) {
457 WriteParam(m, static_cast<int>(p.size()));
458 typename param_type::const_iterator iter;
459 for (iter = p.begin(); iter != p.end(); ++iter)
460 WriteParam(m, *iter);
461 }
462 static bool Read(const base::Pickle* m,
463 base::PickleIterator* iter,
464 param_type* r) {
465 int size;
466 if (!iter->ReadLength(&size))
467 return false;
468 for (int i = 0; i < size; ++i) {
469 P item;
470 if (!ReadParam(m, iter, &item))
471 return false;
472 r->insert(item);
473 }
474 return true;
475 }
476 static void Log(const param_type& p, std::string* l) {
477 l->append("<std::set>");
478 }
479};
480
481template <class K, class V, class C, class A>
482struct ParamTraits<std::map<K, V, C, A> > {
483 typedef std::map<K, V, C, A> param_type;
484 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
485 GetParamSize(sizer, static_cast<int>(p.size()));
486 typename param_type::const_iterator iter;
487 for (iter = p.begin(); iter != p.end(); ++iter) {
488 GetParamSize(sizer, iter->first);
489 GetParamSize(sizer, iter->second);
490 }
491 }
492 static void Write(base::Pickle* m, const param_type& p) {
493 WriteParam(m, static_cast<int>(p.size()));
494 typename param_type::const_iterator iter;
495 for (iter = p.begin(); iter != p.end(); ++iter) {
496 WriteParam(m, iter->first);
497 WriteParam(m, iter->second);
498 }
499 }
500 static bool Read(const base::Pickle* m,
501 base::PickleIterator* iter,
502 param_type* r) {
503 int size;
504 if (!ReadParam(m, iter, &size) || size < 0)
505 return false;
506 for (int i = 0; i < size; ++i) {
507 K k;
508 if (!ReadParam(m, iter, &k))
509 return false;
510 V& value = (*r)[k];
511 if (!ReadParam(m, iter, &value))
512 return false;
513 }
514 return true;
515 }
516 static void Log(const param_type& p, std::string* l) {
517 l->append("<std::map>");
518 }
519};
520
521template <class A, class B>
522struct ParamTraits<std::pair<A, B> > {
523 typedef std::pair<A, B> param_type;
524 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
525 GetParamSize(sizer, p.first);
526 GetParamSize(sizer, p.second);
527 }
528 static void Write(base::Pickle* m, const param_type& p) {
529 WriteParam(m, p.first);
530 WriteParam(m, p.second);
531 }
532 static bool Read(const base::Pickle* m,
533 base::PickleIterator* iter,
534 param_type* r) {
535 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
536 }
537 static void Log(const param_type& p, std::string* l) {
538 l->append("(");
539 LogParam(p.first, l);
540 l->append(", ");
541 LogParam(p.second, l);
542 l->append(")");
543 }
544};
545
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800546// Base ParamTraits ------------------------------------------------------------
547
548template <>
549struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
550 typedef base::DictionaryValue param_type;
551 static void GetSize(base::PickleSizer* sizer, const param_type& p);
552 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);
556 static void Log(const param_type& p, std::string* l);
557};
558
559#if defined(OS_POSIX)
560// FileDescriptors may be serialised over IPC channels on POSIX. On the
561// receiving side, the FileDescriptor is a valid duplicate of the file
562// descriptor which was transmitted: *it is not just a copy of the integer like
563// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
564// this case, the receiving end will see a value of -1. *Zero is a valid file
565// descriptor*.
566//
567// The received file descriptor will have the |auto_close| flag set to true. The
568// code which handles the message is responsible for taking ownership of it.
569// File descriptors are OS resources and must be closed when no longer needed.
570//
571// When sending a file descriptor, the file descriptor must be valid at the time
572// of transmission. Since transmission is not synchronous, one should consider
573// dup()ing any file descriptors to be transmitted and setting the |auto_close|
574// flag, which causes the file descriptor to be closed after writing.
575template<>
576struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
577 typedef base::FileDescriptor param_type;
578 static void GetSize(base::PickleSizer* sizer, const param_type& p);
579 static void Write(base::Pickle* m, const param_type& p);
580 static bool Read(const base::Pickle* m,
581 base::PickleIterator* iter,
582 param_type* r);
583 static void Log(const param_type& p, std::string* l);
584};
585#endif // defined(OS_POSIX)
586
587#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
588template <>
589struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
590 typedef base::SharedMemoryHandle param_type;
591 static void GetSize(base::PickleSizer* sizer, const param_type& p);
592 static void Write(base::Pickle* m, const param_type& p);
593 static bool Read(const base::Pickle* m,
594 base::PickleIterator* iter,
595 param_type* r);
596 static void Log(const param_type& p, std::string* l);
597};
598#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
599
600template <>
601struct IPC_EXPORT ParamTraits<base::FilePath> {
602 typedef base::FilePath param_type;
603 static void GetSize(base::PickleSizer* sizer, const param_type& p);
604 static void Write(base::Pickle* m, const param_type& p);
605 static bool Read(const base::Pickle* m,
606 base::PickleIterator* iter,
607 param_type* r);
608 static void Log(const param_type& p, std::string* l);
609};
610
611template <>
612struct IPC_EXPORT ParamTraits<base::ListValue> {
613 typedef base::ListValue param_type;
614 static void GetSize(base::PickleSizer* sizer, const param_type& p);
615 static void Write(base::Pickle* m, const param_type& p);
616 static bool Read(const base::Pickle* m,
617 base::PickleIterator* iter,
618 param_type* r);
619 static void Log(const param_type& p, std::string* l);
620};
621
622template <>
623struct IPC_EXPORT ParamTraits<base::NullableString16> {
624 typedef base::NullableString16 param_type;
625 static void GetSize(base::PickleSizer* sizer, const param_type& p);
626 static void Write(base::Pickle* m, const param_type& p);
627 static bool Read(const base::Pickle* m,
628 base::PickleIterator* iter,
629 param_type* r);
630 static void Log(const param_type& p, std::string* l);
631};
632
633template <>
634struct IPC_EXPORT ParamTraits<base::File::Info> {
635 typedef base::File::Info param_type;
636 static void GetSize(base::PickleSizer* sizer, const param_type& p);
637 static void Write(base::Pickle* m, const param_type& p);
638 static bool Read(const base::Pickle* m,
639 base::PickleIterator* iter,
640 param_type* r);
641 static void Log(const param_type& p, std::string* l);
642};
643
644template <>
645struct SimilarTypeTraits<base::File::Error> {
646 typedef int Type;
647};
648
649#if defined(OS_WIN)
650template <>
651struct SimilarTypeTraits<HWND> {
652 typedef HANDLE Type;
653};
654#endif // defined(OS_WIN)
655
656template <>
657struct IPC_EXPORT ParamTraits<base::Time> {
658 typedef base::Time param_type;
659 static void GetSize(base::PickleSizer* sizer, const param_type& p);
660 static void Write(base::Pickle* m, const param_type& p);
661 static bool Read(const base::Pickle* m,
662 base::PickleIterator* iter,
663 param_type* r);
664 static void Log(const param_type& p, std::string* l);
665};
666
667template <>
668struct IPC_EXPORT ParamTraits<base::TimeDelta> {
669 typedef base::TimeDelta param_type;
670 static void GetSize(base::PickleSizer* sizer, const param_type& p);
671 static void Write(base::Pickle* m, const param_type& p);
672 static bool Read(const base::Pickle* m,
673 base::PickleIterator* iter,
674 param_type* r);
675 static void Log(const param_type& p, std::string* l);
676};
677
678template <>
679struct IPC_EXPORT ParamTraits<base::TimeTicks> {
680 typedef base::TimeTicks param_type;
681 static void GetSize(base::PickleSizer* sizer, const param_type& p);
682 static void Write(base::Pickle* m, const param_type& p);
683 static bool Read(const base::Pickle* m,
684 base::PickleIterator* iter,
685 param_type* r);
686 static void Log(const param_type& p, std::string* l);
687};
688
689template <>
Jay Civellicfc1eaa2017-08-21 17:18:10 -0700690struct IPC_EXPORT ParamTraits<base::UnguessableToken> {
691 typedef base::UnguessableToken param_type;
692 static void GetSize(base::PickleSizer* sizer, const param_type& p);
693 static void Write(base::Pickle* m, const param_type& p);
694 static bool Read(const base::Pickle* m,
695 base::PickleIterator* iter,
696 param_type* r);
697 static void Log(const param_type& p, std::string* l);
698};
699
700template <>
Luis Hector Chavez645501c2016-12-28 10:56:26 -0800701struct ParamTraits<std::tuple<>> {
702 typedef std::tuple<> param_type;
703 static void GetSize(base::PickleSizer* sizer, const param_type& p) {}
704 static void Write(base::Pickle* m, const param_type& p) {}
705 static bool Read(const base::Pickle* m,
706 base::PickleIterator* iter,
707 param_type* r) {
708 return true;
709 }
710 static void Log(const param_type& p, std::string* l) {
711 }
712};
713
714template <class A>
715struct ParamTraits<std::tuple<A>> {
716 typedef std::tuple<A> param_type;
717 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
718 GetParamSize(sizer, std::get<0>(p));
719 }
720 static void Write(base::Pickle* m, const param_type& p) {
721 WriteParam(m, std::get<0>(p));
722 }
723 static bool Read(const base::Pickle* m,
724 base::PickleIterator* iter,
725 param_type* r) {
726 return ReadParam(m, iter, &std::get<0>(*r));
727 }
728 static void Log(const param_type& p, std::string* l) {
729 LogParam(std::get<0>(p), l);
730 }
731};
732
733template <class A, class B>
734struct ParamTraits<std::tuple<A, B>> {
735 typedef std::tuple<A, B> param_type;
736 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
737 GetParamSize(sizer, std::get<0>(p));
738 GetParamSize(sizer, std::get<1>(p));
739 }
740 static void Write(base::Pickle* m, const param_type& p) {
741 WriteParam(m, std::get<0>(p));
742 WriteParam(m, std::get<1>(p));
743 }
744 static bool Read(const base::Pickle* m,
745 base::PickleIterator* iter,
746 param_type* r) {
747 return (ReadParam(m, iter, &std::get<0>(*r)) &&
748 ReadParam(m, iter, &std::get<1>(*r)));
749 }
750 static void Log(const param_type& p, std::string* l) {
751 LogParam(std::get<0>(p), l);
752 l->append(", ");
753 LogParam(std::get<1>(p), l);
754 }
755};
756
757template <class A, class B, class C>
758struct ParamTraits<std::tuple<A, B, C>> {
759 typedef std::tuple<A, B, C> param_type;
760 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
761 GetParamSize(sizer, std::get<0>(p));
762 GetParamSize(sizer, std::get<1>(p));
763 GetParamSize(sizer, std::get<2>(p));
764 }
765 static void Write(base::Pickle* m, const param_type& p) {
766 WriteParam(m, std::get<0>(p));
767 WriteParam(m, std::get<1>(p));
768 WriteParam(m, std::get<2>(p));
769 }
770 static bool Read(const base::Pickle* m,
771 base::PickleIterator* iter,
772 param_type* r) {
773 return (ReadParam(m, iter, &std::get<0>(*r)) &&
774 ReadParam(m, iter, &std::get<1>(*r)) &&
775 ReadParam(m, iter, &std::get<2>(*r)));
776 }
777 static void Log(const param_type& p, std::string* l) {
778 LogParam(std::get<0>(p), l);
779 l->append(", ");
780 LogParam(std::get<1>(p), l);
781 l->append(", ");
782 LogParam(std::get<2>(p), l);
783 }
784};
785
786template <class A, class B, class C, class D>
787struct ParamTraits<std::tuple<A, B, C, D>> {
788 typedef std::tuple<A, B, C, D> param_type;
789 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
790 GetParamSize(sizer, std::get<0>(p));
791 GetParamSize(sizer, std::get<1>(p));
792 GetParamSize(sizer, std::get<2>(p));
793 GetParamSize(sizer, std::get<3>(p));
794 }
795 static void Write(base::Pickle* m, const param_type& p) {
796 WriteParam(m, std::get<0>(p));
797 WriteParam(m, std::get<1>(p));
798 WriteParam(m, std::get<2>(p));
799 WriteParam(m, std::get<3>(p));
800 }
801 static bool Read(const base::Pickle* m,
802 base::PickleIterator* iter,
803 param_type* r) {
804 return (ReadParam(m, iter, &std::get<0>(*r)) &&
805 ReadParam(m, iter, &std::get<1>(*r)) &&
806 ReadParam(m, iter, &std::get<2>(*r)) &&
807 ReadParam(m, iter, &std::get<3>(*r)));
808 }
809 static void Log(const param_type& p, std::string* l) {
810 LogParam(std::get<0>(p), l);
811 l->append(", ");
812 LogParam(std::get<1>(p), l);
813 l->append(", ");
814 LogParam(std::get<2>(p), l);
815 l->append(", ");
816 LogParam(std::get<3>(p), l);
817 }
818};
819
820template <class A, class B, class C, class D, class E>
821struct ParamTraits<std::tuple<A, B, C, D, E>> {
822 typedef std::tuple<A, B, C, D, E> param_type;
823 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
824 GetParamSize(sizer, std::get<0>(p));
825 GetParamSize(sizer, std::get<1>(p));
826 GetParamSize(sizer, std::get<2>(p));
827 GetParamSize(sizer, std::get<3>(p));
828 GetParamSize(sizer, std::get<4>(p));
829 }
830 static void Write(base::Pickle* m, const param_type& p) {
831 WriteParam(m, std::get<0>(p));
832 WriteParam(m, std::get<1>(p));
833 WriteParam(m, std::get<2>(p));
834 WriteParam(m, std::get<3>(p));
835 WriteParam(m, std::get<4>(p));
836 }
837 static bool Read(const base::Pickle* m,
838 base::PickleIterator* iter,
839 param_type* r) {
840 return (ReadParam(m, iter, &std::get<0>(*r)) &&
841 ReadParam(m, iter, &std::get<1>(*r)) &&
842 ReadParam(m, iter, &std::get<2>(*r)) &&
843 ReadParam(m, iter, &std::get<3>(*r)) &&
844 ReadParam(m, iter, &std::get<4>(*r)));
845 }
846 static void Log(const param_type& p, std::string* l) {
847 LogParam(std::get<0>(p), l);
848 l->append(", ");
849 LogParam(std::get<1>(p), l);
850 l->append(", ");
851 LogParam(std::get<2>(p), l);
852 l->append(", ");
853 LogParam(std::get<3>(p), l);
854 l->append(", ");
855 LogParam(std::get<4>(p), l);
856 }
857};
858
859template<class P>
860struct ParamTraits<ScopedVector<P> > {
861 typedef ScopedVector<P> param_type;
862 static void Write(base::Pickle* m, const param_type& p) {
863 WriteParam(m, static_cast<int>(p.size()));
864 for (size_t i = 0; i < p.size(); i++)
865 WriteParam(m, *p[i]);
866 }
867 static bool Read(const base::Pickle* m,
868 base::PickleIterator* iter,
869 param_type* r) {
870 int size = 0;
871 if (!iter->ReadLength(&size))
872 return false;
873 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
874 return false;
875 r->resize(size);
876 for (int i = 0; i < size; i++) {
877 (*r)[i] = new P();
878 if (!ReadParam(m, iter, (*r)[i]))
879 return false;
880 }
881 return true;
882 }
883 static void Log(const param_type& p, std::string* l) {
884 for (size_t i = 0; i < p.size(); ++i) {
885 if (i != 0)
886 l->append(" ");
887 LogParam(*p[i], l);
888 }
889 }
890};
891
892template <class P, size_t stack_capacity>
893struct ParamTraits<base::StackVector<P, stack_capacity> > {
894 typedef base::StackVector<P, stack_capacity> param_type;
895 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
896 GetParamSize(sizer, static_cast<int>(p->size()));
897 for (size_t i = 0; i < p->size(); i++)
898 GetParamSize(sizer, p[i]);
899 }
900 static void Write(base::Pickle* m, const param_type& p) {
901 WriteParam(m, static_cast<int>(p->size()));
902 for (size_t i = 0; i < p->size(); i++)
903 WriteParam(m, p[i]);
904 }
905 static bool Read(const base::Pickle* m,
906 base::PickleIterator* iter,
907 param_type* r) {
908 int size;
909 // ReadLength() checks for < 0 itself.
910 if (!iter->ReadLength(&size))
911 return false;
912 // Sanity check for the vector size.
913 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
914 return false;
915 P value;
916 for (int i = 0; i < size; i++) {
917 if (!ReadParam(m, iter, &value))
918 return false;
919 (*r)->push_back(value);
920 }
921 return true;
922 }
923 static void Log(const param_type& p, std::string* l) {
924 for (size_t i = 0; i < p->size(); ++i) {
925 if (i != 0)
926 l->append(" ");
927 LogParam((p[i]), l);
928 }
929 }
930};
931
932template <typename NormalMap,
933 int kArraySize,
934 typename EqualKey,
935 typename MapInit>
936struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
937 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
938 typedef typename param_type::key_type K;
939 typedef typename param_type::data_type V;
940 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
941 GetParamSize(sizer, static_cast<int>(p.size()));
942 typename param_type::const_iterator iter;
943 for (iter = p.begin(); iter != p.end(); ++iter) {
944 GetParamSize(sizer, iter->first);
945 GetParamSize(sizer, iter->second);
946 }
947 }
948 static void Write(base::Pickle* m, const param_type& p) {
949 WriteParam(m, static_cast<int>(p.size()));
950 typename param_type::const_iterator iter;
951 for (iter = p.begin(); iter != p.end(); ++iter) {
952 WriteParam(m, iter->first);
953 WriteParam(m, iter->second);
954 }
955 }
956 static bool Read(const base::Pickle* m,
957 base::PickleIterator* iter,
958 param_type* r) {
959 int size;
960 if (!iter->ReadLength(&size))
961 return false;
962 for (int i = 0; i < size; ++i) {
963 K key;
964 if (!ReadParam(m, iter, &key))
965 return false;
966 V& value = (*r)[key];
967 if (!ReadParam(m, iter, &value))
968 return false;
969 }
970 return true;
971 }
972 static void Log(const param_type& p, std::string* l) {
973 l->append("<base::SmallMap>");
974 }
975};
976
977template <class P>
978struct ParamTraits<std::unique_ptr<P>> {
979 typedef std::unique_ptr<P> param_type;
980 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
981 bool valid = !!p;
982 GetParamSize(sizer, valid);
983 if (valid)
984 GetParamSize(sizer, *p);
985 }
986 static void Write(base::Pickle* m, const param_type& p) {
987 bool valid = !!p;
988 WriteParam(m, valid);
989 if (valid)
990 WriteParam(m, *p);
991 }
992 static bool Read(const base::Pickle* m,
993 base::PickleIterator* iter,
994 param_type* r) {
995 bool valid = false;
996 if (!ReadParam(m, iter, &valid))
997 return false;
998
999 if (!valid) {
1000 r->reset();
1001 return true;
1002 }
1003
1004 param_type temp(new P());
1005 if (!ReadParam(m, iter, temp.get()))
1006 return false;
1007
1008 r->swap(temp);
1009 return true;
1010 }
1011 static void Log(const param_type& p, std::string* l) {
1012 if (p)
1013 LogParam(*p, l);
1014 else
1015 l->append("NULL");
1016 }
1017};
1018
1019template <class P>
1020struct ParamTraits<base::Optional<P>> {
1021 typedef base::Optional<P> param_type;
1022 static void GetSize(base::PickleSizer* sizer, const param_type& p) {
1023 const bool is_set = static_cast<bool>(p);
1024 GetParamSize(sizer, is_set);
1025 if (is_set)
1026 GetParamSize(sizer, p.value());
1027 }
1028 static void Write(base::Pickle* m, const param_type& p) {
1029 const bool is_set = static_cast<bool>(p);
1030 WriteParam(m, is_set);
1031 if (is_set)
1032 WriteParam(m, p.value());
1033 }
1034 static bool Read(const base::Pickle* m,
1035 base::PickleIterator* iter,
1036 param_type* r) {
1037 bool is_set = false;
1038 if (!iter->ReadBool(&is_set))
1039 return false;
1040 if (is_set) {
1041 P value;
1042 if (!ReadParam(m, iter, &value))
1043 return false;
1044 *r = std::move(value);
1045 }
1046 return true;
1047 }
1048 static void Log(const param_type& p, std::string* l) {
1049 if (p)
1050 LogParam(p.value(), l);
1051 else
1052 l->append("(unset)");
1053 }
1054};
1055
1056// IPC types ParamTraits -------------------------------------------------------
1057
1058// A ChannelHandle is basically a platform-inspecific wrapper around the
1059// fact that IPC endpoints are handled specially on POSIX. See above comments
1060// on FileDescriptor for more background.
1061template<>
1062struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
1063 typedef ChannelHandle param_type;
1064 static void GetSize(base::PickleSizer* sizer, const param_type& p);
1065 static void Write(base::Pickle* m, const param_type& p);
1066 static bool Read(const base::Pickle* m,
1067 base::PickleIterator* iter,
1068 param_type* r);
1069 static void Log(const param_type& p, std::string* l);
1070};
1071
1072template <>
1073struct IPC_EXPORT ParamTraits<LogData> {
1074 typedef LogData param_type;
1075 static void GetSize(base::PickleSizer* sizer, const param_type& p);
1076 static void Write(base::Pickle* m, const param_type& p);
1077 static bool Read(const base::Pickle* m,
1078 base::PickleIterator* iter,
1079 param_type* r);
1080 static void Log(const param_type& p, std::string* l);
1081};
1082
1083template <>
1084struct IPC_EXPORT ParamTraits<Message> {
1085 static void Write(base::Pickle* m, const Message& p);
1086 static bool Read(const base::Pickle* m,
1087 base::PickleIterator* iter,
1088 Message* r);
1089 static void Log(const Message& p, std::string* l);
1090};
1091
1092// Windows ParamTraits ---------------------------------------------------------
1093
1094#if defined(OS_WIN)
1095template <>
1096struct IPC_EXPORT ParamTraits<HANDLE> {
1097 typedef HANDLE param_type;
1098 static void GetSize(base::PickleSizer* sizer, const param_type& p);
1099 static void Write(base::Pickle* m, const param_type& p);
1100 static bool Read(const base::Pickle* m,
1101 base::PickleIterator* iter,
1102 param_type* r);
1103 static void Log(const param_type& p, std::string* l);
1104};
1105
1106template <>
1107struct IPC_EXPORT ParamTraits<LOGFONT> {
1108 typedef LOGFONT param_type;
1109 static void GetSize(base::PickleSizer* sizer, const param_type& p);
1110 static void Write(base::Pickle* m, const param_type& p);
1111 static bool Read(const base::Pickle* m,
1112 base::PickleIterator* iter,
1113 param_type* r);
1114 static void Log(const param_type& p, std::string* l);
1115};
1116
1117template <>
1118struct IPC_EXPORT ParamTraits<MSG> {
1119 typedef MSG param_type;
1120 static void GetSize(base::PickleSizer* sizer, const param_type& p);
1121 static void Write(base::Pickle* m, const param_type& p);
1122 static bool Read(const base::Pickle* m,
1123 base::PickleIterator* iter,
1124 param_type* r);
1125 static void Log(const param_type& p, std::string* l);
1126};
1127#endif // defined(OS_WIN)
1128
1129//-----------------------------------------------------------------------------
1130// Generic message subclasses
1131
1132// defined in ipc_logging.cc
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001133IPC_EXPORT void GenerateLogData(const Message& message,
1134 LogData* data,
1135 bool get_params);
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001136
1137#if defined(IPC_MESSAGE_LOG_ENABLED)
1138inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
1139 const std::string& output_params = msg->output_params();
1140 if (!l->empty() && !output_params.empty())
1141 l->append(", ");
1142
1143 l->append(output_params);
1144}
1145
1146template <class ReplyParamType>
1147inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1148 const Message* msg) {
1149 if (msg->received_time() != 0) {
1150 std::string output_params;
1151 LogParam(reply_params, &output_params);
1152 msg->set_output_params(output_params);
1153 }
1154}
1155
1156inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
1157 if (msg->sent_time()) {
1158 // Don't log the sync message after dispatch, as we don't have the
1159 // output parameters at that point. Instead, save its data and log it
1160 // with the outgoing reply message when it's sent.
1161 LogData* data = new LogData;
Jay Civellicfc1eaa2017-08-21 17:18:10 -07001162 GenerateLogData(*msg, data, true);
Luis Hector Chavez645501c2016-12-28 10:56:26 -08001163 msg->set_dont_log();
1164 reply->set_sync_log_data(data);
1165 }
1166}
1167#else
1168inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
1169
1170template <class ReplyParamType>
1171inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1172 const Message* msg) {}
1173
1174inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
1175#endif
1176
1177} // namespace IPC
1178
1179#endif // IPC_IPC_MESSAGE_UTILS_H_