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.
5 #ifndef IPC_IPC_MESSAGE_UTILS_H_
6 #define IPC_IPC_MESSAGE_UTILS_H_
16 #include "base/containers/small_map.h"
17 #include "base/containers/stack_container.h"
18 #include "base/files/file.h"
19 #include "base/format_macros.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/memory/scoped_vector.h"
22 #include "base/strings/string16.h"
23 #include "base/strings/string_util.h"
24 #include "base/strings/stringprintf.h"
25 #include "base/tuple.h"
26 #include "ipc/brokerable_attachment.h"
27 #include "ipc/ipc_message_start.h"
28 #include "ipc/ipc_param_traits.h"
29 #include "ipc/ipc_sync_message.h"
31 #if defined(COMPILER_GCC)
32 // GCC "helpfully" tries to inline template methods in release mode. Except we
33 // want the majority of the template junk being expanded once in the
34 // implementation file (and only provide the definitions in
35 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
36 // at every call site. Special note: GCC happily accepts the attribute before
37 // the method declaration, but only acts on it if it is after.
38 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
39 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
40 // the introduced noclone attribute, which will create specialized versions of
41 // functions/methods when certain types are constant.
42 // www.gnu.org/software/gcc/gcc-4.5/changes.html
43 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
45 #define IPC_MSG_NOINLINE __attribute__((noinline));
47 #elif defined(COMPILER_MSVC)
48 // MSVC++ doesn't do this.
49 #define IPC_MSG_NOINLINE
51 #error "Please add the noinline property for your new compiler here."
55 class DictionaryValue
;
58 class NullableString16
;
63 struct FileDescriptor
;
65 #if defined(OS_MACOSX) && !defined(OS_IOS)
66 class SharedMemoryHandle
;
67 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
74 // -----------------------------------------------------------------------------
75 // How we send IPC message logs across channels.
76 struct IPC_EXPORT LogData
{
82 uint32_t type
; // "User-defined" message type, from ipc_message.h.
84 int64_t sent
; // Time that the message was sent (i.e. at Send()).
85 int64_t receive
; // Time before it was dispatched (i.e. before calling
86 // OnMessageReceived).
87 int64_t dispatch
; // Time after it was dispatched (i.e. after calling
88 // OnMessageReceived).
89 std::string message_name
;
93 //-----------------------------------------------------------------------------
95 // A dummy struct to place first just to allow leading commas for all
96 // members in the macro-generated constructor initializer lists.
101 static inline void WriteParam(Message
* m
, const P
& p
) {
102 typedef typename SimilarTypeTraits
<P
>::Type Type
;
103 ParamTraits
<Type
>::Write(m
, static_cast<const Type
& >(p
));
107 static inline bool WARN_UNUSED_RESULT
108 ReadParam(const Message
* m
, base::PickleIterator
* iter
, P
* p
) {
109 typedef typename SimilarTypeTraits
<P
>::Type Type
;
110 return ParamTraits
<Type
>::Read(m
, iter
, reinterpret_cast<Type
* >(p
));
114 static inline void LogParam(const P
& p
, std::string
* l
) {
115 typedef typename SimilarTypeTraits
<P
>::Type Type
;
116 ParamTraits
<Type
>::Log(static_cast<const Type
& >(p
), l
);
119 // Primitive ParamTraits -------------------------------------------------------
122 struct ParamTraits
<bool> {
123 typedef bool param_type
;
124 static void Write(Message
* m
, const param_type
& p
) {
127 static bool Read(const Message
* m
,
128 base::PickleIterator
* iter
,
130 return iter
->ReadBool(r
);
132 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
136 struct IPC_EXPORT ParamTraits
<unsigned char> {
137 typedef unsigned char param_type
;
138 static void Write(Message
* m
, const param_type
& p
);
139 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
140 static void Log(const param_type
& p
, std::string
* l
);
144 struct IPC_EXPORT ParamTraits
<unsigned short> {
145 typedef unsigned short param_type
;
146 static void Write(Message
* m
, const param_type
& p
);
147 static bool Read(const Message
* m
,
148 base::PickleIterator
* iter
,
150 static void Log(const param_type
& p
, std::string
* l
);
154 struct ParamTraits
<int> {
155 typedef int param_type
;
156 static void Write(Message
* m
, const param_type
& p
) {
159 static bool Read(const Message
* m
,
160 base::PickleIterator
* iter
,
162 return iter
->ReadInt(r
);
164 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
168 struct ParamTraits
<unsigned int> {
169 typedef unsigned int param_type
;
170 static void Write(Message
* m
, const param_type
& p
) {
173 static bool Read(const Message
* m
,
174 base::PickleIterator
* iter
,
176 return iter
->ReadInt(reinterpret_cast<int*>(r
));
178 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
182 struct ParamTraits
<long> {
183 typedef long param_type
;
184 static void Write(Message
* m
, const param_type
& p
) {
185 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
187 static bool Read(const Message
* m
,
188 base::PickleIterator
* iter
,
190 return iter
->ReadLong(r
);
192 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
196 struct ParamTraits
<unsigned long> {
197 typedef unsigned long param_type
;
198 static void Write(Message
* m
, const param_type
& p
) {
199 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
201 static bool Read(const Message
* m
,
202 base::PickleIterator
* iter
,
204 return iter
->ReadLong(reinterpret_cast<long*>(r
));
206 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
210 struct ParamTraits
<long long> {
211 typedef long long param_type
;
212 static void Write(Message
* m
, const param_type
& p
) {
213 m
->WriteInt64(static_cast<int64_t>(p
));
215 static bool Read(const Message
* m
,
216 base::PickleIterator
* iter
,
218 return iter
->ReadInt64(reinterpret_cast<int64_t*>(r
));
220 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
224 struct ParamTraits
<unsigned long long> {
225 typedef unsigned long long param_type
;
226 static void Write(Message
* m
, const param_type
& p
) {
229 static bool Read(const Message
* m
,
230 base::PickleIterator
* iter
,
232 return iter
->ReadInt64(reinterpret_cast<int64_t*>(r
));
234 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
237 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
238 // should be sure to check the sanity of these values after receiving them over
241 struct IPC_EXPORT ParamTraits
<float> {
242 typedef float param_type
;
243 static void Write(Message
* m
, const param_type
& p
) {
246 static bool Read(const Message
* m
,
247 base::PickleIterator
* iter
,
249 return iter
->ReadFloat(r
);
251 static void Log(const param_type
& p
, std::string
* l
);
255 struct IPC_EXPORT ParamTraits
<double> {
256 typedef double param_type
;
257 static void Write(Message
* m
, const param_type
& p
);
258 static bool Read(const Message
* m
,
259 base::PickleIterator
* iter
,
261 static void Log(const param_type
& p
, std::string
* l
);
264 // STL ParamTraits -------------------------------------------------------------
267 struct ParamTraits
<std::string
> {
268 typedef std::string param_type
;
269 static void Write(Message
* m
, const param_type
& p
) {
272 static bool Read(const Message
* m
,
273 base::PickleIterator
* iter
,
275 return iter
->ReadString(r
);
277 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
281 struct ParamTraits
<base::string16
> {
282 typedef base::string16 param_type
;
283 static void Write(Message
* m
, const param_type
& p
) {
286 static bool Read(const Message
* m
,
287 base::PickleIterator
* iter
,
289 return iter
->ReadString16(r
);
291 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
295 struct IPC_EXPORT ParamTraits
<std::vector
<char> > {
296 typedef std::vector
<char> param_type
;
297 static void Write(Message
* m
, const param_type
& p
);
298 static bool Read(const Message
*,
299 base::PickleIterator
* iter
,
301 static void Log(const param_type
& p
, std::string
* l
);
305 struct IPC_EXPORT ParamTraits
<std::vector
<unsigned char> > {
306 typedef std::vector
<unsigned char> param_type
;
307 static void Write(Message
* m
, const param_type
& p
);
308 static bool Read(const Message
* m
,
309 base::PickleIterator
* iter
,
311 static void Log(const param_type
& p
, std::string
* l
);
315 struct IPC_EXPORT ParamTraits
<std::vector
<bool> > {
316 typedef std::vector
<bool> param_type
;
317 static void Write(Message
* m
, const param_type
& p
);
318 static bool Read(const Message
* m
,
319 base::PickleIterator
* iter
,
321 static void Log(const param_type
& p
, std::string
* l
);
325 struct ParamTraits
<std::vector
<P
> > {
326 typedef std::vector
<P
> param_type
;
327 static void Write(Message
* m
, const param_type
& p
) {
328 WriteParam(m
, static_cast<int>(p
.size()));
329 for (size_t i
= 0; i
< p
.size(); i
++)
332 static bool Read(const Message
* m
,
333 base::PickleIterator
* iter
,
336 // ReadLength() checks for < 0 itself.
337 if (!iter
->ReadLength(&size
))
339 // Resizing beforehand is not safe, see BUG 1006367 for details.
340 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
343 for (int i
= 0; i
< size
; i
++) {
344 if (!ReadParam(m
, iter
, &(*r
)[i
]))
349 static void Log(const param_type
& p
, std::string
* l
) {
350 for (size_t i
= 0; i
< p
.size(); ++i
) {
359 struct ParamTraits
<std::set
<P
> > {
360 typedef std::set
<P
> param_type
;
361 static void Write(Message
* m
, const param_type
& p
) {
362 WriteParam(m
, static_cast<int>(p
.size()));
363 typename
param_type::const_iterator iter
;
364 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
365 WriteParam(m
, *iter
);
367 static bool Read(const Message
* m
,
368 base::PickleIterator
* iter
,
371 if (!iter
->ReadLength(&size
))
373 for (int i
= 0; i
< size
; ++i
) {
375 if (!ReadParam(m
, iter
, &item
))
381 static void Log(const param_type
& p
, std::string
* l
) {
382 l
->append("<std::set>");
386 template <class K
, class V
, class C
, class A
>
387 struct ParamTraits
<std::map
<K
, V
, C
, A
> > {
388 typedef std::map
<K
, V
, C
, A
> param_type
;
389 static void Write(Message
* m
, const param_type
& p
) {
390 WriteParam(m
, static_cast<int>(p
.size()));
391 typename
param_type::const_iterator iter
;
392 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
393 WriteParam(m
, iter
->first
);
394 WriteParam(m
, iter
->second
);
397 static bool Read(const Message
* m
,
398 base::PickleIterator
* iter
,
401 if (!ReadParam(m
, iter
, &size
) || size
< 0)
403 for (int i
= 0; i
< size
; ++i
) {
405 if (!ReadParam(m
, iter
, &k
))
408 if (!ReadParam(m
, iter
, &value
))
413 static void Log(const param_type
& p
, std::string
* l
) {
414 l
->append("<std::map>");
418 template <class A
, class B
>
419 struct ParamTraits
<std::pair
<A
, B
> > {
420 typedef std::pair
<A
, B
> param_type
;
421 static void Write(Message
* m
, const param_type
& p
) {
422 WriteParam(m
, p
.first
);
423 WriteParam(m
, p
.second
);
425 static bool Read(const Message
* m
,
426 base::PickleIterator
* iter
,
428 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
430 static void Log(const param_type
& p
, std::string
* l
) {
432 LogParam(p
.first
, l
);
434 LogParam(p
.second
, l
);
439 // IPC ParamTraits -------------------------------------------------------------
441 struct IPC_EXPORT ParamTraits
<BrokerableAttachment::AttachmentId
> {
442 typedef BrokerableAttachment::AttachmentId param_type
;
443 static void Write(Message
* m
, const param_type
& p
);
444 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
445 static void Log(const param_type
& p
, std::string
* l
);
448 // Base ParamTraits ------------------------------------------------------------
451 struct IPC_EXPORT ParamTraits
<base::DictionaryValue
> {
452 typedef base::DictionaryValue param_type
;
453 static void Write(Message
* m
, const param_type
& p
);
454 static bool Read(const Message
* m
,
455 base::PickleIterator
* iter
,
457 static void Log(const param_type
& p
, std::string
* l
);
460 #if defined(OS_POSIX)
461 // FileDescriptors may be serialised over IPC channels on POSIX. On the
462 // receiving side, the FileDescriptor is a valid duplicate of the file
463 // descriptor which was transmitted: *it is not just a copy of the integer like
464 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
465 // this case, the receiving end will see a value of -1. *Zero is a valid file
468 // The received file descriptor will have the |auto_close| flag set to true. The
469 // code which handles the message is responsible for taking ownership of it.
470 // File descriptors are OS resources and must be closed when no longer needed.
472 // When sending a file descriptor, the file descriptor must be valid at the time
473 // of transmission. Since transmission is not synchronous, one should consider
474 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
475 // flag, which causes the file descriptor to be closed after writing.
477 struct IPC_EXPORT ParamTraits
<base::FileDescriptor
> {
478 typedef base::FileDescriptor param_type
;
479 static void Write(Message
* m
, const param_type
& p
);
480 static bool Read(const Message
* m
,
481 base::PickleIterator
* iter
,
483 static void Log(const param_type
& p
, std::string
* l
);
485 #endif // defined(OS_POSIX)
487 #if defined(OS_MACOSX) && !defined(OS_IOS)
489 struct IPC_EXPORT ParamTraits
<base::SharedMemoryHandle
> {
490 typedef base::SharedMemoryHandle param_type
;
491 static void Write(Message
* m
, const param_type
& p
);
492 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
493 static void Log(const param_type
& p
, std::string
* l
);
498 struct IPC_EXPORT ParamTraits
<base::FilePath
> {
499 typedef base::FilePath param_type
;
500 static void Write(Message
* m
, const param_type
& p
);
501 static bool Read(const Message
* m
,
502 base::PickleIterator
* iter
,
504 static void Log(const param_type
& p
, std::string
* l
);
508 struct IPC_EXPORT ParamTraits
<base::ListValue
> {
509 typedef base::ListValue param_type
;
510 static void Write(Message
* m
, const param_type
& p
);
511 static bool Read(const Message
* m
,
512 base::PickleIterator
* iter
,
514 static void Log(const param_type
& p
, std::string
* l
);
518 struct IPC_EXPORT ParamTraits
<base::NullableString16
> {
519 typedef base::NullableString16 param_type
;
520 static void Write(Message
* m
, const param_type
& p
);
521 static bool Read(const Message
* m
,
522 base::PickleIterator
* iter
,
524 static void Log(const param_type
& p
, std::string
* l
);
528 struct IPC_EXPORT ParamTraits
<base::File::Info
> {
529 typedef base::File::Info param_type
;
530 static void Write(Message
* m
, const param_type
& p
);
531 static bool Read(const Message
* m
,
532 base::PickleIterator
* iter
,
534 static void Log(const param_type
& p
, std::string
* l
);
538 struct SimilarTypeTraits
<base::File::Error
> {
544 struct SimilarTypeTraits
<HWND
> {
547 #endif // defined(OS_WIN)
550 struct IPC_EXPORT ParamTraits
<base::Time
> {
551 typedef base::Time param_type
;
552 static void Write(Message
* m
, const param_type
& p
);
553 static bool Read(const Message
* m
,
554 base::PickleIterator
* iter
,
556 static void Log(const param_type
& p
, std::string
* l
);
560 struct IPC_EXPORT ParamTraits
<base::TimeDelta
> {
561 typedef base::TimeDelta param_type
;
562 static void Write(Message
* m
, const param_type
& p
);
563 static bool Read(const Message
* m
,
564 base::PickleIterator
* iter
,
566 static void Log(const param_type
& p
, std::string
* l
);
570 struct IPC_EXPORT ParamTraits
<base::TimeTicks
> {
571 typedef base::TimeTicks param_type
;
572 static void Write(Message
* m
, const param_type
& p
);
573 static bool Read(const Message
* m
,
574 base::PickleIterator
* iter
,
576 static void Log(const param_type
& p
, std::string
* l
);
580 struct IPC_EXPORT ParamTraits
<base::TraceTicks
> {
581 typedef base::TraceTicks param_type
;
582 static void Write(Message
* m
, const param_type
& p
);
583 static bool Read(const Message
* m
,
584 base::PickleIterator
* iter
,
586 static void Log(const param_type
& p
, std::string
* l
);
590 struct ParamTraits
<base::Tuple
<>> {
591 typedef base::Tuple
<> param_type
;
592 static void Write(Message
* m
, const param_type
& p
) {
594 static bool Read(const Message
* m
,
595 base::PickleIterator
* iter
,
599 static void Log(const param_type
& p
, std::string
* l
) {
604 struct ParamTraits
<base::Tuple
<A
>> {
605 typedef base::Tuple
<A
> param_type
;
606 static void Write(Message
* m
, const param_type
& p
) {
607 WriteParam(m
, base::get
<0>(p
));
609 static bool Read(const Message
* m
,
610 base::PickleIterator
* iter
,
612 return ReadParam(m
, iter
, &base::get
<0>(*r
));
614 static void Log(const param_type
& p
, std::string
* l
) {
615 LogParam(base::get
<0>(p
), l
);
619 template <class A
, class B
>
620 struct ParamTraits
<base::Tuple
<A
, B
>> {
621 typedef base::Tuple
<A
, B
> param_type
;
622 static void Write(Message
* m
, const param_type
& p
) {
623 WriteParam(m
, base::get
<0>(p
));
624 WriteParam(m
, base::get
<1>(p
));
626 static bool Read(const Message
* m
,
627 base::PickleIterator
* iter
,
629 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
630 ReadParam(m
, iter
, &base::get
<1>(*r
)));
632 static void Log(const param_type
& p
, std::string
* l
) {
633 LogParam(base::get
<0>(p
), l
);
635 LogParam(base::get
<1>(p
), l
);
639 template <class A
, class B
, class C
>
640 struct ParamTraits
<base::Tuple
<A
, B
, C
>> {
641 typedef base::Tuple
<A
, B
, C
> param_type
;
642 static void Write(Message
* m
, const param_type
& p
) {
643 WriteParam(m
, base::get
<0>(p
));
644 WriteParam(m
, base::get
<1>(p
));
645 WriteParam(m
, base::get
<2>(p
));
647 static bool Read(const Message
* m
,
648 base::PickleIterator
* iter
,
650 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
651 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
652 ReadParam(m
, iter
, &base::get
<2>(*r
)));
654 static void Log(const param_type
& p
, std::string
* l
) {
655 LogParam(base::get
<0>(p
), l
);
657 LogParam(base::get
<1>(p
), l
);
659 LogParam(base::get
<2>(p
), l
);
663 template <class A
, class B
, class C
, class D
>
664 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
>> {
665 typedef base::Tuple
<A
, B
, C
, D
> param_type
;
666 static void Write(Message
* m
, const param_type
& p
) {
667 WriteParam(m
, base::get
<0>(p
));
668 WriteParam(m
, base::get
<1>(p
));
669 WriteParam(m
, base::get
<2>(p
));
670 WriteParam(m
, base::get
<3>(p
));
672 static bool Read(const Message
* m
,
673 base::PickleIterator
* iter
,
675 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
676 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
677 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
678 ReadParam(m
, iter
, &base::get
<3>(*r
)));
680 static void Log(const param_type
& p
, std::string
* l
) {
681 LogParam(base::get
<0>(p
), l
);
683 LogParam(base::get
<1>(p
), l
);
685 LogParam(base::get
<2>(p
), l
);
687 LogParam(base::get
<3>(p
), l
);
691 template <class A
, class B
, class C
, class D
, class E
>
692 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
, E
>> {
693 typedef base::Tuple
<A
, B
, C
, D
, E
> param_type
;
694 static void Write(Message
* m
, const param_type
& p
) {
695 WriteParam(m
, base::get
<0>(p
));
696 WriteParam(m
, base::get
<1>(p
));
697 WriteParam(m
, base::get
<2>(p
));
698 WriteParam(m
, base::get
<3>(p
));
699 WriteParam(m
, base::get
<4>(p
));
701 static bool Read(const Message
* m
,
702 base::PickleIterator
* iter
,
704 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
705 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
706 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
707 ReadParam(m
, iter
, &base::get
<3>(*r
)) &&
708 ReadParam(m
, iter
, &base::get
<4>(*r
)));
710 static void Log(const param_type
& p
, std::string
* l
) {
711 LogParam(base::get
<0>(p
), l
);
713 LogParam(base::get
<1>(p
), l
);
715 LogParam(base::get
<2>(p
), l
);
717 LogParam(base::get
<3>(p
), l
);
719 LogParam(base::get
<4>(p
), l
);
724 struct ParamTraits
<ScopedVector
<P
> > {
725 typedef ScopedVector
<P
> param_type
;
726 static void Write(Message
* m
, const param_type
& p
) {
727 WriteParam(m
, static_cast<int>(p
.size()));
728 for (size_t i
= 0; i
< p
.size(); i
++)
729 WriteParam(m
, *p
[i
]);
731 static bool Read(const Message
* m
,
732 base::PickleIterator
* iter
,
735 if (!iter
->ReadLength(&size
))
737 if (INT_MAX
/sizeof(P
) <= static_cast<size_t>(size
))
740 for (int i
= 0; i
< size
; i
++) {
742 if (!ReadParam(m
, iter
, (*r
)[i
]))
747 static void Log(const param_type
& p
, std::string
* l
) {
748 for (size_t i
= 0; i
< p
.size(); ++i
) {
756 template <class P
, size_t stack_capacity
>
757 struct ParamTraits
<base::StackVector
<P
, stack_capacity
> > {
758 typedef base::StackVector
<P
, stack_capacity
> param_type
;
759 static void Write(Message
* m
, const param_type
& p
) {
760 WriteParam(m
, static_cast<int>(p
->size()));
761 for (size_t i
= 0; i
< p
->size(); i
++)
764 static bool Read(const Message
* m
,
765 base::PickleIterator
* iter
,
768 // ReadLength() checks for < 0 itself.
769 if (!iter
->ReadLength(&size
))
771 // Sanity check for the vector size.
772 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
775 for (int i
= 0; i
< size
; i
++) {
776 if (!ReadParam(m
, iter
, &value
))
778 (*r
)->push_back(value
);
782 static void Log(const param_type
& p
, std::string
* l
) {
783 for (size_t i
= 0; i
< p
->size(); ++i
) {
791 template <typename NormalMap
,
795 struct ParamTraits
<base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> > {
796 typedef base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> param_type
;
797 typedef typename
param_type::key_type K
;
798 typedef typename
param_type::data_type V
;
799 static void Write(Message
* m
, const param_type
& p
) {
800 WriteParam(m
, static_cast<int>(p
.size()));
801 typename
param_type::const_iterator iter
;
802 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
803 WriteParam(m
, iter
->first
);
804 WriteParam(m
, iter
->second
);
807 static bool Read(const Message
* m
,
808 base::PickleIterator
* iter
,
811 if (!iter
->ReadLength(&size
))
813 for (int i
= 0; i
< size
; ++i
) {
815 if (!ReadParam(m
, iter
, &key
))
817 V
& value
= (*r
)[key
];
818 if (!ReadParam(m
, iter
, &value
))
823 static void Log(const param_type
& p
, std::string
* l
) {
824 l
->append("<base::SmallMap>");
829 struct ParamTraits
<scoped_ptr
<P
> > {
830 typedef scoped_ptr
<P
> param_type
;
831 static void Write(Message
* m
, const param_type
& p
) {
833 WriteParam(m
, valid
);
837 static bool Read(const Message
* m
,
838 base::PickleIterator
* iter
,
841 if (!ReadParam(m
, iter
, &valid
))
849 param_type
temp(new P());
850 if (!ReadParam(m
, iter
, temp
.get()))
856 static void Log(const param_type
& p
, std::string
* l
) {
864 // IPC types ParamTraits -------------------------------------------------------
866 // A ChannelHandle is basically a platform-inspecific wrapper around the
867 // fact that IPC endpoints are handled specially on POSIX. See above comments
868 // on FileDescriptor for more background.
870 struct IPC_EXPORT ParamTraits
<IPC::ChannelHandle
> {
871 typedef ChannelHandle param_type
;
872 static void Write(Message
* m
, const param_type
& p
);
873 static bool Read(const Message
* m
,
874 base::PickleIterator
* iter
,
876 static void Log(const param_type
& p
, std::string
* l
);
880 struct IPC_EXPORT ParamTraits
<LogData
> {
881 typedef LogData param_type
;
882 static void Write(Message
* m
, const param_type
& p
);
883 static bool Read(const Message
* m
,
884 base::PickleIterator
* iter
,
886 static void Log(const param_type
& p
, std::string
* l
);
890 struct IPC_EXPORT ParamTraits
<Message
> {
891 static void Write(Message
* m
, const Message
& p
);
892 static bool Read(const Message
* m
,
893 base::PickleIterator
* iter
,
895 static void Log(const Message
& p
, std::string
* l
);
898 // Windows ParamTraits ---------------------------------------------------------
902 struct IPC_EXPORT ParamTraits
<HANDLE
> {
903 typedef HANDLE param_type
;
904 static void Write(Message
* m
, const param_type
& p
);
905 static bool Read(const Message
* m
,
906 base::PickleIterator
* iter
,
908 static void Log(const param_type
& p
, std::string
* l
);
912 struct IPC_EXPORT ParamTraits
<LOGFONT
> {
913 typedef LOGFONT param_type
;
914 static void Write(Message
* m
, const param_type
& p
);
915 static bool Read(const Message
* m
,
916 base::PickleIterator
* iter
,
918 static void Log(const param_type
& p
, std::string
* l
);
922 struct IPC_EXPORT ParamTraits
<MSG
> {
923 typedef MSG param_type
;
924 static void Write(Message
* m
, const param_type
& p
);
925 static bool Read(const Message
* m
,
926 base::PickleIterator
* iter
,
928 static void Log(const param_type
& p
, std::string
* l
);
930 #endif // defined(OS_WIN)
932 //-----------------------------------------------------------------------------
933 // Generic message subclasses
935 // Used for asynchronous messages.
936 template <class ParamType
>
937 class MessageSchema
{
939 typedef ParamType Param
;
940 typedef typename
base::TupleTypes
<ParamType
>::ParamTuple RefParam
;
942 static void Write(Message
* msg
, const RefParam
& p
) IPC_MSG_NOINLINE
;
943 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
946 // defined in ipc_logging.cc
947 IPC_EXPORT
void GenerateLogData(const std::string
& channel
,
948 const Message
& message
,
949 LogData
* data
, bool get_params
);
952 #if defined(IPC_MESSAGE_LOG_ENABLED)
953 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
954 const std::string
& output_params
= msg
->output_params();
955 if (!l
->empty() && !output_params
.empty())
958 l
->append(output_params
);
961 template <class ReplyParamType
>
962 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
963 const Message
* msg
) {
964 if (msg
->received_time() != 0) {
965 std::string output_params
;
966 LogParam(reply_params
, &output_params
);
967 msg
->set_output_params(output_params
);
971 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
972 if (msg
->sent_time()) {
973 // Don't log the sync message after dispatch, as we don't have the
974 // output parameters at that point. Instead, save its data and log it
975 // with the outgoing reply message when it's sent.
976 LogData
* data
= new LogData
;
977 GenerateLogData("", *msg
, data
, true);
979 reply
->set_sync_log_data(data
);
983 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
985 template <class ReplyParamType
>
986 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
987 const Message
* msg
) {}
989 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
992 // This class assumes that its template argument is a RefTuple (a Tuple with
993 // reference elements). This would go into ipc_message_utils_impl.h, but it is
994 // also used by chrome_frame.
995 template <class RefTuple
>
996 class ParamDeserializer
: public MessageReplyDeserializer
{
998 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
1000 bool SerializeOutputParameters(const IPC::Message
& msg
,
1001 base::PickleIterator iter
) override
{
1002 return ReadParam(&msg
, &iter
, &out_
);
1008 // Used for synchronous messages.
1009 template <class SendParamType
, class ReplyParamType
>
1010 class SyncMessageSchema
{
1012 typedef SendParamType SendParam
;
1013 typedef typename
base::TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
1014 typedef ReplyParamType ReplyParam
;
1016 static void Write(Message
* msg
, const RefSendParam
& send
) IPC_MSG_NOINLINE
;
1017 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
1018 static bool ReadReplyParam(
1020 typename
base::TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
1022 template<class T
, class S
, class Method
>
1023 static bool DispatchWithSendParams(bool ok
, const SendParam
& send_params
,
1024 const Message
* msg
, T
* obj
, S
* sender
,
1026 Message
* reply
= SyncMessage::GenerateReply(msg
);
1028 typename
base::TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
1029 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
1030 WriteParam(reply
, reply_params
);
1031 LogReplyParamsToMessage(reply_params
, msg
);
1033 NOTREACHED() << "Error deserializing message " << msg
->type();
1034 reply
->set_reply_error();
1036 sender
->Send(reply
);
1040 template<class T
, class Method
>
1041 static bool DispatchDelayReplyWithSendParams(bool ok
,
1042 const SendParam
& send_params
,
1043 const Message
* msg
, T
* obj
,
1045 Message
* reply
= SyncMessage::GenerateReply(msg
);
1047 base::Tuple
<Message
&> t
= base::MakeRefTuple(*reply
);
1048 ConnectMessageAndReply(msg
, reply
);
1049 DispatchToMethod(obj
, func
, send_params
, &t
);
1051 NOTREACHED() << "Error deserializing message " << msg
->type();
1052 reply
->set_reply_error();
1058 template <typename
... Ts
>
1059 static void WriteReplyParams(Message
* reply
, Ts
... args
) {
1060 ReplyParam
p(args
...);
1061 WriteParam(reply
, p
);
1067 #endif // IPC_IPC_MESSAGE_UTILS_H_