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_
14 #include "base/containers/small_map.h"
15 #include "base/containers/stack_container.h"
16 #include "base/files/file.h"
17 #include "base/format_macros.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/scoped_vector.h"
20 #include "base/strings/string16.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/tuple.h"
24 #include "ipc/brokerable_attachment.h"
25 #include "ipc/ipc_message_start.h"
26 #include "ipc/ipc_param_traits.h"
27 #include "ipc/ipc_sync_message.h"
29 #if defined(COMPILER_GCC)
30 // GCC "helpfully" tries to inline template methods in release mode. Except we
31 // want the majority of the template junk being expanded once in the
32 // implementation file (and only provide the definitions in
33 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
34 // at every call site. Special note: GCC happily accepts the attribute before
35 // the method declaration, but only acts on it if it is after.
36 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
37 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
38 // the introduced noclone attribute, which will create specialized versions of
39 // functions/methods when certain types are constant.
40 // www.gnu.org/software/gcc/gcc-4.5/changes.html
41 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
43 #define IPC_MSG_NOINLINE __attribute__((noinline));
45 #elif defined(COMPILER_MSVC)
46 // MSVC++ doesn't do this.
47 #define IPC_MSG_NOINLINE
49 #error "Please add the noinline property for your new compiler here."
53 class DictionaryValue
;
56 class NullableString16
;
61 struct FileDescriptor
;
63 #if defined(OS_MACOSX) && !defined(OS_IOS)
64 class SharedMemoryHandle
;
65 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
72 // -----------------------------------------------------------------------------
73 // How we send IPC message logs across channels.
74 struct IPC_EXPORT LogData
{
80 uint32 type
; // "User-defined" message type, from ipc_message.h.
82 int64 sent
; // Time that the message was sent (i.e. at Send()).
83 int64 receive
; // Time before it was dispatched (i.e. before calling
84 // OnMessageReceived).
85 int64 dispatch
; // Time after it was dispatched (i.e. after calling
86 // OnMessageReceived).
87 std::string message_name
;
91 //-----------------------------------------------------------------------------
93 // A dummy struct to place first just to allow leading commas for all
94 // members in the macro-generated constructor initializer lists.
99 static inline void WriteParam(Message
* m
, const P
& p
) {
100 typedef typename SimilarTypeTraits
<P
>::Type Type
;
101 ParamTraits
<Type
>::Write(m
, static_cast<const Type
& >(p
));
105 static inline bool WARN_UNUSED_RESULT
106 ReadParam(const Message
* m
, base::PickleIterator
* iter
, P
* p
) {
107 typedef typename SimilarTypeTraits
<P
>::Type Type
;
108 return ParamTraits
<Type
>::Read(m
, iter
, reinterpret_cast<Type
* >(p
));
112 static inline void LogParam(const P
& p
, std::string
* l
) {
113 typedef typename SimilarTypeTraits
<P
>::Type Type
;
114 ParamTraits
<Type
>::Log(static_cast<const Type
& >(p
), l
);
117 // Primitive ParamTraits -------------------------------------------------------
120 struct ParamTraits
<bool> {
121 typedef bool param_type
;
122 static void Write(Message
* m
, const param_type
& p
) {
125 static bool Read(const Message
* m
,
126 base::PickleIterator
* iter
,
128 return iter
->ReadBool(r
);
130 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
134 struct IPC_EXPORT ParamTraits
<unsigned char> {
135 typedef unsigned char param_type
;
136 static void Write(Message
* m
, const param_type
& p
);
137 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
138 static void Log(const param_type
& p
, std::string
* l
);
142 struct IPC_EXPORT ParamTraits
<unsigned short> {
143 typedef unsigned short param_type
;
144 static void Write(Message
* m
, const param_type
& p
);
145 static bool Read(const Message
* m
,
146 base::PickleIterator
* iter
,
148 static void Log(const param_type
& p
, std::string
* l
);
152 struct ParamTraits
<int> {
153 typedef int param_type
;
154 static void Write(Message
* m
, const param_type
& p
) {
157 static bool Read(const Message
* m
,
158 base::PickleIterator
* iter
,
160 return iter
->ReadInt(r
);
162 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
166 struct ParamTraits
<unsigned int> {
167 typedef unsigned int param_type
;
168 static void Write(Message
* m
, const param_type
& p
) {
171 static bool Read(const Message
* m
,
172 base::PickleIterator
* iter
,
174 return iter
->ReadInt(reinterpret_cast<int*>(r
));
176 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
180 struct ParamTraits
<long> {
181 typedef long param_type
;
182 static void Write(Message
* m
, const param_type
& p
) {
183 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
185 static bool Read(const Message
* m
,
186 base::PickleIterator
* iter
,
188 return iter
->ReadLong(r
);
190 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
194 struct ParamTraits
<unsigned long> {
195 typedef unsigned long param_type
;
196 static void Write(Message
* m
, const param_type
& p
) {
197 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
199 static bool Read(const Message
* m
,
200 base::PickleIterator
* iter
,
202 return iter
->ReadLong(reinterpret_cast<long*>(r
));
204 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
208 struct ParamTraits
<long long> {
209 typedef long long param_type
;
210 static void Write(Message
* m
, const param_type
& p
) {
211 m
->WriteInt64(static_cast<int64
>(p
));
213 static bool Read(const Message
* m
,
214 base::PickleIterator
* iter
,
216 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
218 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
222 struct ParamTraits
<unsigned long long> {
223 typedef unsigned long long param_type
;
224 static void Write(Message
* m
, const param_type
& p
) {
227 static bool Read(const Message
* m
,
228 base::PickleIterator
* iter
,
230 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
232 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
235 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
236 // should be sure to check the sanity of these values after receiving them over
239 struct IPC_EXPORT ParamTraits
<float> {
240 typedef float param_type
;
241 static void Write(Message
* m
, const param_type
& p
) {
244 static bool Read(const Message
* m
,
245 base::PickleIterator
* iter
,
247 return iter
->ReadFloat(r
);
249 static void Log(const param_type
& p
, std::string
* l
);
253 struct IPC_EXPORT ParamTraits
<double> {
254 typedef double param_type
;
255 static void Write(Message
* m
, const param_type
& p
);
256 static bool Read(const Message
* m
,
257 base::PickleIterator
* iter
,
259 static void Log(const param_type
& p
, std::string
* l
);
262 // STL ParamTraits -------------------------------------------------------------
265 struct ParamTraits
<std::string
> {
266 typedef std::string param_type
;
267 static void Write(Message
* m
, const param_type
& p
) {
270 static bool Read(const Message
* m
,
271 base::PickleIterator
* iter
,
273 return iter
->ReadString(r
);
275 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
279 struct ParamTraits
<base::string16
> {
280 typedef base::string16 param_type
;
281 static void Write(Message
* m
, const param_type
& p
) {
284 static bool Read(const Message
* m
,
285 base::PickleIterator
* iter
,
287 return iter
->ReadString16(r
);
289 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
293 struct IPC_EXPORT ParamTraits
<std::vector
<char> > {
294 typedef std::vector
<char> param_type
;
295 static void Write(Message
* m
, const param_type
& p
);
296 static bool Read(const Message
*,
297 base::PickleIterator
* iter
,
299 static void Log(const param_type
& p
, std::string
* l
);
303 struct IPC_EXPORT ParamTraits
<std::vector
<unsigned char> > {
304 typedef std::vector
<unsigned char> param_type
;
305 static void Write(Message
* m
, const param_type
& p
);
306 static bool Read(const Message
* m
,
307 base::PickleIterator
* iter
,
309 static void Log(const param_type
& p
, std::string
* l
);
313 struct IPC_EXPORT ParamTraits
<std::vector
<bool> > {
314 typedef std::vector
<bool> param_type
;
315 static void Write(Message
* m
, const param_type
& p
);
316 static bool Read(const Message
* m
,
317 base::PickleIterator
* iter
,
319 static void Log(const param_type
& p
, std::string
* l
);
323 struct ParamTraits
<std::vector
<P
> > {
324 typedef std::vector
<P
> param_type
;
325 static void Write(Message
* m
, const param_type
& p
) {
326 WriteParam(m
, static_cast<int>(p
.size()));
327 for (size_t i
= 0; i
< p
.size(); i
++)
330 static bool Read(const Message
* m
,
331 base::PickleIterator
* iter
,
334 // ReadLength() checks for < 0 itself.
335 if (!iter
->ReadLength(&size
))
337 // Resizing beforehand is not safe, see BUG 1006367 for details.
338 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
341 for (int i
= 0; i
< size
; i
++) {
342 if (!ReadParam(m
, iter
, &(*r
)[i
]))
347 static void Log(const param_type
& p
, std::string
* l
) {
348 for (size_t i
= 0; i
< p
.size(); ++i
) {
357 struct ParamTraits
<std::set
<P
> > {
358 typedef std::set
<P
> param_type
;
359 static void Write(Message
* m
, const param_type
& p
) {
360 WriteParam(m
, static_cast<int>(p
.size()));
361 typename
param_type::const_iterator iter
;
362 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
363 WriteParam(m
, *iter
);
365 static bool Read(const Message
* m
,
366 base::PickleIterator
* iter
,
369 if (!iter
->ReadLength(&size
))
371 for (int i
= 0; i
< size
; ++i
) {
373 if (!ReadParam(m
, iter
, &item
))
379 static void Log(const param_type
& p
, std::string
* l
) {
380 l
->append("<std::set>");
384 template <class K
, class V
, class C
, class A
>
385 struct ParamTraits
<std::map
<K
, V
, C
, A
> > {
386 typedef std::map
<K
, V
, C
, A
> param_type
;
387 static void Write(Message
* m
, const param_type
& p
) {
388 WriteParam(m
, static_cast<int>(p
.size()));
389 typename
param_type::const_iterator iter
;
390 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
391 WriteParam(m
, iter
->first
);
392 WriteParam(m
, iter
->second
);
395 static bool Read(const Message
* m
,
396 base::PickleIterator
* iter
,
399 if (!ReadParam(m
, iter
, &size
) || size
< 0)
401 for (int i
= 0; i
< size
; ++i
) {
403 if (!ReadParam(m
, iter
, &k
))
406 if (!ReadParam(m
, iter
, &value
))
411 static void Log(const param_type
& p
, std::string
* l
) {
412 l
->append("<std::map>");
416 template <class A
, class B
>
417 struct ParamTraits
<std::pair
<A
, B
> > {
418 typedef std::pair
<A
, B
> param_type
;
419 static void Write(Message
* m
, const param_type
& p
) {
420 WriteParam(m
, p
.first
);
421 WriteParam(m
, p
.second
);
423 static bool Read(const Message
* m
,
424 base::PickleIterator
* iter
,
426 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
428 static void Log(const param_type
& p
, std::string
* l
) {
430 LogParam(p
.first
, l
);
432 LogParam(p
.second
, l
);
437 // IPC ParamTraits -------------------------------------------------------------
439 struct IPC_EXPORT ParamTraits
<BrokerableAttachment::AttachmentId
> {
440 typedef BrokerableAttachment::AttachmentId param_type
;
441 static void Write(Message
* m
, const param_type
& p
);
442 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
443 static void Log(const param_type
& p
, std::string
* l
);
446 // Base ParamTraits ------------------------------------------------------------
449 struct IPC_EXPORT ParamTraits
<base::DictionaryValue
> {
450 typedef base::DictionaryValue param_type
;
451 static void Write(Message
* m
, const param_type
& p
);
452 static bool Read(const Message
* m
,
453 base::PickleIterator
* iter
,
455 static void Log(const param_type
& p
, std::string
* l
);
458 #if defined(OS_POSIX)
459 // FileDescriptors may be serialised over IPC channels on POSIX. On the
460 // receiving side, the FileDescriptor is a valid duplicate of the file
461 // descriptor which was transmitted: *it is not just a copy of the integer like
462 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
463 // this case, the receiving end will see a value of -1. *Zero is a valid file
466 // The received file descriptor will have the |auto_close| flag set to true. The
467 // code which handles the message is responsible for taking ownership of it.
468 // File descriptors are OS resources and must be closed when no longer needed.
470 // When sending a file descriptor, the file descriptor must be valid at the time
471 // of transmission. Since transmission is not synchronous, one should consider
472 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
473 // flag, which causes the file descriptor to be closed after writing.
475 struct IPC_EXPORT ParamTraits
<base::FileDescriptor
> {
476 typedef base::FileDescriptor param_type
;
477 static void Write(Message
* m
, const param_type
& p
);
478 static bool Read(const Message
* m
,
479 base::PickleIterator
* iter
,
481 static void Log(const param_type
& p
, std::string
* l
);
483 #endif // defined(OS_POSIX)
485 #if defined(OS_MACOSX) && !defined(OS_IOS)
487 struct IPC_EXPORT ParamTraits
<base::SharedMemoryHandle
> {
488 typedef base::SharedMemoryHandle param_type
;
489 static void Write(Message
* m
, const param_type
& p
);
490 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
491 static void Log(const param_type
& p
, std::string
* l
);
496 struct IPC_EXPORT ParamTraits
<base::FilePath
> {
497 typedef base::FilePath param_type
;
498 static void Write(Message
* m
, const param_type
& p
);
499 static bool Read(const Message
* m
,
500 base::PickleIterator
* iter
,
502 static void Log(const param_type
& p
, std::string
* l
);
506 struct IPC_EXPORT ParamTraits
<base::ListValue
> {
507 typedef base::ListValue param_type
;
508 static void Write(Message
* m
, const param_type
& p
);
509 static bool Read(const Message
* m
,
510 base::PickleIterator
* iter
,
512 static void Log(const param_type
& p
, std::string
* l
);
516 struct IPC_EXPORT ParamTraits
<base::NullableString16
> {
517 typedef base::NullableString16 param_type
;
518 static void Write(Message
* m
, const param_type
& p
);
519 static bool Read(const Message
* m
,
520 base::PickleIterator
* iter
,
522 static void Log(const param_type
& p
, std::string
* l
);
526 struct IPC_EXPORT ParamTraits
<base::File::Info
> {
527 typedef base::File::Info param_type
;
528 static void Write(Message
* m
, const param_type
& p
);
529 static bool Read(const Message
* m
,
530 base::PickleIterator
* iter
,
532 static void Log(const param_type
& p
, std::string
* l
);
536 struct SimilarTypeTraits
<base::File::Error
> {
542 struct SimilarTypeTraits
<HWND
> {
545 #endif // defined(OS_WIN)
548 struct IPC_EXPORT ParamTraits
<base::Time
> {
549 typedef base::Time param_type
;
550 static void Write(Message
* m
, const param_type
& p
);
551 static bool Read(const Message
* m
,
552 base::PickleIterator
* iter
,
554 static void Log(const param_type
& p
, std::string
* l
);
558 struct IPC_EXPORT ParamTraits
<base::TimeDelta
> {
559 typedef base::TimeDelta param_type
;
560 static void Write(Message
* m
, const param_type
& p
);
561 static bool Read(const Message
* m
,
562 base::PickleIterator
* iter
,
564 static void Log(const param_type
& p
, std::string
* l
);
568 struct IPC_EXPORT ParamTraits
<base::TimeTicks
> {
569 typedef base::TimeTicks param_type
;
570 static void Write(Message
* m
, const param_type
& p
);
571 static bool Read(const Message
* m
,
572 base::PickleIterator
* iter
,
574 static void Log(const param_type
& p
, std::string
* l
);
578 struct IPC_EXPORT ParamTraits
<base::TraceTicks
> {
579 typedef base::TraceTicks param_type
;
580 static void Write(Message
* m
, const param_type
& p
);
581 static bool Read(const Message
* m
,
582 base::PickleIterator
* iter
,
584 static void Log(const param_type
& p
, std::string
* l
);
588 struct ParamTraits
<base::Tuple
<>> {
589 typedef base::Tuple
<> param_type
;
590 static void Write(Message
* m
, const param_type
& p
) {
592 static bool Read(const Message
* m
,
593 base::PickleIterator
* iter
,
597 static void Log(const param_type
& p
, std::string
* l
) {
602 struct ParamTraits
<base::Tuple
<A
>> {
603 typedef base::Tuple
<A
> param_type
;
604 static void Write(Message
* m
, const param_type
& p
) {
605 WriteParam(m
, base::get
<0>(p
));
607 static bool Read(const Message
* m
,
608 base::PickleIterator
* iter
,
610 return ReadParam(m
, iter
, &base::get
<0>(*r
));
612 static void Log(const param_type
& p
, std::string
* l
) {
613 LogParam(base::get
<0>(p
), l
);
617 template <class A
, class B
>
618 struct ParamTraits
<base::Tuple
<A
, B
>> {
619 typedef base::Tuple
<A
, B
> param_type
;
620 static void Write(Message
* m
, const param_type
& p
) {
621 WriteParam(m
, base::get
<0>(p
));
622 WriteParam(m
, base::get
<1>(p
));
624 static bool Read(const Message
* m
,
625 base::PickleIterator
* iter
,
627 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
628 ReadParam(m
, iter
, &base::get
<1>(*r
)));
630 static void Log(const param_type
& p
, std::string
* l
) {
631 LogParam(base::get
<0>(p
), l
);
633 LogParam(base::get
<1>(p
), l
);
637 template <class A
, class B
, class C
>
638 struct ParamTraits
<base::Tuple
<A
, B
, C
>> {
639 typedef base::Tuple
<A
, B
, C
> param_type
;
640 static void Write(Message
* m
, const param_type
& p
) {
641 WriteParam(m
, base::get
<0>(p
));
642 WriteParam(m
, base::get
<1>(p
));
643 WriteParam(m
, base::get
<2>(p
));
645 static bool Read(const Message
* m
,
646 base::PickleIterator
* iter
,
648 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
649 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
650 ReadParam(m
, iter
, &base::get
<2>(*r
)));
652 static void Log(const param_type
& p
, std::string
* l
) {
653 LogParam(base::get
<0>(p
), l
);
655 LogParam(base::get
<1>(p
), l
);
657 LogParam(base::get
<2>(p
), l
);
661 template <class A
, class B
, class C
, class D
>
662 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
>> {
663 typedef base::Tuple
<A
, B
, C
, D
> param_type
;
664 static void Write(Message
* m
, const param_type
& p
) {
665 WriteParam(m
, base::get
<0>(p
));
666 WriteParam(m
, base::get
<1>(p
));
667 WriteParam(m
, base::get
<2>(p
));
668 WriteParam(m
, base::get
<3>(p
));
670 static bool Read(const Message
* m
,
671 base::PickleIterator
* iter
,
673 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
674 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
675 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
676 ReadParam(m
, iter
, &base::get
<3>(*r
)));
678 static void Log(const param_type
& p
, std::string
* l
) {
679 LogParam(base::get
<0>(p
), l
);
681 LogParam(base::get
<1>(p
), l
);
683 LogParam(base::get
<2>(p
), l
);
685 LogParam(base::get
<3>(p
), l
);
689 template <class A
, class B
, class C
, class D
, class E
>
690 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
, E
>> {
691 typedef base::Tuple
<A
, B
, C
, D
, E
> param_type
;
692 static void Write(Message
* m
, const param_type
& p
) {
693 WriteParam(m
, base::get
<0>(p
));
694 WriteParam(m
, base::get
<1>(p
));
695 WriteParam(m
, base::get
<2>(p
));
696 WriteParam(m
, base::get
<3>(p
));
697 WriteParam(m
, base::get
<4>(p
));
699 static bool Read(const Message
* m
,
700 base::PickleIterator
* iter
,
702 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
703 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
704 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
705 ReadParam(m
, iter
, &base::get
<3>(*r
)) &&
706 ReadParam(m
, iter
, &base::get
<4>(*r
)));
708 static void Log(const param_type
& p
, std::string
* l
) {
709 LogParam(base::get
<0>(p
), l
);
711 LogParam(base::get
<1>(p
), l
);
713 LogParam(base::get
<2>(p
), l
);
715 LogParam(base::get
<3>(p
), l
);
717 LogParam(base::get
<4>(p
), l
);
722 struct ParamTraits
<ScopedVector
<P
> > {
723 typedef ScopedVector
<P
> param_type
;
724 static void Write(Message
* m
, const param_type
& p
) {
725 WriteParam(m
, static_cast<int>(p
.size()));
726 for (size_t i
= 0; i
< p
.size(); i
++)
727 WriteParam(m
, *p
[i
]);
729 static bool Read(const Message
* m
,
730 base::PickleIterator
* iter
,
733 if (!iter
->ReadLength(&size
))
735 if (INT_MAX
/sizeof(P
) <= static_cast<size_t>(size
))
738 for (int i
= 0; i
< size
; i
++) {
740 if (!ReadParam(m
, iter
, (*r
)[i
]))
745 static void Log(const param_type
& p
, std::string
* l
) {
746 for (size_t i
= 0; i
< p
.size(); ++i
) {
754 template <class P
, size_t stack_capacity
>
755 struct ParamTraits
<base::StackVector
<P
, stack_capacity
> > {
756 typedef base::StackVector
<P
, stack_capacity
> param_type
;
757 static void Write(Message
* m
, const param_type
& p
) {
758 WriteParam(m
, static_cast<int>(p
->size()));
759 for (size_t i
= 0; i
< p
->size(); i
++)
762 static bool Read(const Message
* m
,
763 base::PickleIterator
* iter
,
766 // ReadLength() checks for < 0 itself.
767 if (!iter
->ReadLength(&size
))
769 // Sanity check for the vector size.
770 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
773 for (int i
= 0; i
< size
; i
++) {
774 if (!ReadParam(m
, iter
, &value
))
776 (*r
)->push_back(value
);
780 static void Log(const param_type
& p
, std::string
* l
) {
781 for (size_t i
= 0; i
< p
->size(); ++i
) {
789 template <typename NormalMap
,
793 struct ParamTraits
<base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> > {
794 typedef base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> param_type
;
795 typedef typename
param_type::key_type K
;
796 typedef typename
param_type::data_type V
;
797 static void Write(Message
* m
, const param_type
& p
) {
798 WriteParam(m
, static_cast<int>(p
.size()));
799 typename
param_type::const_iterator iter
;
800 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
801 WriteParam(m
, iter
->first
);
802 WriteParam(m
, iter
->second
);
805 static bool Read(const Message
* m
,
806 base::PickleIterator
* iter
,
809 if (!iter
->ReadLength(&size
))
811 for (int i
= 0; i
< size
; ++i
) {
813 if (!ReadParam(m
, iter
, &key
))
815 V
& value
= (*r
)[key
];
816 if (!ReadParam(m
, iter
, &value
))
821 static void Log(const param_type
& p
, std::string
* l
) {
822 l
->append("<base::SmallMap>");
827 struct ParamTraits
<scoped_ptr
<P
> > {
828 typedef scoped_ptr
<P
> param_type
;
829 static void Write(Message
* m
, const param_type
& p
) {
831 WriteParam(m
, valid
);
835 static bool Read(const Message
* m
,
836 base::PickleIterator
* iter
,
839 if (!ReadParam(m
, iter
, &valid
))
847 param_type
temp(new P());
848 if (!ReadParam(m
, iter
, temp
.get()))
854 static void Log(const param_type
& p
, std::string
* l
) {
862 // IPC types ParamTraits -------------------------------------------------------
864 // A ChannelHandle is basically a platform-inspecific wrapper around the
865 // fact that IPC endpoints are handled specially on POSIX. See above comments
866 // on FileDescriptor for more background.
868 struct IPC_EXPORT ParamTraits
<IPC::ChannelHandle
> {
869 typedef ChannelHandle param_type
;
870 static void Write(Message
* m
, const param_type
& p
);
871 static bool Read(const Message
* m
,
872 base::PickleIterator
* iter
,
874 static void Log(const param_type
& p
, std::string
* l
);
878 struct IPC_EXPORT ParamTraits
<LogData
> {
879 typedef LogData param_type
;
880 static void Write(Message
* m
, const param_type
& p
);
881 static bool Read(const Message
* m
,
882 base::PickleIterator
* iter
,
884 static void Log(const param_type
& p
, std::string
* l
);
888 struct IPC_EXPORT ParamTraits
<Message
> {
889 static void Write(Message
* m
, const Message
& p
);
890 static bool Read(const Message
* m
,
891 base::PickleIterator
* iter
,
893 static void Log(const Message
& p
, std::string
* l
);
896 // Windows ParamTraits ---------------------------------------------------------
900 struct IPC_EXPORT ParamTraits
<HANDLE
> {
901 typedef HANDLE param_type
;
902 static void Write(Message
* m
, const param_type
& p
);
903 static bool Read(const Message
* m
,
904 base::PickleIterator
* iter
,
906 static void Log(const param_type
& p
, std::string
* l
);
910 struct IPC_EXPORT ParamTraits
<LOGFONT
> {
911 typedef LOGFONT param_type
;
912 static void Write(Message
* m
, const param_type
& p
);
913 static bool Read(const Message
* m
,
914 base::PickleIterator
* iter
,
916 static void Log(const param_type
& p
, std::string
* l
);
920 struct IPC_EXPORT ParamTraits
<MSG
> {
921 typedef MSG param_type
;
922 static void Write(Message
* m
, const param_type
& p
);
923 static bool Read(const Message
* m
,
924 base::PickleIterator
* iter
,
926 static void Log(const param_type
& p
, std::string
* l
);
928 #endif // defined(OS_WIN)
930 //-----------------------------------------------------------------------------
931 // Generic message subclasses
933 // Used for asynchronous messages.
934 template <class ParamType
>
935 class MessageSchema
{
937 typedef ParamType Param
;
938 typedef typename
base::TupleTypes
<ParamType
>::ParamTuple RefParam
;
940 static void Write(Message
* msg
, const RefParam
& p
) IPC_MSG_NOINLINE
;
941 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
944 // defined in ipc_logging.cc
945 IPC_EXPORT
void GenerateLogData(const std::string
& channel
,
946 const Message
& message
,
947 LogData
* data
, bool get_params
);
950 #if defined(IPC_MESSAGE_LOG_ENABLED)
951 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
952 const std::string
& output_params
= msg
->output_params();
953 if (!l
->empty() && !output_params
.empty())
956 l
->append(output_params
);
959 template <class ReplyParamType
>
960 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
961 const Message
* msg
) {
962 if (msg
->received_time() != 0) {
963 std::string output_params
;
964 LogParam(reply_params
, &output_params
);
965 msg
->set_output_params(output_params
);
969 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
970 if (msg
->sent_time()) {
971 // Don't log the sync message after dispatch, as we don't have the
972 // output parameters at that point. Instead, save its data and log it
973 // with the outgoing reply message when it's sent.
974 LogData
* data
= new LogData
;
975 GenerateLogData("", *msg
, data
, true);
977 reply
->set_sync_log_data(data
);
981 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
983 template <class ReplyParamType
>
984 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
985 const Message
* msg
) {}
987 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
990 // This class assumes that its template argument is a RefTuple (a Tuple with
991 // reference elements). This would go into ipc_message_utils_impl.h, but it is
992 // also used by chrome_frame.
993 template <class RefTuple
>
994 class ParamDeserializer
: public MessageReplyDeserializer
{
996 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
998 bool SerializeOutputParameters(const IPC::Message
& msg
,
999 base::PickleIterator iter
) override
{
1000 return ReadParam(&msg
, &iter
, &out_
);
1006 // Used for synchronous messages.
1007 template <class SendParamType
, class ReplyParamType
>
1008 class SyncMessageSchema
{
1010 typedef SendParamType SendParam
;
1011 typedef typename
base::TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
1012 typedef ReplyParamType ReplyParam
;
1014 static void Write(Message
* msg
, const RefSendParam
& send
) IPC_MSG_NOINLINE
;
1015 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
1016 static bool ReadReplyParam(
1018 typename
base::TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
1020 template<class T
, class S
, class Method
>
1021 static bool DispatchWithSendParams(bool ok
, const SendParam
& send_params
,
1022 const Message
* msg
, T
* obj
, S
* sender
,
1024 Message
* reply
= SyncMessage::GenerateReply(msg
);
1026 typename
base::TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
1027 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
1028 WriteParam(reply
, reply_params
);
1029 LogReplyParamsToMessage(reply_params
, msg
);
1031 NOTREACHED() << "Error deserializing message " << msg
->type();
1032 reply
->set_reply_error();
1034 sender
->Send(reply
);
1038 template<class T
, class Method
>
1039 static bool DispatchDelayReplyWithSendParams(bool ok
,
1040 const SendParam
& send_params
,
1041 const Message
* msg
, T
* obj
,
1043 Message
* reply
= SyncMessage::GenerateReply(msg
);
1045 base::Tuple
<Message
&> t
= base::MakeRefTuple(*reply
);
1046 ConnectMessageAndReply(msg
, reply
);
1047 DispatchToMethod(obj
, func
, send_params
, &t
);
1049 NOTREACHED() << "Error deserializing message " << msg
->type();
1050 reply
->set_reply_error();
1056 template <typename
... Ts
>
1057 static void WriteReplyParams(Message
* reply
, Ts
... args
) {
1058 ReplyParam
p(args
...);
1059 WriteParam(reply
, p
);
1065 #endif // IPC_IPC_MESSAGE_UTILS_H_