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