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