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/files/file.h"
16 #include "base/format_macros.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/scoped_vector.h"
19 #include "base/strings/string16.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/tuple.h"
23 #include "ipc/brokerable_attachment.h"
24 #include "ipc/ipc_message_start.h"
25 #include "ipc/ipc_param_traits.h"
26 #include "ipc/ipc_sync_message.h"
28 #if defined(COMPILER_GCC)
29 // GCC "helpfully" tries to inline template methods in release mode. Except we
30 // want the majority of the template junk being expanded once in the
31 // implementation file (and only provide the definitions in
32 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
33 // at every call site. Special note: GCC happily accepts the attribute before
34 // the method declaration, but only acts on it if it is after.
35 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
36 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
37 // the introduced noclone attribute, which will create specialized versions of
38 // functions/methods when certain types are constant.
39 // www.gnu.org/software/gcc/gcc-4.5/changes.html
40 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
42 #define IPC_MSG_NOINLINE __attribute__((noinline));
44 #elif defined(COMPILER_MSVC)
45 // MSVC++ doesn't do this.
46 #define IPC_MSG_NOINLINE
48 #error "Please add the noinline property for your new compiler here."
52 class DictionaryValue
;
55 class NullableString16
;
60 struct FileDescriptor
;
62 #if defined(OS_MACOSX) && !defined(OS_IOS)
63 class SharedMemoryHandle
;
64 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
71 // -----------------------------------------------------------------------------
72 // How we send IPC message logs across channels.
73 struct IPC_EXPORT LogData
{
79 uint32 type
; // "User-defined" message type, from ipc_message.h.
81 int64 sent
; // Time that the message was sent (i.e. at Send()).
82 int64 receive
; // Time before it was dispatched (i.e. before calling
83 // OnMessageReceived).
84 int64 dispatch
; // Time after it was dispatched (i.e. after calling
85 // OnMessageReceived).
86 std::string message_name
;
90 //-----------------------------------------------------------------------------
92 // A dummy struct to place first just to allow leading commas for all
93 // members in the macro-generated constructor initializer lists.
98 static inline void WriteParam(Message
* m
, const P
& p
) {
99 typedef typename SimilarTypeTraits
<P
>::Type Type
;
100 ParamTraits
<Type
>::Write(m
, static_cast<const Type
& >(p
));
104 static inline bool WARN_UNUSED_RESULT
105 ReadParam(const Message
* m
, base::PickleIterator
* iter
, P
* p
) {
106 typedef typename SimilarTypeTraits
<P
>::Type Type
;
107 return ParamTraits
<Type
>::Read(m
, iter
, reinterpret_cast<Type
* >(p
));
111 static inline void LogParam(const P
& p
, std::string
* l
) {
112 typedef typename SimilarTypeTraits
<P
>::Type Type
;
113 ParamTraits
<Type
>::Log(static_cast<const Type
& >(p
), l
);
116 // Primitive ParamTraits -------------------------------------------------------
119 struct ParamTraits
<bool> {
120 typedef bool param_type
;
121 static void Write(Message
* m
, const param_type
& p
) {
124 static bool Read(const Message
* m
,
125 base::PickleIterator
* iter
,
127 return iter
->ReadBool(r
);
129 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
133 struct IPC_EXPORT ParamTraits
<unsigned char> {
134 typedef unsigned char param_type
;
135 static void Write(Message
* m
, const param_type
& p
);
136 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
137 static void Log(const param_type
& p
, std::string
* l
);
141 struct IPC_EXPORT ParamTraits
<unsigned short> {
142 typedef unsigned short param_type
;
143 static void Write(Message
* m
, const param_type
& p
);
144 static bool Read(const Message
* m
,
145 base::PickleIterator
* iter
,
147 static void Log(const param_type
& p
, std::string
* l
);
151 struct ParamTraits
<int> {
152 typedef int param_type
;
153 static void Write(Message
* m
, const param_type
& p
) {
156 static bool Read(const Message
* m
,
157 base::PickleIterator
* iter
,
159 return iter
->ReadInt(r
);
161 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
165 struct ParamTraits
<unsigned int> {
166 typedef unsigned int param_type
;
167 static void Write(Message
* m
, const param_type
& p
) {
170 static bool Read(const Message
* m
,
171 base::PickleIterator
* iter
,
173 return iter
->ReadInt(reinterpret_cast<int*>(r
));
175 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
179 struct ParamTraits
<long> {
180 typedef long param_type
;
181 static void Write(Message
* m
, const param_type
& p
) {
182 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
184 static bool Read(const Message
* m
,
185 base::PickleIterator
* iter
,
187 return iter
->ReadLong(r
);
189 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
193 struct ParamTraits
<unsigned long> {
194 typedef unsigned long param_type
;
195 static void Write(Message
* m
, const param_type
& p
) {
196 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
198 static bool Read(const Message
* m
,
199 base::PickleIterator
* iter
,
201 return iter
->ReadLong(reinterpret_cast<long*>(r
));
203 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
207 struct ParamTraits
<long long> {
208 typedef long long param_type
;
209 static void Write(Message
* m
, const param_type
& p
) {
210 m
->WriteInt64(static_cast<int64
>(p
));
212 static bool Read(const Message
* m
,
213 base::PickleIterator
* iter
,
215 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
217 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
221 struct ParamTraits
<unsigned long long> {
222 typedef unsigned long long param_type
;
223 static void Write(Message
* m
, const param_type
& p
) {
226 static bool Read(const Message
* m
,
227 base::PickleIterator
* iter
,
229 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
231 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
234 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
235 // should be sure to check the sanity of these values after receiving them over
238 struct IPC_EXPORT ParamTraits
<float> {
239 typedef float param_type
;
240 static void Write(Message
* m
, const param_type
& p
) {
243 static bool Read(const Message
* m
,
244 base::PickleIterator
* iter
,
246 return iter
->ReadFloat(r
);
248 static void Log(const param_type
& p
, std::string
* l
);
252 struct IPC_EXPORT ParamTraits
<double> {
253 typedef double param_type
;
254 static void Write(Message
* m
, const param_type
& p
);
255 static bool Read(const Message
* m
,
256 base::PickleIterator
* iter
,
258 static void Log(const param_type
& p
, std::string
* l
);
261 // STL ParamTraits -------------------------------------------------------------
264 struct ParamTraits
<std::string
> {
265 typedef std::string param_type
;
266 static void Write(Message
* m
, const param_type
& p
) {
269 static bool Read(const Message
* m
,
270 base::PickleIterator
* iter
,
272 return iter
->ReadString(r
);
274 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
278 struct ParamTraits
<base::string16
> {
279 typedef base::string16 param_type
;
280 static void Write(Message
* m
, const param_type
& p
) {
283 static bool Read(const Message
* m
,
284 base::PickleIterator
* iter
,
286 return iter
->ReadString16(r
);
288 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
292 struct IPC_EXPORT ParamTraits
<std::vector
<char> > {
293 typedef std::vector
<char> param_type
;
294 static void Write(Message
* m
, const param_type
& p
);
295 static bool Read(const Message
*,
296 base::PickleIterator
* iter
,
298 static void Log(const param_type
& p
, std::string
* l
);
302 struct IPC_EXPORT ParamTraits
<std::vector
<unsigned char> > {
303 typedef std::vector
<unsigned char> param_type
;
304 static void Write(Message
* m
, const param_type
& p
);
305 static bool Read(const Message
* m
,
306 base::PickleIterator
* iter
,
308 static void Log(const param_type
& p
, std::string
* l
);
312 struct IPC_EXPORT ParamTraits
<std::vector
<bool> > {
313 typedef std::vector
<bool> param_type
;
314 static void Write(Message
* m
, const param_type
& p
);
315 static bool Read(const Message
* m
,
316 base::PickleIterator
* iter
,
318 static void Log(const param_type
& p
, std::string
* l
);
322 struct ParamTraits
<std::vector
<P
> > {
323 typedef std::vector
<P
> param_type
;
324 static void Write(Message
* m
, const param_type
& p
) {
325 WriteParam(m
, static_cast<int>(p
.size()));
326 for (size_t i
= 0; i
< p
.size(); i
++)
329 static bool Read(const Message
* m
,
330 base::PickleIterator
* iter
,
333 // ReadLength() checks for < 0 itself.
334 if (!iter
->ReadLength(&size
))
336 // Resizing beforehand is not safe, see BUG 1006367 for details.
337 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
340 for (int i
= 0; i
< size
; i
++) {
341 if (!ReadParam(m
, iter
, &(*r
)[i
]))
346 static void Log(const param_type
& p
, std::string
* l
) {
347 for (size_t i
= 0; i
< p
.size(); ++i
) {
356 struct ParamTraits
<std::set
<P
> > {
357 typedef std::set
<P
> param_type
;
358 static void Write(Message
* m
, const param_type
& p
) {
359 WriteParam(m
, static_cast<int>(p
.size()));
360 typename
param_type::const_iterator iter
;
361 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
362 WriteParam(m
, *iter
);
364 static bool Read(const Message
* m
,
365 base::PickleIterator
* iter
,
368 if (!iter
->ReadLength(&size
))
370 for (int i
= 0; i
< size
; ++i
) {
372 if (!ReadParam(m
, iter
, &item
))
378 static void Log(const param_type
& p
, std::string
* l
) {
379 l
->append("<std::set>");
383 template <class K
, class V
, class C
, class A
>
384 struct ParamTraits
<std::map
<K
, V
, C
, A
> > {
385 typedef std::map
<K
, V
, C
, A
> param_type
;
386 static void Write(Message
* m
, const param_type
& p
) {
387 WriteParam(m
, static_cast<int>(p
.size()));
388 typename
param_type::const_iterator iter
;
389 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
390 WriteParam(m
, iter
->first
);
391 WriteParam(m
, iter
->second
);
394 static bool Read(const Message
* m
,
395 base::PickleIterator
* iter
,
398 if (!ReadParam(m
, iter
, &size
) || size
< 0)
400 for (int i
= 0; i
< size
; ++i
) {
402 if (!ReadParam(m
, iter
, &k
))
405 if (!ReadParam(m
, iter
, &value
))
410 static void Log(const param_type
& p
, std::string
* l
) {
411 l
->append("<std::map>");
415 template <class A
, class B
>
416 struct ParamTraits
<std::pair
<A
, B
> > {
417 typedef std::pair
<A
, B
> param_type
;
418 static void Write(Message
* m
, const param_type
& p
) {
419 WriteParam(m
, p
.first
);
420 WriteParam(m
, p
.second
);
422 static bool Read(const Message
* m
,
423 base::PickleIterator
* iter
,
425 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
427 static void Log(const param_type
& p
, std::string
* l
) {
429 LogParam(p
.first
, l
);
431 LogParam(p
.second
, l
);
436 // IPC ParamTraits -------------------------------------------------------------
438 struct IPC_EXPORT ParamTraits
<BrokerableAttachment::AttachmentId
> {
439 typedef BrokerableAttachment::AttachmentId param_type
;
440 static void Write(Message
* m
, const param_type
& p
);
441 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
442 static void Log(const param_type
& p
, std::string
* l
);
445 // Base ParamTraits ------------------------------------------------------------
448 struct IPC_EXPORT ParamTraits
<base::DictionaryValue
> {
449 typedef base::DictionaryValue param_type
;
450 static void Write(Message
* m
, const param_type
& p
);
451 static bool Read(const Message
* m
,
452 base::PickleIterator
* iter
,
454 static void Log(const param_type
& p
, std::string
* l
);
457 #if defined(OS_POSIX)
458 // FileDescriptors may be serialised over IPC channels on POSIX. On the
459 // receiving side, the FileDescriptor is a valid duplicate of the file
460 // descriptor which was transmitted: *it is not just a copy of the integer like
461 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
462 // this case, the receiving end will see a value of -1. *Zero is a valid file
465 // The received file descriptor will have the |auto_close| flag set to true. The
466 // code which handles the message is responsible for taking ownership of it.
467 // File descriptors are OS resources and must be closed when no longer needed.
469 // When sending a file descriptor, the file descriptor must be valid at the time
470 // of transmission. Since transmission is not synchronous, one should consider
471 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
472 // flag, which causes the file descriptor to be closed after writing.
474 struct IPC_EXPORT ParamTraits
<base::FileDescriptor
> {
475 typedef base::FileDescriptor param_type
;
476 static void Write(Message
* m
, const param_type
& p
);
477 static bool Read(const Message
* m
,
478 base::PickleIterator
* iter
,
480 static void Log(const param_type
& p
, std::string
* l
);
482 #endif // defined(OS_POSIX)
484 #if defined(OS_MACOSX) && !defined(OS_IOS)
486 struct IPC_EXPORT ParamTraits
<base::SharedMemoryHandle
> {
487 typedef base::SharedMemoryHandle param_type
;
488 static void Write(Message
* m
, const param_type
& p
);
489 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
490 static void Log(const param_type
& p
, std::string
* l
);
495 struct IPC_EXPORT ParamTraits
<base::FilePath
> {
496 typedef base::FilePath param_type
;
497 static void Write(Message
* m
, const param_type
& p
);
498 static bool Read(const Message
* m
,
499 base::PickleIterator
* iter
,
501 static void Log(const param_type
& p
, std::string
* l
);
505 struct IPC_EXPORT ParamTraits
<base::ListValue
> {
506 typedef base::ListValue param_type
;
507 static void Write(Message
* m
, const param_type
& p
);
508 static bool Read(const Message
* m
,
509 base::PickleIterator
* iter
,
511 static void Log(const param_type
& p
, std::string
* l
);
515 struct IPC_EXPORT ParamTraits
<base::NullableString16
> {
516 typedef base::NullableString16 param_type
;
517 static void Write(Message
* m
, const param_type
& p
);
518 static bool Read(const Message
* m
,
519 base::PickleIterator
* iter
,
521 static void Log(const param_type
& p
, std::string
* l
);
525 struct IPC_EXPORT ParamTraits
<base::File::Info
> {
526 typedef base::File::Info param_type
;
527 static void Write(Message
* m
, const param_type
& p
);
528 static bool Read(const Message
* m
,
529 base::PickleIterator
* iter
,
531 static void Log(const param_type
& p
, std::string
* l
);
535 struct SimilarTypeTraits
<base::File::Error
> {
541 struct SimilarTypeTraits
<HWND
> {
544 #endif // defined(OS_WIN)
547 struct IPC_EXPORT ParamTraits
<base::Time
> {
548 typedef base::Time param_type
;
549 static void Write(Message
* m
, const param_type
& p
);
550 static bool Read(const Message
* m
,
551 base::PickleIterator
* iter
,
553 static void Log(const param_type
& p
, std::string
* l
);
557 struct IPC_EXPORT ParamTraits
<base::TimeDelta
> {
558 typedef base::TimeDelta param_type
;
559 static void Write(Message
* m
, const param_type
& p
);
560 static bool Read(const Message
* m
,
561 base::PickleIterator
* iter
,
563 static void Log(const param_type
& p
, std::string
* l
);
567 struct IPC_EXPORT ParamTraits
<base::TimeTicks
> {
568 typedef base::TimeTicks param_type
;
569 static void Write(Message
* m
, const param_type
& p
);
570 static bool Read(const Message
* m
,
571 base::PickleIterator
* iter
,
573 static void Log(const param_type
& p
, std::string
* l
);
577 struct IPC_EXPORT ParamTraits
<base::TraceTicks
> {
578 typedef base::TraceTicks param_type
;
579 static void Write(Message
* m
, const param_type
& p
);
580 static bool Read(const Message
* m
,
581 base::PickleIterator
* iter
,
583 static void Log(const param_type
& p
, std::string
* l
);
587 struct ParamTraits
<base::Tuple
<>> {
588 typedef base::Tuple
<> param_type
;
589 static void Write(Message
* m
, const param_type
& p
) {
591 static bool Read(const Message
* m
,
592 base::PickleIterator
* iter
,
596 static void Log(const param_type
& p
, std::string
* l
) {
601 struct ParamTraits
<base::Tuple
<A
>> {
602 typedef base::Tuple
<A
> param_type
;
603 static void Write(Message
* m
, const param_type
& p
) {
604 WriteParam(m
, base::get
<0>(p
));
606 static bool Read(const Message
* m
,
607 base::PickleIterator
* iter
,
609 return ReadParam(m
, iter
, &base::get
<0>(*r
));
611 static void Log(const param_type
& p
, std::string
* l
) {
612 LogParam(base::get
<0>(p
), l
);
616 template <class A
, class B
>
617 struct ParamTraits
<base::Tuple
<A
, B
>> {
618 typedef base::Tuple
<A
, B
> param_type
;
619 static void Write(Message
* m
, const param_type
& p
) {
620 WriteParam(m
, base::get
<0>(p
));
621 WriteParam(m
, base::get
<1>(p
));
623 static bool Read(const Message
* m
,
624 base::PickleIterator
* iter
,
626 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
627 ReadParam(m
, iter
, &base::get
<1>(*r
)));
629 static void Log(const param_type
& p
, std::string
* l
) {
630 LogParam(base::get
<0>(p
), l
);
632 LogParam(base::get
<1>(p
), l
);
636 template <class A
, class B
, class C
>
637 struct ParamTraits
<base::Tuple
<A
, B
, C
>> {
638 typedef base::Tuple
<A
, B
, C
> param_type
;
639 static void Write(Message
* m
, const param_type
& p
) {
640 WriteParam(m
, base::get
<0>(p
));
641 WriteParam(m
, base::get
<1>(p
));
642 WriteParam(m
, base::get
<2>(p
));
644 static bool Read(const Message
* m
,
645 base::PickleIterator
* iter
,
647 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
648 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
649 ReadParam(m
, iter
, &base::get
<2>(*r
)));
651 static void Log(const param_type
& p
, std::string
* l
) {
652 LogParam(base::get
<0>(p
), l
);
654 LogParam(base::get
<1>(p
), l
);
656 LogParam(base::get
<2>(p
), l
);
660 template <class A
, class B
, class C
, class D
>
661 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
>> {
662 typedef base::Tuple
<A
, B
, C
, D
> param_type
;
663 static void Write(Message
* m
, const param_type
& p
) {
664 WriteParam(m
, base::get
<0>(p
));
665 WriteParam(m
, base::get
<1>(p
));
666 WriteParam(m
, base::get
<2>(p
));
667 WriteParam(m
, base::get
<3>(p
));
669 static bool Read(const Message
* m
,
670 base::PickleIterator
* iter
,
672 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
673 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
674 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
675 ReadParam(m
, iter
, &base::get
<3>(*r
)));
677 static void Log(const param_type
& p
, std::string
* l
) {
678 LogParam(base::get
<0>(p
), l
);
680 LogParam(base::get
<1>(p
), l
);
682 LogParam(base::get
<2>(p
), l
);
684 LogParam(base::get
<3>(p
), l
);
688 template <class A
, class B
, class C
, class D
, class E
>
689 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
, E
>> {
690 typedef base::Tuple
<A
, B
, C
, D
, E
> param_type
;
691 static void Write(Message
* m
, const param_type
& p
) {
692 WriteParam(m
, base::get
<0>(p
));
693 WriteParam(m
, base::get
<1>(p
));
694 WriteParam(m
, base::get
<2>(p
));
695 WriteParam(m
, base::get
<3>(p
));
696 WriteParam(m
, base::get
<4>(p
));
698 static bool Read(const Message
* m
,
699 base::PickleIterator
* iter
,
701 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
702 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
703 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
704 ReadParam(m
, iter
, &base::get
<3>(*r
)) &&
705 ReadParam(m
, iter
, &base::get
<4>(*r
)));
707 static void Log(const param_type
& p
, std::string
* l
) {
708 LogParam(base::get
<0>(p
), l
);
710 LogParam(base::get
<1>(p
), l
);
712 LogParam(base::get
<2>(p
), l
);
714 LogParam(base::get
<3>(p
), l
);
716 LogParam(base::get
<4>(p
), l
);
721 struct ParamTraits
<ScopedVector
<P
> > {
722 typedef ScopedVector
<P
> param_type
;
723 static void Write(Message
* m
, const param_type
& p
) {
724 WriteParam(m
, static_cast<int>(p
.size()));
725 for (size_t i
= 0; i
< p
.size(); i
++)
726 WriteParam(m
, *p
[i
]);
728 static bool Read(const Message
* m
,
729 base::PickleIterator
* iter
,
732 if (!iter
->ReadLength(&size
))
734 if (INT_MAX
/sizeof(P
) <= static_cast<size_t>(size
))
737 for (int i
= 0; i
< size
; i
++) {
739 if (!ReadParam(m
, iter
, (*r
)[i
]))
744 static void Log(const param_type
& p
, std::string
* l
) {
745 for (size_t i
= 0; i
< p
.size(); ++i
) {
753 template <typename NormalMap
,
757 struct ParamTraits
<base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> > {
758 typedef base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> param_type
;
759 typedef typename
param_type::key_type K
;
760 typedef typename
param_type::data_type V
;
761 static void Write(Message
* m
, const param_type
& p
) {
762 WriteParam(m
, static_cast<int>(p
.size()));
763 typename
param_type::const_iterator iter
;
764 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
765 WriteParam(m
, iter
->first
);
766 WriteParam(m
, iter
->second
);
769 static bool Read(const Message
* m
,
770 base::PickleIterator
* iter
,
773 if (!iter
->ReadLength(&size
))
775 for (int i
= 0; i
< size
; ++i
) {
777 if (!ReadParam(m
, iter
, &key
))
779 V
& value
= (*r
)[key
];
780 if (!ReadParam(m
, iter
, &value
))
785 static void Log(const param_type
& p
, std::string
* l
) {
786 l
->append("<base::SmallMap>");
791 struct ParamTraits
<scoped_ptr
<P
> > {
792 typedef scoped_ptr
<P
> param_type
;
793 static void Write(Message
* m
, const param_type
& p
) {
795 WriteParam(m
, valid
);
799 static bool Read(const Message
* m
,
800 base::PickleIterator
* iter
,
803 if (!ReadParam(m
, iter
, &valid
))
811 param_type
temp(new P());
812 if (!ReadParam(m
, iter
, temp
.get()))
818 static void Log(const param_type
& p
, std::string
* l
) {
826 // IPC types ParamTraits -------------------------------------------------------
828 // A ChannelHandle is basically a platform-inspecific wrapper around the
829 // fact that IPC endpoints are handled specially on POSIX. See above comments
830 // on FileDescriptor for more background.
832 struct IPC_EXPORT ParamTraits
<IPC::ChannelHandle
> {
833 typedef ChannelHandle param_type
;
834 static void Write(Message
* m
, const param_type
& p
);
835 static bool Read(const Message
* m
,
836 base::PickleIterator
* iter
,
838 static void Log(const param_type
& p
, std::string
* l
);
842 struct IPC_EXPORT ParamTraits
<LogData
> {
843 typedef LogData param_type
;
844 static void Write(Message
* m
, const param_type
& p
);
845 static bool Read(const Message
* m
,
846 base::PickleIterator
* iter
,
848 static void Log(const param_type
& p
, std::string
* l
);
852 struct IPC_EXPORT ParamTraits
<Message
> {
853 static void Write(Message
* m
, const Message
& p
);
854 static bool Read(const Message
* m
,
855 base::PickleIterator
* iter
,
857 static void Log(const Message
& p
, std::string
* l
);
860 // Windows ParamTraits ---------------------------------------------------------
864 struct IPC_EXPORT ParamTraits
<HANDLE
> {
865 typedef HANDLE param_type
;
866 static void Write(Message
* m
, const param_type
& p
);
867 static bool Read(const Message
* m
,
868 base::PickleIterator
* iter
,
870 static void Log(const param_type
& p
, std::string
* l
);
874 struct IPC_EXPORT ParamTraits
<LOGFONT
> {
875 typedef LOGFONT param_type
;
876 static void Write(Message
* m
, const param_type
& p
);
877 static bool Read(const Message
* m
,
878 base::PickleIterator
* iter
,
880 static void Log(const param_type
& p
, std::string
* l
);
884 struct IPC_EXPORT ParamTraits
<MSG
> {
885 typedef MSG param_type
;
886 static void Write(Message
* m
, const param_type
& p
);
887 static bool Read(const Message
* m
,
888 base::PickleIterator
* iter
,
890 static void Log(const param_type
& p
, std::string
* l
);
892 #endif // defined(OS_WIN)
894 //-----------------------------------------------------------------------------
895 // Generic message subclasses
897 // Used for asynchronous messages.
898 template <class ParamType
>
899 class MessageSchema
{
901 typedef ParamType Param
;
902 typedef typename
base::TupleTypes
<ParamType
>::ParamTuple RefParam
;
904 static void Write(Message
* msg
, const RefParam
& p
) IPC_MSG_NOINLINE
;
905 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
908 // defined in ipc_logging.cc
909 IPC_EXPORT
void GenerateLogData(const std::string
& channel
,
910 const Message
& message
,
911 LogData
* data
, bool get_params
);
914 #if defined(IPC_MESSAGE_LOG_ENABLED)
915 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
916 const std::string
& output_params
= msg
->output_params();
917 if (!l
->empty() && !output_params
.empty())
920 l
->append(output_params
);
923 template <class ReplyParamType
>
924 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
925 const Message
* msg
) {
926 if (msg
->received_time() != 0) {
927 std::string output_params
;
928 LogParam(reply_params
, &output_params
);
929 msg
->set_output_params(output_params
);
933 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
934 if (msg
->sent_time()) {
935 // Don't log the sync message after dispatch, as we don't have the
936 // output parameters at that point. Instead, save its data and log it
937 // with the outgoing reply message when it's sent.
938 LogData
* data
= new LogData
;
939 GenerateLogData("", *msg
, data
, true);
941 reply
->set_sync_log_data(data
);
945 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
947 template <class ReplyParamType
>
948 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
949 const Message
* msg
) {}
951 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
954 // This class assumes that its template argument is a RefTuple (a Tuple with
955 // reference elements). This would go into ipc_message_utils_impl.h, but it is
956 // also used by chrome_frame.
957 template <class RefTuple
>
958 class ParamDeserializer
: public MessageReplyDeserializer
{
960 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
962 bool SerializeOutputParameters(const IPC::Message
& msg
,
963 base::PickleIterator iter
) override
{
964 return ReadParam(&msg
, &iter
, &out_
);
970 // Used for synchronous messages.
971 template <class SendParamType
, class ReplyParamType
>
972 class SyncMessageSchema
{
974 typedef SendParamType SendParam
;
975 typedef typename
base::TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
976 typedef ReplyParamType ReplyParam
;
978 static void Write(Message
* msg
, const RefSendParam
& send
) IPC_MSG_NOINLINE
;
979 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
980 static bool ReadReplyParam(
982 typename
base::TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
984 template<class T
, class S
, class Method
>
985 static bool DispatchWithSendParams(bool ok
, const SendParam
& send_params
,
986 const Message
* msg
, T
* obj
, S
* sender
,
988 Message
* reply
= SyncMessage::GenerateReply(msg
);
990 typename
base::TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
991 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
992 WriteParam(reply
, reply_params
);
993 LogReplyParamsToMessage(reply_params
, msg
);
995 NOTREACHED() << "Error deserializing message " << msg
->type();
996 reply
->set_reply_error();
1002 template<class T
, class Method
>
1003 static bool DispatchDelayReplyWithSendParams(bool ok
,
1004 const SendParam
& send_params
,
1005 const Message
* msg
, T
* obj
,
1007 Message
* reply
= SyncMessage::GenerateReply(msg
);
1009 base::Tuple
<Message
&> t
= base::MakeRefTuple(*reply
);
1010 ConnectMessageAndReply(msg
, reply
);
1011 DispatchToMethod(obj
, func
, send_params
, &t
);
1013 NOTREACHED() << "Error deserializing message " << msg
->type();
1014 reply
->set_reply_error();
1020 template <typename
... Ts
>
1021 static void WriteReplyParams(Message
* reply
, Ts
... args
) {
1022 ReplyParam
p(args
...);
1023 WriteParam(reply
, p
);
1029 #endif // IPC_IPC_MESSAGE_UTILS_H_