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