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