1// 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"
30#include "ipc/brokerable_attachment.h"
31#include "ipc/ipc_message_start.h"
32#include "ipc/ipc_param_traits.h"
33#include "ipc/ipc_sync_message.h"
34
35namespace base {
36class DictionaryValue;
37class FilePath;
38class ListValue;
39class NullableString16;
40class Time;
41class TimeDelta;
42class TimeTicks;
43struct 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
310// STL ParamTraits -------------------------------------------------------------
311
312template <>
313struct ParamTraits<std::string> {
314  typedef std::string param_type;
315  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
316    sizer->AddString(p);
317  }
318  static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); }
319  static bool Read(const base::Pickle* m,
320                   base::PickleIterator* iter,
321                   param_type* r) {
322    return iter->ReadString(r);
323  }
324  IPC_EXPORT static void Log(const param_type& p, std::string* l);
325};
326
327template <>
328struct ParamTraits<base::string16> {
329  typedef base::string16 param_type;
330  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
331    sizer->AddString16(p);
332  }
333  static void Write(base::Pickle* m, const param_type& p) {
334    m->WriteString16(p);
335  }
336  static bool Read(const base::Pickle* m,
337                   base::PickleIterator* iter,
338                   param_type* r) {
339    return iter->ReadString16(r);
340  }
341  IPC_EXPORT static void Log(const param_type& p, std::string* l);
342};
343
344template <>
345struct IPC_EXPORT ParamTraits<std::vector<char> > {
346  typedef std::vector<char> param_type;
347  static void GetSize(base::PickleSizer* sizer, const param_type& p);
348  static void Write(base::Pickle* m, const param_type& p);
349  static bool Read(const base::Pickle*,
350                   base::PickleIterator* iter,
351                   param_type* r);
352  static void Log(const param_type& p, std::string* l);
353};
354
355template <>
356struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
357  typedef std::vector<unsigned char> param_type;
358  static void GetSize(base::PickleSizer* sizer, const param_type& p);
359  static void Write(base::Pickle* m, const param_type& p);
360  static bool Read(const base::Pickle* m,
361                   base::PickleIterator* iter,
362                   param_type* r);
363  static void Log(const param_type& p, std::string* l);
364};
365
366template <>
367struct IPC_EXPORT ParamTraits<std::vector<bool> > {
368  typedef std::vector<bool> param_type;
369  static void GetSize(base::PickleSizer* sizer, const param_type& p);
370  static void Write(base::Pickle* m, const param_type& p);
371  static bool Read(const base::Pickle* m,
372                   base::PickleIterator* iter,
373                   param_type* r);
374  static void Log(const param_type& p, std::string* l);
375};
376
377template <class P>
378struct ParamTraits<std::vector<P>> {
379  typedef std::vector<P> param_type;
380  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
381    GetParamSize(sizer, static_cast<int>(p.size()));
382    for (size_t i = 0; i < p.size(); i++)
383      GetParamSize(sizer, p[i]);
384  }
385  static void Write(base::Pickle* m, const param_type& p) {
386    WriteParam(m, static_cast<int>(p.size()));
387    for (size_t i = 0; i < p.size(); i++)
388      WriteParam(m, p[i]);
389  }
390  static bool Read(const base::Pickle* m,
391                   base::PickleIterator* iter,
392                   param_type* r) {
393    int size;
394    // ReadLength() checks for < 0 itself.
395    if (!iter->ReadLength(&size))
396      return false;
397    // Resizing beforehand is not safe, see BUG 1006367 for details.
398    if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
399      return false;
400    r->resize(size);
401    for (int i = 0; i < size; i++) {
402      if (!ReadParam(m, iter, &(*r)[i]))
403        return false;
404    }
405    return true;
406  }
407  static void Log(const param_type& p, std::string* l) {
408    for (size_t i = 0; i < p.size(); ++i) {
409      if (i != 0)
410        l->append(" ");
411      LogParam((p[i]), l);
412    }
413  }
414};
415
416template <class P>
417struct ParamTraits<std::set<P> > {
418  typedef std::set<P> param_type;
419  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
420    GetParamSize(sizer, static_cast<int>(p.size()));
421    typename param_type::const_iterator iter;
422    for (iter = p.begin(); iter != p.end(); ++iter)
423      GetParamSize(sizer, *iter);
424  }
425  static void Write(base::Pickle* m, const param_type& p) {
426    WriteParam(m, static_cast<int>(p.size()));
427    typename param_type::const_iterator iter;
428    for (iter = p.begin(); iter != p.end(); ++iter)
429      WriteParam(m, *iter);
430  }
431  static bool Read(const base::Pickle* m,
432                   base::PickleIterator* iter,
433                   param_type* r) {
434    int size;
435    if (!iter->ReadLength(&size))
436      return false;
437    for (int i = 0; i < size; ++i) {
438      P item;
439      if (!ReadParam(m, iter, &item))
440        return false;
441      r->insert(item);
442    }
443    return true;
444  }
445  static void Log(const param_type& p, std::string* l) {
446    l->append("<std::set>");
447  }
448};
449
450template <class K, class V, class C, class A>
451struct ParamTraits<std::map<K, V, C, A> > {
452  typedef std::map<K, V, C, A> param_type;
453  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
454    GetParamSize(sizer, static_cast<int>(p.size()));
455    typename param_type::const_iterator iter;
456    for (iter = p.begin(); iter != p.end(); ++iter) {
457      GetParamSize(sizer, iter->first);
458      GetParamSize(sizer, iter->second);
459    }
460  }
461  static void Write(base::Pickle* m, const param_type& p) {
462    WriteParam(m, static_cast<int>(p.size()));
463    typename param_type::const_iterator iter;
464    for (iter = p.begin(); iter != p.end(); ++iter) {
465      WriteParam(m, iter->first);
466      WriteParam(m, iter->second);
467    }
468  }
469  static bool Read(const base::Pickle* m,
470                   base::PickleIterator* iter,
471                   param_type* r) {
472    int size;
473    if (!ReadParam(m, iter, &size) || size < 0)
474      return false;
475    for (int i = 0; i < size; ++i) {
476      K k;
477      if (!ReadParam(m, iter, &k))
478        return false;
479      V& value = (*r)[k];
480      if (!ReadParam(m, iter, &value))
481        return false;
482    }
483    return true;
484  }
485  static void Log(const param_type& p, std::string* l) {
486    l->append("<std::map>");
487  }
488};
489
490template <class A, class B>
491struct ParamTraits<std::pair<A, B> > {
492  typedef std::pair<A, B> param_type;
493  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
494    GetParamSize(sizer, p.first);
495    GetParamSize(sizer, p.second);
496  }
497  static void Write(base::Pickle* m, const param_type& p) {
498    WriteParam(m, p.first);
499    WriteParam(m, p.second);
500  }
501  static bool Read(const base::Pickle* m,
502                   base::PickleIterator* iter,
503                   param_type* r) {
504    return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
505  }
506  static void Log(const param_type& p, std::string* l) {
507    l->append("(");
508    LogParam(p.first, l);
509    l->append(", ");
510    LogParam(p.second, l);
511    l->append(")");
512  }
513};
514
515// IPC ParamTraits -------------------------------------------------------------
516template <>
517struct IPC_EXPORT ParamTraits<BrokerableAttachment::AttachmentId> {
518  typedef BrokerableAttachment::AttachmentId param_type;
519  static void Write(base::Pickle* m, const param_type& p);
520  static bool Read(const base::Pickle* m,
521                   base::PickleIterator* iter,
522                   param_type* r);
523  static void Log(const param_type& p, std::string* l);
524};
525
526// Base ParamTraits ------------------------------------------------------------
527
528template <>
529struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
530  typedef base::DictionaryValue param_type;
531  static void GetSize(base::PickleSizer* sizer, const param_type& p);
532  static void Write(base::Pickle* m, const param_type& p);
533  static bool Read(const base::Pickle* m,
534                   base::PickleIterator* iter,
535                   param_type* r);
536  static void Log(const param_type& p, std::string* l);
537};
538
539#if defined(OS_POSIX)
540// FileDescriptors may be serialised over IPC channels on POSIX. On the
541// receiving side, the FileDescriptor is a valid duplicate of the file
542// descriptor which was transmitted: *it is not just a copy of the integer like
543// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
544// this case, the receiving end will see a value of -1. *Zero is a valid file
545// descriptor*.
546//
547// The received file descriptor will have the |auto_close| flag set to true. The
548// code which handles the message is responsible for taking ownership of it.
549// File descriptors are OS resources and must be closed when no longer needed.
550//
551// When sending a file descriptor, the file descriptor must be valid at the time
552// of transmission. Since transmission is not synchronous, one should consider
553// dup()ing any file descriptors to be transmitted and setting the |auto_close|
554// flag, which causes the file descriptor to be closed after writing.
555template<>
556struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
557  typedef base::FileDescriptor param_type;
558  static void GetSize(base::PickleSizer* sizer, const param_type& p);
559  static void Write(base::Pickle* m, const param_type& p);
560  static bool Read(const base::Pickle* m,
561                   base::PickleIterator* iter,
562                   param_type* r);
563  static void Log(const param_type& p, std::string* l);
564};
565#endif  // defined(OS_POSIX)
566
567#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
568template <>
569struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
570  typedef base::SharedMemoryHandle param_type;
571  static void GetSize(base::PickleSizer* sizer, const param_type& p);
572  static void Write(base::Pickle* m, const param_type& p);
573  static bool Read(const base::Pickle* m,
574                   base::PickleIterator* iter,
575                   param_type* r);
576  static void Log(const param_type& p, std::string* l);
577};
578#endif  // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
579
580template <>
581struct IPC_EXPORT ParamTraits<base::FilePath> {
582  typedef base::FilePath param_type;
583  static void GetSize(base::PickleSizer* sizer, const param_type& p);
584  static void Write(base::Pickle* m, const param_type& p);
585  static bool Read(const base::Pickle* m,
586                   base::PickleIterator* iter,
587                   param_type* r);
588  static void Log(const param_type& p, std::string* l);
589};
590
591template <>
592struct IPC_EXPORT ParamTraits<base::ListValue> {
593  typedef base::ListValue param_type;
594  static void GetSize(base::PickleSizer* sizer, const param_type& p);
595  static void Write(base::Pickle* m, const param_type& p);
596  static bool Read(const base::Pickle* m,
597                   base::PickleIterator* iter,
598                   param_type* r);
599  static void Log(const param_type& p, std::string* l);
600};
601
602template <>
603struct IPC_EXPORT ParamTraits<base::NullableString16> {
604  typedef base::NullableString16 param_type;
605  static void GetSize(base::PickleSizer* sizer, const param_type& p);
606  static void Write(base::Pickle* m, const param_type& p);
607  static bool Read(const base::Pickle* m,
608                   base::PickleIterator* iter,
609                   param_type* r);
610  static void Log(const param_type& p, std::string* l);
611};
612
613template <>
614struct IPC_EXPORT ParamTraits<base::File::Info> {
615  typedef base::File::Info param_type;
616  static void GetSize(base::PickleSizer* sizer, const param_type& p);
617  static void Write(base::Pickle* m, const param_type& p);
618  static bool Read(const base::Pickle* m,
619                   base::PickleIterator* iter,
620                   param_type* r);
621  static void Log(const param_type& p, std::string* l);
622};
623
624template <>
625struct SimilarTypeTraits<base::File::Error> {
626  typedef int Type;
627};
628
629#if defined(OS_WIN)
630template <>
631struct SimilarTypeTraits<HWND> {
632  typedef HANDLE Type;
633};
634#endif  // defined(OS_WIN)
635
636template <>
637struct IPC_EXPORT ParamTraits<base::Time> {
638  typedef base::Time param_type;
639  static void GetSize(base::PickleSizer* sizer, const param_type& p);
640  static void Write(base::Pickle* m, const param_type& p);
641  static bool Read(const base::Pickle* m,
642                   base::PickleIterator* iter,
643                   param_type* r);
644  static void Log(const param_type& p, std::string* l);
645};
646
647template <>
648struct IPC_EXPORT ParamTraits<base::TimeDelta> {
649  typedef base::TimeDelta param_type;
650  static void GetSize(base::PickleSizer* sizer, const param_type& p);
651  static void Write(base::Pickle* m, const param_type& p);
652  static bool Read(const base::Pickle* m,
653                   base::PickleIterator* iter,
654                   param_type* r);
655  static void Log(const param_type& p, std::string* l);
656};
657
658template <>
659struct IPC_EXPORT ParamTraits<base::TimeTicks> {
660  typedef base::TimeTicks param_type;
661  static void GetSize(base::PickleSizer* sizer, const param_type& p);
662  static void Write(base::Pickle* m, const param_type& p);
663  static bool Read(const base::Pickle* m,
664                   base::PickleIterator* iter,
665                   param_type* r);
666  static void Log(const param_type& p, std::string* l);
667};
668
669template <>
670struct ParamTraits<std::tuple<>> {
671  typedef std::tuple<> param_type;
672  static void GetSize(base::PickleSizer* sizer, const param_type& p) {}
673  static void Write(base::Pickle* m, const param_type& p) {}
674  static bool Read(const base::Pickle* m,
675                   base::PickleIterator* iter,
676                   param_type* r) {
677    return true;
678  }
679  static void Log(const param_type& p, std::string* l) {
680  }
681};
682
683template <class A>
684struct ParamTraits<std::tuple<A>> {
685  typedef std::tuple<A> param_type;
686  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
687    GetParamSize(sizer, std::get<0>(p));
688  }
689  static void Write(base::Pickle* m, const param_type& p) {
690    WriteParam(m, std::get<0>(p));
691  }
692  static bool Read(const base::Pickle* m,
693                   base::PickleIterator* iter,
694                   param_type* r) {
695    return ReadParam(m, iter, &std::get<0>(*r));
696  }
697  static void Log(const param_type& p, std::string* l) {
698    LogParam(std::get<0>(p), l);
699  }
700};
701
702template <class A, class B>
703struct ParamTraits<std::tuple<A, B>> {
704  typedef std::tuple<A, B> param_type;
705  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
706    GetParamSize(sizer, std::get<0>(p));
707    GetParamSize(sizer, std::get<1>(p));
708  }
709  static void Write(base::Pickle* m, const param_type& p) {
710    WriteParam(m, std::get<0>(p));
711    WriteParam(m, std::get<1>(p));
712  }
713  static bool Read(const base::Pickle* m,
714                   base::PickleIterator* iter,
715                   param_type* r) {
716    return (ReadParam(m, iter, &std::get<0>(*r)) &&
717            ReadParam(m, iter, &std::get<1>(*r)));
718  }
719  static void Log(const param_type& p, std::string* l) {
720    LogParam(std::get<0>(p), l);
721    l->append(", ");
722    LogParam(std::get<1>(p), l);
723  }
724};
725
726template <class A, class B, class C>
727struct ParamTraits<std::tuple<A, B, C>> {
728  typedef std::tuple<A, B, C> param_type;
729  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
730    GetParamSize(sizer, std::get<0>(p));
731    GetParamSize(sizer, std::get<1>(p));
732    GetParamSize(sizer, std::get<2>(p));
733  }
734  static void Write(base::Pickle* m, const param_type& p) {
735    WriteParam(m, std::get<0>(p));
736    WriteParam(m, std::get<1>(p));
737    WriteParam(m, std::get<2>(p));
738  }
739  static bool Read(const base::Pickle* m,
740                   base::PickleIterator* iter,
741                   param_type* r) {
742    return (ReadParam(m, iter, &std::get<0>(*r)) &&
743            ReadParam(m, iter, &std::get<1>(*r)) &&
744            ReadParam(m, iter, &std::get<2>(*r)));
745  }
746  static void Log(const param_type& p, std::string* l) {
747    LogParam(std::get<0>(p), l);
748    l->append(", ");
749    LogParam(std::get<1>(p), l);
750    l->append(", ");
751    LogParam(std::get<2>(p), l);
752  }
753};
754
755template <class A, class B, class C, class D>
756struct ParamTraits<std::tuple<A, B, C, D>> {
757  typedef std::tuple<A, B, C, D> param_type;
758  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
759    GetParamSize(sizer, std::get<0>(p));
760    GetParamSize(sizer, std::get<1>(p));
761    GetParamSize(sizer, std::get<2>(p));
762    GetParamSize(sizer, std::get<3>(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    WriteParam(m, std::get<3>(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            ReadParam(m, iter, &std::get<3>(*r)));
777  }
778  static void Log(const param_type& p, std::string* l) {
779    LogParam(std::get<0>(p), l);
780    l->append(", ");
781    LogParam(std::get<1>(p), l);
782    l->append(", ");
783    LogParam(std::get<2>(p), l);
784    l->append(", ");
785    LogParam(std::get<3>(p), l);
786  }
787};
788
789template <class A, class B, class C, class D, class E>
790struct ParamTraits<std::tuple<A, B, C, D, E>> {
791  typedef std::tuple<A, B, C, D, E> param_type;
792  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
793    GetParamSize(sizer, std::get<0>(p));
794    GetParamSize(sizer, std::get<1>(p));
795    GetParamSize(sizer, std::get<2>(p));
796    GetParamSize(sizer, std::get<3>(p));
797    GetParamSize(sizer, std::get<4>(p));
798  }
799  static void Write(base::Pickle* m, const param_type& p) {
800    WriteParam(m, std::get<0>(p));
801    WriteParam(m, std::get<1>(p));
802    WriteParam(m, std::get<2>(p));
803    WriteParam(m, std::get<3>(p));
804    WriteParam(m, std::get<4>(p));
805  }
806  static bool Read(const base::Pickle* m,
807                   base::PickleIterator* iter,
808                   param_type* r) {
809    return (ReadParam(m, iter, &std::get<0>(*r)) &&
810            ReadParam(m, iter, &std::get<1>(*r)) &&
811            ReadParam(m, iter, &std::get<2>(*r)) &&
812            ReadParam(m, iter, &std::get<3>(*r)) &&
813            ReadParam(m, iter, &std::get<4>(*r)));
814  }
815  static void Log(const param_type& p, std::string* l) {
816    LogParam(std::get<0>(p), l);
817    l->append(", ");
818    LogParam(std::get<1>(p), l);
819    l->append(", ");
820    LogParam(std::get<2>(p), l);
821    l->append(", ");
822    LogParam(std::get<3>(p), l);
823    l->append(", ");
824    LogParam(std::get<4>(p), l);
825  }
826};
827
828template<class P>
829struct ParamTraits<ScopedVector<P> > {
830  typedef ScopedVector<P> param_type;
831  static void Write(base::Pickle* m, const param_type& p) {
832    WriteParam(m, static_cast<int>(p.size()));
833    for (size_t i = 0; i < p.size(); i++)
834      WriteParam(m, *p[i]);
835  }
836  static bool Read(const base::Pickle* m,
837                   base::PickleIterator* iter,
838                   param_type* r) {
839    int size = 0;
840    if (!iter->ReadLength(&size))
841      return false;
842    if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
843      return false;
844    r->resize(size);
845    for (int i = 0; i < size; i++) {
846      (*r)[i] = new P();
847      if (!ReadParam(m, iter, (*r)[i]))
848        return false;
849    }
850    return true;
851  }
852  static void Log(const param_type& p, std::string* l) {
853    for (size_t i = 0; i < p.size(); ++i) {
854      if (i != 0)
855        l->append(" ");
856      LogParam(*p[i], l);
857    }
858  }
859};
860
861template <class P, size_t stack_capacity>
862struct ParamTraits<base::StackVector<P, stack_capacity> > {
863  typedef base::StackVector<P, stack_capacity> param_type;
864  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
865    GetParamSize(sizer, static_cast<int>(p->size()));
866    for (size_t i = 0; i < p->size(); i++)
867      GetParamSize(sizer, p[i]);
868  }
869  static void Write(base::Pickle* m, const param_type& p) {
870    WriteParam(m, static_cast<int>(p->size()));
871    for (size_t i = 0; i < p->size(); i++)
872      WriteParam(m, p[i]);
873  }
874  static bool Read(const base::Pickle* m,
875                   base::PickleIterator* iter,
876                   param_type* r) {
877    int size;
878    // ReadLength() checks for < 0 itself.
879    if (!iter->ReadLength(&size))
880      return false;
881    // Sanity check for the vector size.
882    if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
883      return false;
884    P value;
885    for (int i = 0; i < size; i++) {
886      if (!ReadParam(m, iter, &value))
887        return false;
888      (*r)->push_back(value);
889    }
890    return true;
891  }
892  static void Log(const param_type& p, std::string* l) {
893    for (size_t i = 0; i < p->size(); ++i) {
894      if (i != 0)
895        l->append(" ");
896      LogParam((p[i]), l);
897    }
898  }
899};
900
901template <typename NormalMap,
902          int kArraySize,
903          typename EqualKey,
904          typename MapInit>
905struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
906  typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
907  typedef typename param_type::key_type K;
908  typedef typename param_type::data_type V;
909  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
910    GetParamSize(sizer, static_cast<int>(p.size()));
911    typename param_type::const_iterator iter;
912    for (iter = p.begin(); iter != p.end(); ++iter) {
913      GetParamSize(sizer, iter->first);
914      GetParamSize(sizer, iter->second);
915    }
916  }
917  static void Write(base::Pickle* m, const param_type& p) {
918    WriteParam(m, static_cast<int>(p.size()));
919    typename param_type::const_iterator iter;
920    for (iter = p.begin(); iter != p.end(); ++iter) {
921      WriteParam(m, iter->first);
922      WriteParam(m, iter->second);
923    }
924  }
925  static bool Read(const base::Pickle* m,
926                   base::PickleIterator* iter,
927                   param_type* r) {
928    int size;
929    if (!iter->ReadLength(&size))
930      return false;
931    for (int i = 0; i < size; ++i) {
932      K key;
933      if (!ReadParam(m, iter, &key))
934        return false;
935      V& value = (*r)[key];
936      if (!ReadParam(m, iter, &value))
937        return false;
938    }
939    return true;
940  }
941  static void Log(const param_type& p, std::string* l) {
942    l->append("<base::SmallMap>");
943  }
944};
945
946template <class P>
947struct ParamTraits<std::unique_ptr<P>> {
948  typedef std::unique_ptr<P> param_type;
949  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
950    bool valid = !!p;
951    GetParamSize(sizer, valid);
952    if (valid)
953      GetParamSize(sizer, *p);
954  }
955  static void Write(base::Pickle* m, const param_type& p) {
956    bool valid = !!p;
957    WriteParam(m, valid);
958    if (valid)
959      WriteParam(m, *p);
960  }
961  static bool Read(const base::Pickle* m,
962                   base::PickleIterator* iter,
963                   param_type* r) {
964    bool valid = false;
965    if (!ReadParam(m, iter, &valid))
966      return false;
967
968    if (!valid) {
969      r->reset();
970      return true;
971    }
972
973    param_type temp(new P());
974    if (!ReadParam(m, iter, temp.get()))
975      return false;
976
977    r->swap(temp);
978    return true;
979  }
980  static void Log(const param_type& p, std::string* l) {
981    if (p)
982      LogParam(*p, l);
983    else
984      l->append("NULL");
985  }
986};
987
988template <class P>
989struct ParamTraits<base::Optional<P>> {
990  typedef base::Optional<P> param_type;
991  static void GetSize(base::PickleSizer* sizer, const param_type& p) {
992    const bool is_set = static_cast<bool>(p);
993    GetParamSize(sizer, is_set);
994    if (is_set)
995      GetParamSize(sizer, p.value());
996  }
997  static void Write(base::Pickle* m, const param_type& p) {
998    const bool is_set = static_cast<bool>(p);
999    WriteParam(m, is_set);
1000    if (is_set)
1001      WriteParam(m, p.value());
1002  }
1003  static bool Read(const base::Pickle* m,
1004                   base::PickleIterator* iter,
1005                   param_type* r) {
1006    bool is_set = false;
1007    if (!iter->ReadBool(&is_set))
1008      return false;
1009    if (is_set) {
1010      P value;
1011      if (!ReadParam(m, iter, &value))
1012        return false;
1013      *r = std::move(value);
1014    }
1015    return true;
1016  }
1017  static void Log(const param_type& p, std::string* l) {
1018    if (p)
1019      LogParam(p.value(), l);
1020    else
1021      l->append("(unset)");
1022  }
1023};
1024
1025// IPC types ParamTraits -------------------------------------------------------
1026
1027// A ChannelHandle is basically a platform-inspecific wrapper around the
1028// fact that IPC endpoints are handled specially on POSIX.  See above comments
1029// on FileDescriptor for more background.
1030template<>
1031struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
1032  typedef ChannelHandle param_type;
1033  static void GetSize(base::PickleSizer* sizer, const param_type& p);
1034  static void Write(base::Pickle* m, const param_type& p);
1035  static bool Read(const base::Pickle* m,
1036                   base::PickleIterator* iter,
1037                   param_type* r);
1038  static void Log(const param_type& p, std::string* l);
1039};
1040
1041template <>
1042struct IPC_EXPORT ParamTraits<LogData> {
1043  typedef LogData param_type;
1044  static void GetSize(base::PickleSizer* sizer, const param_type& p);
1045  static void Write(base::Pickle* m, const param_type& p);
1046  static bool Read(const base::Pickle* m,
1047                   base::PickleIterator* iter,
1048                   param_type* r);
1049  static void Log(const param_type& p, std::string* l);
1050};
1051
1052template <>
1053struct IPC_EXPORT ParamTraits<Message> {
1054  static void Write(base::Pickle* m, const Message& p);
1055  static bool Read(const base::Pickle* m,
1056                   base::PickleIterator* iter,
1057                   Message* r);
1058  static void Log(const Message& p, std::string* l);
1059};
1060
1061// Windows ParamTraits ---------------------------------------------------------
1062
1063#if defined(OS_WIN)
1064template <>
1065struct IPC_EXPORT ParamTraits<HANDLE> {
1066  typedef HANDLE param_type;
1067  static void GetSize(base::PickleSizer* sizer, const param_type& p);
1068  static void Write(base::Pickle* m, const param_type& p);
1069  static bool Read(const base::Pickle* m,
1070                   base::PickleIterator* iter,
1071                   param_type* r);
1072  static void Log(const param_type& p, std::string* l);
1073};
1074
1075template <>
1076struct IPC_EXPORT ParamTraits<LOGFONT> {
1077  typedef LOGFONT param_type;
1078  static void GetSize(base::PickleSizer* sizer, const param_type& p);
1079  static void Write(base::Pickle* m, const param_type& p);
1080  static bool Read(const base::Pickle* m,
1081                   base::PickleIterator* iter,
1082                   param_type* r);
1083  static void Log(const param_type& p, std::string* l);
1084};
1085
1086template <>
1087struct IPC_EXPORT ParamTraits<MSG> {
1088  typedef MSG param_type;
1089  static void GetSize(base::PickleSizer* sizer, const param_type& p);
1090  static void Write(base::Pickle* m, const param_type& p);
1091  static bool Read(const base::Pickle* m,
1092                   base::PickleIterator* iter,
1093                   param_type* r);
1094  static void Log(const param_type& p, std::string* l);
1095};
1096#endif  // defined(OS_WIN)
1097
1098//-----------------------------------------------------------------------------
1099// Generic message subclasses
1100
1101// defined in ipc_logging.cc
1102IPC_EXPORT void GenerateLogData(const std::string& channel,
1103                                const Message& message,
1104                                LogData* data, bool get_params);
1105
1106
1107#if defined(IPC_MESSAGE_LOG_ENABLED)
1108inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
1109  const std::string& output_params = msg->output_params();
1110  if (!l->empty() && !output_params.empty())
1111    l->append(", ");
1112
1113  l->append(output_params);
1114}
1115
1116template <class ReplyParamType>
1117inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1118                                    const Message* msg) {
1119  if (msg->received_time() != 0) {
1120    std::string output_params;
1121    LogParam(reply_params, &output_params);
1122    msg->set_output_params(output_params);
1123  }
1124}
1125
1126inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
1127  if (msg->sent_time()) {
1128    // Don't log the sync message after dispatch, as we don't have the
1129    // output parameters at that point.  Instead, save its data and log it
1130    // with the outgoing reply message when it's sent.
1131    LogData* data = new LogData;
1132    GenerateLogData("", *msg, data, true);
1133    msg->set_dont_log();
1134    reply->set_sync_log_data(data);
1135  }
1136}
1137#else
1138inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
1139
1140template <class ReplyParamType>
1141inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1142                                    const Message* msg) {}
1143
1144inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
1145#endif
1146
1147}  // namespace IPC
1148
1149#endif  // IPC_IPC_MESSAGE_UTILS_H_
1150