• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
35 namespace base {
36 class DictionaryValue;
37 class FilePath;
38 class ListValue;
39 class NullableString16;
40 class Time;
41 class TimeDelta;
42 class TimeTicks;
43 struct FileDescriptor;
44 
45 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
46 class SharedMemoryHandle;
47 #endif  // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
48 }
49 
50 namespace IPC {
51 
52 struct ChannelHandle;
53 
54 // -----------------------------------------------------------------------------
55 // How we send IPC message logs across channels.
56 struct 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.
78 struct NoParams {
79 };
80 
81 // Specializations are checked by 'IPC checker' part of find-bad-constructs
82 // Clang plugin (see WriteParam() below for the details).
83 template <typename... Ts>
84 struct CheckedTuple {
85   typedef std::tuple<Ts...> Tuple;
86 };
87 
88 template <class P>
GetParamSize(base::PickleSizer * sizer,const P & p)89 static 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>)
101 template <class P>
WriteParam(base::Pickle * m,const P & p)102 static 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 
107 template <class P>
ReadParam(const base::Pickle * m,base::PickleIterator * iter,P * p)108 static 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 
115 template <class P>
LogParam(const P & p,std::string * l)116 static 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 
123 template <>
124 struct 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 
138 template <>
139 struct 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 
149 template <>
150 struct 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 
160 template <>
161 struct 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 
171 template <>
172 struct 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 
186 template <>
187 struct 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))
214 template <>
215 struct 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 
231 template <>
232 struct 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 
249 template <>
250 struct 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 
266 template <>
267 struct 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.
284 template <>
285 struct 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 
299 template <>
300 struct 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 
312 template <>
313 struct 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 
327 template <>
328 struct 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 
344 template <>
345 struct 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 
355 template <>
356 struct 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 
366 template <>
367 struct 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 
377 template <class P>
378 struct 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 
416 template <class P>
417 struct 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 
450 template <class K, class V, class C, class A>
451 struct 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 
490 template <class A, class B>
491 struct 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 -------------------------------------------------------------
516 template <>
517 struct 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 
528 template <>
529 struct 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.
555 template<>
556 struct 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)
568 template <>
569 struct 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 
580 template <>
581 struct 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 
591 template <>
592 struct 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 
602 template <>
603 struct 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 
613 template <>
614 struct 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 
624 template <>
625 struct SimilarTypeTraits<base::File::Error> {
626   typedef int Type;
627 };
628 
629 #if defined(OS_WIN)
630 template <>
631 struct SimilarTypeTraits<HWND> {
632   typedef HANDLE Type;
633 };
634 #endif  // defined(OS_WIN)
635 
636 template <>
637 struct 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 
647 template <>
648 struct 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 
658 template <>
659 struct 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 
669 template <>
670 struct 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 
683 template <class A>
684 struct 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 
702 template <class A, class B>
703 struct 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 
726 template <class A, class B, class C>
727 struct 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 
755 template <class A, class B, class C, class D>
756 struct 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 
789 template <class A, class B, class C, class D, class E>
790 struct 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 
828 template<class P>
829 struct 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 
861 template <class P, size_t stack_capacity>
862 struct 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 
901 template <typename NormalMap,
902           int kArraySize,
903           typename EqualKey,
904           typename MapInit>
905 struct 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 
946 template <class P>
947 struct 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 
988 template <class P>
989 struct 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.
1030 template<>
1031 struct 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 
1041 template <>
1042 struct 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 
1052 template <>
1053 struct 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)
1064 template <>
1065 struct 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 
1075 template <>
1076 struct 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 
1086 template <>
1087 struct 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
1102 IPC_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)
1108 inline 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 
1116 template <class ReplyParamType>
1117 inline 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 
1126 inline 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
1138 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
1139 
1140 template <class ReplyParamType>
1141 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1142                                     const Message* msg) {}
1143 
1144 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
1145 #endif
1146 
1147 }  // namespace IPC
1148 
1149 #endif  // IPC_IPC_MESSAGE_UTILS_H_
1150