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/ipc_message_start.h"
24 #include "ipc/ipc_param_traits.h"
25 #include "ipc/ipc_sync_message.h"
27 #if defined(COMPILER_GCC)
28 // GCC "helpfully" tries to inline template methods in release mode. Except we
29 // want the majority of the template junk being expanded once in the
30 // implementation file (and only provide the definitions in
31 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
32 // at every call site. Special note: GCC happily accepts the attribute before
33 // the method declaration, but only acts on it if it is after.
34 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
35 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
36 // the introduced noclone attribute, which will create specialized versions of
37 // functions/methods when certain types are constant.
38 // www.gnu.org/software/gcc/gcc-4.5/changes.html
39 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
41 #define IPC_MSG_NOINLINE __attribute__((noinline));
43 #elif defined(COMPILER_MSVC)
44 // MSVC++ doesn't do this.
45 #define IPC_MSG_NOINLINE
47 #error "Please add the noinline property for your new compiler here."
51 class DictionaryValue
;
54 class NullableString16
;
59 struct FileDescriptor
;
66 // -----------------------------------------------------------------------------
67 // How we send IPC message logs across channels.
68 struct IPC_EXPORT LogData
{
74 uint32 type
; // "User-defined" message type, from ipc_message.h.
76 int64 sent
; // Time that the message was sent (i.e. at Send()).
77 int64 receive
; // Time before it was dispatched (i.e. before calling
78 // OnMessageReceived).
79 int64 dispatch
; // Time after it was dispatched (i.e. after calling
80 // OnMessageReceived).
81 std::string message_name
;
85 //-----------------------------------------------------------------------------
87 // A dummy struct to place first just to allow leading commas for all
88 // members in the macro-generated constructor initializer lists.
93 static inline void WriteParam(Message
* m
, const P
& p
) {
94 typedef typename SimilarTypeTraits
<P
>::Type Type
;
95 ParamTraits
<Type
>::Write(m
, static_cast<const Type
& >(p
));
99 static inline bool WARN_UNUSED_RESULT
100 ReadParam(const Message
* m
, base::PickleIterator
* iter
, P
* p
) {
101 typedef typename SimilarTypeTraits
<P
>::Type Type
;
102 return ParamTraits
<Type
>::Read(m
, iter
, reinterpret_cast<Type
* >(p
));
106 static inline void LogParam(const P
& p
, std::string
* l
) {
107 typedef typename SimilarTypeTraits
<P
>::Type Type
;
108 ParamTraits
<Type
>::Log(static_cast<const Type
& >(p
), l
);
111 // Primitive ParamTraits -------------------------------------------------------
114 struct ParamTraits
<bool> {
115 typedef bool param_type
;
116 static void Write(Message
* m
, const param_type
& p
) {
119 static bool Read(const Message
* m
,
120 base::PickleIterator
* iter
,
122 return iter
->ReadBool(r
);
124 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
128 struct IPC_EXPORT ParamTraits
<unsigned char> {
129 typedef unsigned char param_type
;
130 static void Write(Message
* m
, const param_type
& p
);
131 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
132 static void Log(const param_type
& p
, std::string
* l
);
136 struct IPC_EXPORT ParamTraits
<unsigned short> {
137 typedef unsigned short param_type
;
138 static void Write(Message
* m
, const param_type
& p
);
139 static bool Read(const Message
* m
,
140 base::PickleIterator
* iter
,
142 static void Log(const param_type
& p
, std::string
* l
);
146 struct ParamTraits
<int> {
147 typedef int param_type
;
148 static void Write(Message
* m
, const param_type
& p
) {
151 static bool Read(const Message
* m
,
152 base::PickleIterator
* iter
,
154 return iter
->ReadInt(r
);
156 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
160 struct ParamTraits
<unsigned int> {
161 typedef unsigned int param_type
;
162 static void Write(Message
* m
, const param_type
& p
) {
165 static bool Read(const Message
* m
,
166 base::PickleIterator
* iter
,
168 return iter
->ReadInt(reinterpret_cast<int*>(r
));
170 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
174 struct ParamTraits
<long> {
175 typedef long param_type
;
176 static void Write(Message
* m
, const param_type
& p
) {
177 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
179 static bool Read(const Message
* m
,
180 base::PickleIterator
* iter
,
182 return iter
->ReadLong(r
);
184 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
188 struct ParamTraits
<unsigned long> {
189 typedef unsigned long param_type
;
190 static void Write(Message
* m
, const param_type
& p
) {
191 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
193 static bool Read(const Message
* m
,
194 base::PickleIterator
* iter
,
196 return iter
->ReadLong(reinterpret_cast<long*>(r
));
198 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
202 struct ParamTraits
<long long> {
203 typedef long long param_type
;
204 static void Write(Message
* m
, const param_type
& p
) {
205 m
->WriteInt64(static_cast<int64
>(p
));
207 static bool Read(const Message
* m
,
208 base::PickleIterator
* iter
,
210 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
212 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
216 struct ParamTraits
<unsigned long long> {
217 typedef unsigned long long param_type
;
218 static void Write(Message
* m
, const param_type
& p
) {
221 static bool Read(const Message
* m
,
222 base::PickleIterator
* iter
,
224 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
226 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
229 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
230 // should be sure to check the sanity of these values after receiving them over
233 struct IPC_EXPORT ParamTraits
<float> {
234 typedef float param_type
;
235 static void Write(Message
* m
, const param_type
& p
) {
238 static bool Read(const Message
* m
,
239 base::PickleIterator
* iter
,
241 return iter
->ReadFloat(r
);
243 static void Log(const param_type
& p
, std::string
* l
);
247 struct IPC_EXPORT ParamTraits
<double> {
248 typedef double param_type
;
249 static void Write(Message
* m
, const param_type
& p
);
250 static bool Read(const Message
* m
,
251 base::PickleIterator
* iter
,
253 static void Log(const param_type
& p
, std::string
* l
);
256 // STL ParamTraits -------------------------------------------------------------
259 struct ParamTraits
<std::string
> {
260 typedef std::string param_type
;
261 static void Write(Message
* m
, const param_type
& p
) {
264 static bool Read(const Message
* m
,
265 base::PickleIterator
* iter
,
267 return iter
->ReadString(r
);
269 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
273 struct ParamTraits
<base::string16
> {
274 typedef base::string16 param_type
;
275 static void Write(Message
* m
, const param_type
& p
) {
278 static bool Read(const Message
* m
,
279 base::PickleIterator
* iter
,
281 return iter
->ReadString16(r
);
283 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
287 struct IPC_EXPORT ParamTraits
<std::vector
<char> > {
288 typedef std::vector
<char> param_type
;
289 static void Write(Message
* m
, const param_type
& p
);
290 static bool Read(const Message
*,
291 base::PickleIterator
* iter
,
293 static void Log(const param_type
& p
, std::string
* l
);
297 struct IPC_EXPORT ParamTraits
<std::vector
<unsigned char> > {
298 typedef std::vector
<unsigned char> param_type
;
299 static void Write(Message
* m
, const param_type
& p
);
300 static bool Read(const Message
* m
,
301 base::PickleIterator
* iter
,
303 static void Log(const param_type
& p
, std::string
* l
);
307 struct IPC_EXPORT ParamTraits
<std::vector
<bool> > {
308 typedef std::vector
<bool> param_type
;
309 static void Write(Message
* m
, const param_type
& p
);
310 static bool Read(const Message
* m
,
311 base::PickleIterator
* iter
,
313 static void Log(const param_type
& p
, std::string
* l
);
317 struct ParamTraits
<std::vector
<P
> > {
318 typedef std::vector
<P
> param_type
;
319 static void Write(Message
* m
, const param_type
& p
) {
320 WriteParam(m
, static_cast<int>(p
.size()));
321 for (size_t i
= 0; i
< p
.size(); i
++)
324 static bool Read(const Message
* m
,
325 base::PickleIterator
* iter
,
328 // ReadLength() checks for < 0 itself.
329 if (!iter
->ReadLength(&size
))
331 // Resizing beforehand is not safe, see BUG 1006367 for details.
332 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
335 for (int i
= 0; i
< size
; i
++) {
336 if (!ReadParam(m
, iter
, &(*r
)[i
]))
341 static void Log(const param_type
& p
, std::string
* l
) {
342 for (size_t i
= 0; i
< p
.size(); ++i
) {
351 struct ParamTraits
<std::set
<P
> > {
352 typedef std::set
<P
> param_type
;
353 static void Write(Message
* m
, const param_type
& p
) {
354 WriteParam(m
, static_cast<int>(p
.size()));
355 typename
param_type::const_iterator iter
;
356 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
357 WriteParam(m
, *iter
);
359 static bool Read(const Message
* m
,
360 base::PickleIterator
* iter
,
363 if (!iter
->ReadLength(&size
))
365 for (int i
= 0; i
< size
; ++i
) {
367 if (!ReadParam(m
, iter
, &item
))
373 static void Log(const param_type
& p
, std::string
* l
) {
374 l
->append("<std::set>");
378 template <class K
, class V
, class C
, class A
>
379 struct ParamTraits
<std::map
<K
, V
, C
, A
> > {
380 typedef std::map
<K
, V
, C
, A
> param_type
;
381 static void Write(Message
* m
, const param_type
& p
) {
382 WriteParam(m
, static_cast<int>(p
.size()));
383 typename
param_type::const_iterator iter
;
384 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
385 WriteParam(m
, iter
->first
);
386 WriteParam(m
, iter
->second
);
389 static bool Read(const Message
* m
,
390 base::PickleIterator
* iter
,
393 if (!ReadParam(m
, iter
, &size
) || size
< 0)
395 for (int i
= 0; i
< size
; ++i
) {
397 if (!ReadParam(m
, iter
, &k
))
400 if (!ReadParam(m
, iter
, &value
))
405 static void Log(const param_type
& p
, std::string
* l
) {
406 l
->append("<std::map>");
410 template <class A
, class B
>
411 struct ParamTraits
<std::pair
<A
, B
> > {
412 typedef std::pair
<A
, B
> param_type
;
413 static void Write(Message
* m
, const param_type
& p
) {
414 WriteParam(m
, p
.first
);
415 WriteParam(m
, p
.second
);
417 static bool Read(const Message
* m
,
418 base::PickleIterator
* iter
,
420 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
422 static void Log(const param_type
& p
, std::string
* l
) {
424 LogParam(p
.first
, l
);
426 LogParam(p
.second
, l
);
431 // Base ParamTraits ------------------------------------------------------------
434 struct IPC_EXPORT ParamTraits
<base::DictionaryValue
> {
435 typedef base::DictionaryValue param_type
;
436 static void Write(Message
* m
, const param_type
& p
);
437 static bool Read(const Message
* m
,
438 base::PickleIterator
* iter
,
440 static void Log(const param_type
& p
, std::string
* l
);
443 #if defined(OS_POSIX)
444 // FileDescriptors may be serialised over IPC channels on POSIX. On the
445 // receiving side, the FileDescriptor is a valid duplicate of the file
446 // descriptor which was transmitted: *it is not just a copy of the integer like
447 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
448 // this case, the receiving end will see a value of -1. *Zero is a valid file
451 // The received file descriptor will have the |auto_close| flag set to true. The
452 // code which handles the message is responsible for taking ownership of it.
453 // File descriptors are OS resources and must be closed when no longer needed.
455 // When sending a file descriptor, the file descriptor must be valid at the time
456 // of transmission. Since transmission is not synchronous, one should consider
457 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
458 // flag, which causes the file descriptor to be closed after writing.
460 struct IPC_EXPORT ParamTraits
<base::FileDescriptor
> {
461 typedef base::FileDescriptor param_type
;
462 static void Write(Message
* m
, const param_type
& p
);
463 static bool Read(const Message
* m
,
464 base::PickleIterator
* iter
,
466 static void Log(const param_type
& p
, std::string
* l
);
468 #endif // defined(OS_POSIX)
471 struct IPC_EXPORT ParamTraits
<base::FilePath
> {
472 typedef base::FilePath param_type
;
473 static void Write(Message
* m
, const param_type
& p
);
474 static bool Read(const Message
* m
,
475 base::PickleIterator
* iter
,
477 static void Log(const param_type
& p
, std::string
* l
);
481 struct IPC_EXPORT ParamTraits
<base::ListValue
> {
482 typedef base::ListValue param_type
;
483 static void Write(Message
* m
, const param_type
& p
);
484 static bool Read(const Message
* m
,
485 base::PickleIterator
* iter
,
487 static void Log(const param_type
& p
, std::string
* l
);
491 struct IPC_EXPORT ParamTraits
<base::NullableString16
> {
492 typedef base::NullableString16 param_type
;
493 static void Write(Message
* m
, const param_type
& p
);
494 static bool Read(const Message
* m
,
495 base::PickleIterator
* iter
,
497 static void Log(const param_type
& p
, std::string
* l
);
501 struct IPC_EXPORT ParamTraits
<base::File::Info
> {
502 typedef base::File::Info param_type
;
503 static void Write(Message
* m
, const param_type
& p
);
504 static bool Read(const Message
* m
,
505 base::PickleIterator
* iter
,
507 static void Log(const param_type
& p
, std::string
* l
);
511 struct SimilarTypeTraits
<base::File::Error
> {
517 struct SimilarTypeTraits
<HWND
> {
520 #endif // defined(OS_WIN)
523 struct IPC_EXPORT ParamTraits
<base::Time
> {
524 typedef base::Time param_type
;
525 static void Write(Message
* m
, const param_type
& p
);
526 static bool Read(const Message
* m
,
527 base::PickleIterator
* iter
,
529 static void Log(const param_type
& p
, std::string
* l
);
533 struct IPC_EXPORT ParamTraits
<base::TimeDelta
> {
534 typedef base::TimeDelta param_type
;
535 static void Write(Message
* m
, const param_type
& p
);
536 static bool Read(const Message
* m
,
537 base::PickleIterator
* iter
,
539 static void Log(const param_type
& p
, std::string
* l
);
543 struct IPC_EXPORT ParamTraits
<base::TimeTicks
> {
544 typedef base::TimeTicks param_type
;
545 static void Write(Message
* m
, const param_type
& p
);
546 static bool Read(const Message
* m
,
547 base::PickleIterator
* iter
,
549 static void Log(const param_type
& p
, std::string
* l
);
553 struct IPC_EXPORT ParamTraits
<base::TraceTicks
> {
554 typedef base::TraceTicks param_type
;
555 static void Write(Message
* m
, const param_type
& p
);
556 static bool Read(const Message
* m
,
557 base::PickleIterator
* iter
,
559 static void Log(const param_type
& p
, std::string
* l
);
563 struct ParamTraits
<base::Tuple
<>> {
564 typedef base::Tuple
<> param_type
;
565 static void Write(Message
* m
, const param_type
& p
) {
567 static bool Read(const Message
* m
,
568 base::PickleIterator
* iter
,
572 static void Log(const param_type
& p
, std::string
* l
) {
577 struct ParamTraits
<base::Tuple
<A
>> {
578 typedef base::Tuple
<A
> param_type
;
579 static void Write(Message
* m
, const param_type
& p
) {
580 WriteParam(m
, base::get
<0>(p
));
582 static bool Read(const Message
* m
,
583 base::PickleIterator
* iter
,
585 return ReadParam(m
, iter
, &base::get
<0>(*r
));
587 static void Log(const param_type
& p
, std::string
* l
) {
588 LogParam(base::get
<0>(p
), l
);
592 template <class A
, class B
>
593 struct ParamTraits
<base::Tuple
<A
, B
>> {
594 typedef base::Tuple
<A
, B
> param_type
;
595 static void Write(Message
* m
, const param_type
& p
) {
596 WriteParam(m
, base::get
<0>(p
));
597 WriteParam(m
, base::get
<1>(p
));
599 static bool Read(const Message
* m
,
600 base::PickleIterator
* iter
,
602 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
603 ReadParam(m
, iter
, &base::get
<1>(*r
)));
605 static void Log(const param_type
& p
, std::string
* l
) {
606 LogParam(base::get
<0>(p
), l
);
608 LogParam(base::get
<1>(p
), l
);
612 template <class A
, class B
, class C
>
613 struct ParamTraits
<base::Tuple
<A
, B
, C
>> {
614 typedef base::Tuple
<A
, B
, C
> param_type
;
615 static void Write(Message
* m
, const param_type
& p
) {
616 WriteParam(m
, base::get
<0>(p
));
617 WriteParam(m
, base::get
<1>(p
));
618 WriteParam(m
, base::get
<2>(p
));
620 static bool Read(const Message
* m
,
621 base::PickleIterator
* iter
,
623 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
624 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
625 ReadParam(m
, iter
, &base::get
<2>(*r
)));
627 static void Log(const param_type
& p
, std::string
* l
) {
628 LogParam(base::get
<0>(p
), l
);
630 LogParam(base::get
<1>(p
), l
);
632 LogParam(base::get
<2>(p
), l
);
636 template <class A
, class B
, class C
, class D
>
637 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
>> {
638 typedef base::Tuple
<A
, B
, C
, D
> 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
));
643 WriteParam(m
, base::get
<3>(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
)) &&
651 ReadParam(m
, iter
, &base::get
<3>(*r
)));
653 static void Log(const param_type
& p
, std::string
* l
) {
654 LogParam(base::get
<0>(p
), l
);
656 LogParam(base::get
<1>(p
), l
);
658 LogParam(base::get
<2>(p
), l
);
660 LogParam(base::get
<3>(p
), l
);
664 template <class A
, class B
, class C
, class D
, class E
>
665 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
, E
>> {
666 typedef base::Tuple
<A
, B
, C
, D
, E
> param_type
;
667 static void Write(Message
* m
, const param_type
& p
) {
668 WriteParam(m
, base::get
<0>(p
));
669 WriteParam(m
, base::get
<1>(p
));
670 WriteParam(m
, base::get
<2>(p
));
671 WriteParam(m
, base::get
<3>(p
));
672 WriteParam(m
, base::get
<4>(p
));
674 static bool Read(const Message
* m
,
675 base::PickleIterator
* iter
,
677 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
678 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
679 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
680 ReadParam(m
, iter
, &base::get
<3>(*r
)) &&
681 ReadParam(m
, iter
, &base::get
<4>(*r
)));
683 static void Log(const param_type
& p
, std::string
* l
) {
684 LogParam(base::get
<0>(p
), l
);
686 LogParam(base::get
<1>(p
), l
);
688 LogParam(base::get
<2>(p
), l
);
690 LogParam(base::get
<3>(p
), l
);
692 LogParam(base::get
<4>(p
), l
);
697 struct ParamTraits
<ScopedVector
<P
> > {
698 typedef ScopedVector
<P
> param_type
;
699 static void Write(Message
* m
, const param_type
& p
) {
700 WriteParam(m
, static_cast<int>(p
.size()));
701 for (size_t i
= 0; i
< p
.size(); i
++)
702 WriteParam(m
, *p
[i
]);
704 static bool Read(const Message
* m
,
705 base::PickleIterator
* iter
,
708 if (!iter
->ReadLength(&size
))
710 if (INT_MAX
/sizeof(P
) <= static_cast<size_t>(size
))
713 for (int i
= 0; i
< size
; i
++) {
715 if (!ReadParam(m
, iter
, (*r
)[i
]))
720 static void Log(const param_type
& p
, std::string
* l
) {
721 for (size_t i
= 0; i
< p
.size(); ++i
) {
729 template <typename NormalMap
,
733 struct ParamTraits
<base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> > {
734 typedef base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> param_type
;
735 typedef typename
param_type::key_type K
;
736 typedef typename
param_type::data_type V
;
737 static void Write(Message
* m
, const param_type
& p
) {
738 WriteParam(m
, static_cast<int>(p
.size()));
739 typename
param_type::const_iterator iter
;
740 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
741 WriteParam(m
, iter
->first
);
742 WriteParam(m
, iter
->second
);
745 static bool Read(const Message
* m
,
746 base::PickleIterator
* iter
,
749 if (!iter
->ReadLength(&size
))
751 for (int i
= 0; i
< size
; ++i
) {
753 if (!ReadParam(m
, iter
, &key
))
755 V
& value
= (*r
)[key
];
756 if (!ReadParam(m
, iter
, &value
))
761 static void Log(const param_type
& p
, std::string
* l
) {
762 l
->append("<base::SmallMap>");
767 struct ParamTraits
<scoped_ptr
<P
> > {
768 typedef scoped_ptr
<P
> param_type
;
769 static void Write(Message
* m
, const param_type
& p
) {
771 WriteParam(m
, valid
);
775 static bool Read(const Message
* m
,
776 base::PickleIterator
* iter
,
779 if (!ReadParam(m
, iter
, &valid
))
787 param_type
temp(new P());
788 if (!ReadParam(m
, iter
, temp
.get()))
794 static void Log(const param_type
& p
, std::string
* l
) {
802 // IPC types ParamTraits -------------------------------------------------------
804 // A ChannelHandle is basically a platform-inspecific wrapper around the
805 // fact that IPC endpoints are handled specially on POSIX. See above comments
806 // on FileDescriptor for more background.
808 struct IPC_EXPORT ParamTraits
<IPC::ChannelHandle
> {
809 typedef ChannelHandle param_type
;
810 static void Write(Message
* m
, const param_type
& p
);
811 static bool Read(const Message
* m
,
812 base::PickleIterator
* iter
,
814 static void Log(const param_type
& p
, std::string
* l
);
818 struct IPC_EXPORT ParamTraits
<LogData
> {
819 typedef LogData param_type
;
820 static void Write(Message
* m
, const param_type
& p
);
821 static bool Read(const Message
* m
,
822 base::PickleIterator
* iter
,
824 static void Log(const param_type
& p
, std::string
* l
);
828 struct IPC_EXPORT ParamTraits
<Message
> {
829 static void Write(Message
* m
, const Message
& p
);
830 static bool Read(const Message
* m
,
831 base::PickleIterator
* iter
,
833 static void Log(const Message
& p
, std::string
* l
);
836 // Windows ParamTraits ---------------------------------------------------------
840 struct IPC_EXPORT ParamTraits
<HANDLE
> {
841 typedef HANDLE param_type
;
842 static void Write(Message
* m
, const param_type
& p
);
843 static bool Read(const Message
* m
,
844 base::PickleIterator
* iter
,
846 static void Log(const param_type
& p
, std::string
* l
);
850 struct IPC_EXPORT ParamTraits
<LOGFONT
> {
851 typedef LOGFONT param_type
;
852 static void Write(Message
* m
, const param_type
& p
);
853 static bool Read(const Message
* m
,
854 base::PickleIterator
* iter
,
856 static void Log(const param_type
& p
, std::string
* l
);
860 struct IPC_EXPORT ParamTraits
<MSG
> {
861 typedef MSG param_type
;
862 static void Write(Message
* m
, const param_type
& p
);
863 static bool Read(const Message
* m
,
864 base::PickleIterator
* iter
,
866 static void Log(const param_type
& p
, std::string
* l
);
868 #endif // defined(OS_WIN)
870 //-----------------------------------------------------------------------------
871 // Generic message subclasses
873 // Used for asynchronous messages.
874 template <class ParamType
>
875 class MessageSchema
{
877 typedef ParamType Param
;
878 typedef typename
base::TupleTypes
<ParamType
>::ParamTuple RefParam
;
880 static void Write(Message
* msg
, const RefParam
& p
) IPC_MSG_NOINLINE
;
881 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
884 // defined in ipc_logging.cc
885 IPC_EXPORT
void GenerateLogData(const std::string
& channel
,
886 const Message
& message
,
887 LogData
* data
, bool get_params
);
890 #if defined(IPC_MESSAGE_LOG_ENABLED)
891 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
892 const std::string
& output_params
= msg
->output_params();
893 if (!l
->empty() && !output_params
.empty())
896 l
->append(output_params
);
899 template <class ReplyParamType
>
900 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
901 const Message
* msg
) {
902 if (msg
->received_time() != 0) {
903 std::string output_params
;
904 LogParam(reply_params
, &output_params
);
905 msg
->set_output_params(output_params
);
909 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
910 if (msg
->sent_time()) {
911 // Don't log the sync message after dispatch, as we don't have the
912 // output parameters at that point. Instead, save its data and log it
913 // with the outgoing reply message when it's sent.
914 LogData
* data
= new LogData
;
915 GenerateLogData("", *msg
, data
, true);
917 reply
->set_sync_log_data(data
);
921 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
923 template <class ReplyParamType
>
924 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
925 const Message
* msg
) {}
927 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
930 // This class assumes that its template argument is a RefTuple (a Tuple with
931 // reference elements). This would go into ipc_message_utils_impl.h, but it is
932 // also used by chrome_frame.
933 template <class RefTuple
>
934 class ParamDeserializer
: public MessageReplyDeserializer
{
936 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
938 bool SerializeOutputParameters(const IPC::Message
& msg
,
939 base::PickleIterator iter
) override
{
940 return ReadParam(&msg
, &iter
, &out_
);
946 // Used for synchronous messages.
947 template <class SendParamType
, class ReplyParamType
>
948 class SyncMessageSchema
{
950 typedef SendParamType SendParam
;
951 typedef typename
base::TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
952 typedef ReplyParamType ReplyParam
;
954 static void Write(Message
* msg
, const RefSendParam
& send
) IPC_MSG_NOINLINE
;
955 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
956 static bool ReadReplyParam(
958 typename
base::TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
960 template<class T
, class S
, class Method
>
961 static bool DispatchWithSendParams(bool ok
, const SendParam
& send_params
,
962 const Message
* msg
, T
* obj
, S
* sender
,
964 Message
* reply
= SyncMessage::GenerateReply(msg
);
966 typename
base::TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
967 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
968 WriteParam(reply
, reply_params
);
969 LogReplyParamsToMessage(reply_params
, msg
);
971 NOTREACHED() << "Error deserializing message " << msg
->type();
972 reply
->set_reply_error();
978 template<class T
, class Method
>
979 static bool DispatchDelayReplyWithSendParams(bool ok
,
980 const SendParam
& send_params
,
981 const Message
* msg
, T
* obj
,
983 Message
* reply
= SyncMessage::GenerateReply(msg
);
985 base::Tuple
<Message
&> t
= base::MakeRefTuple(*reply
);
986 ConnectMessageAndReply(msg
, reply
);
987 DispatchToMethod(obj
, func
, send_params
, &t
);
989 NOTREACHED() << "Error deserializing message " << msg
->type();
990 reply
->set_reply_error();
996 template <typename
... Ts
>
997 static void WriteReplyParams(Message
* reply
, Ts
... args
) {
998 ReplyParam
p(args
...);
999 WriteParam(reply
, p
);
1005 #endif // IPC_IPC_MESSAGE_UTILS_H_