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