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