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
;
61 #if defined(OS_MACOSX) && !defined(OS_IOS)
62 class SharedMemoryHandle
;
63 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
70 // -----------------------------------------------------------------------------
71 // How we send IPC message logs across channels.
72 struct IPC_EXPORT LogData
{
78 uint32 type
; // "User-defined" message type, from ipc_message.h.
80 int64 sent
; // Time that the message was sent (i.e. at Send()).
81 int64 receive
; // Time before it was dispatched (i.e. before calling
82 // OnMessageReceived).
83 int64 dispatch
; // Time after it was dispatched (i.e. after calling
84 // OnMessageReceived).
85 std::string message_name
;
89 //-----------------------------------------------------------------------------
91 // A dummy struct to place first just to allow leading commas for all
92 // members in the macro-generated constructor initializer lists.
97 static inline void WriteParam(Message
* m
, const P
& p
) {
98 typedef typename SimilarTypeTraits
<P
>::Type Type
;
99 ParamTraits
<Type
>::Write(m
, static_cast<const Type
& >(p
));
103 static inline bool WARN_UNUSED_RESULT
104 ReadParam(const Message
* m
, base::PickleIterator
* iter
, P
* p
) {
105 typedef typename SimilarTypeTraits
<P
>::Type Type
;
106 return ParamTraits
<Type
>::Read(m
, iter
, reinterpret_cast<Type
* >(p
));
110 static inline void LogParam(const P
& p
, std::string
* l
) {
111 typedef typename SimilarTypeTraits
<P
>::Type Type
;
112 ParamTraits
<Type
>::Log(static_cast<const Type
& >(p
), l
);
115 // Primitive ParamTraits -------------------------------------------------------
118 struct ParamTraits
<bool> {
119 typedef bool param_type
;
120 static void Write(Message
* m
, const param_type
& p
) {
123 static bool Read(const Message
* m
,
124 base::PickleIterator
* iter
,
126 return iter
->ReadBool(r
);
128 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
132 struct IPC_EXPORT ParamTraits
<unsigned char> {
133 typedef unsigned char param_type
;
134 static void Write(Message
* m
, const param_type
& p
);
135 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
136 static void Log(const param_type
& p
, std::string
* l
);
140 struct IPC_EXPORT ParamTraits
<unsigned short> {
141 typedef unsigned short param_type
;
142 static void Write(Message
* m
, const param_type
& p
);
143 static bool Read(const Message
* m
,
144 base::PickleIterator
* iter
,
146 static void Log(const param_type
& p
, std::string
* l
);
150 struct ParamTraits
<int> {
151 typedef int param_type
;
152 static void Write(Message
* m
, const param_type
& p
) {
155 static bool Read(const Message
* m
,
156 base::PickleIterator
* iter
,
158 return iter
->ReadInt(r
);
160 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
164 struct ParamTraits
<unsigned int> {
165 typedef unsigned int param_type
;
166 static void Write(Message
* m
, const param_type
& p
) {
169 static bool Read(const Message
* m
,
170 base::PickleIterator
* iter
,
172 return iter
->ReadInt(reinterpret_cast<int*>(r
));
174 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
178 struct ParamTraits
<long> {
179 typedef long param_type
;
180 static void Write(Message
* m
, const param_type
& p
) {
181 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
183 static bool Read(const Message
* m
,
184 base::PickleIterator
* iter
,
186 return iter
->ReadLong(r
);
188 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
192 struct ParamTraits
<unsigned long> {
193 typedef unsigned long param_type
;
194 static void Write(Message
* m
, const param_type
& p
) {
195 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
197 static bool Read(const Message
* m
,
198 base::PickleIterator
* iter
,
200 return iter
->ReadLong(reinterpret_cast<long*>(r
));
202 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
206 struct ParamTraits
<long long> {
207 typedef long long param_type
;
208 static void Write(Message
* m
, const param_type
& p
) {
209 m
->WriteInt64(static_cast<int64
>(p
));
211 static bool Read(const Message
* m
,
212 base::PickleIterator
* iter
,
214 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
216 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
220 struct ParamTraits
<unsigned long long> {
221 typedef unsigned long long param_type
;
222 static void Write(Message
* m
, const param_type
& p
) {
225 static bool Read(const Message
* m
,
226 base::PickleIterator
* iter
,
228 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
230 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
233 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
234 // should be sure to check the sanity of these values after receiving them over
237 struct IPC_EXPORT ParamTraits
<float> {
238 typedef float param_type
;
239 static void Write(Message
* m
, const param_type
& p
) {
242 static bool Read(const Message
* m
,
243 base::PickleIterator
* iter
,
245 return iter
->ReadFloat(r
);
247 static void Log(const param_type
& p
, std::string
* l
);
251 struct IPC_EXPORT ParamTraits
<double> {
252 typedef double param_type
;
253 static void Write(Message
* m
, const param_type
& p
);
254 static bool Read(const Message
* m
,
255 base::PickleIterator
* iter
,
257 static void Log(const param_type
& p
, std::string
* l
);
260 // STL ParamTraits -------------------------------------------------------------
263 struct ParamTraits
<std::string
> {
264 typedef std::string param_type
;
265 static void Write(Message
* m
, const param_type
& p
) {
268 static bool Read(const Message
* m
,
269 base::PickleIterator
* iter
,
271 return iter
->ReadString(r
);
273 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
277 struct ParamTraits
<base::string16
> {
278 typedef base::string16 param_type
;
279 static void Write(Message
* m
, const param_type
& p
) {
282 static bool Read(const Message
* m
,
283 base::PickleIterator
* iter
,
285 return iter
->ReadString16(r
);
287 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
291 struct IPC_EXPORT ParamTraits
<std::vector
<char> > {
292 typedef std::vector
<char> param_type
;
293 static void Write(Message
* m
, const param_type
& p
);
294 static bool Read(const Message
*,
295 base::PickleIterator
* iter
,
297 static void Log(const param_type
& p
, std::string
* l
);
301 struct IPC_EXPORT ParamTraits
<std::vector
<unsigned char> > {
302 typedef std::vector
<unsigned char> param_type
;
303 static void Write(Message
* m
, const param_type
& p
);
304 static bool Read(const Message
* m
,
305 base::PickleIterator
* iter
,
307 static void Log(const param_type
& p
, std::string
* l
);
311 struct IPC_EXPORT ParamTraits
<std::vector
<bool> > {
312 typedef std::vector
<bool> param_type
;
313 static void Write(Message
* m
, const param_type
& p
);
314 static bool Read(const Message
* m
,
315 base::PickleIterator
* iter
,
317 static void Log(const param_type
& p
, std::string
* l
);
321 struct ParamTraits
<std::vector
<P
> > {
322 typedef std::vector
<P
> param_type
;
323 static void Write(Message
* m
, const param_type
& p
) {
324 WriteParam(m
, static_cast<int>(p
.size()));
325 for (size_t i
= 0; i
< p
.size(); i
++)
328 static bool Read(const Message
* m
,
329 base::PickleIterator
* iter
,
332 // ReadLength() checks for < 0 itself.
333 if (!iter
->ReadLength(&size
))
335 // Resizing beforehand is not safe, see BUG 1006367 for details.
336 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
339 for (int i
= 0; i
< size
; i
++) {
340 if (!ReadParam(m
, iter
, &(*r
)[i
]))
345 static void Log(const param_type
& p
, std::string
* l
) {
346 for (size_t i
= 0; i
< p
.size(); ++i
) {
355 struct ParamTraits
<std::set
<P
> > {
356 typedef std::set
<P
> param_type
;
357 static void Write(Message
* m
, const param_type
& p
) {
358 WriteParam(m
, static_cast<int>(p
.size()));
359 typename
param_type::const_iterator iter
;
360 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
361 WriteParam(m
, *iter
);
363 static bool Read(const Message
* m
,
364 base::PickleIterator
* iter
,
367 if (!iter
->ReadLength(&size
))
369 for (int i
= 0; i
< size
; ++i
) {
371 if (!ReadParam(m
, iter
, &item
))
377 static void Log(const param_type
& p
, std::string
* l
) {
378 l
->append("<std::set>");
382 template <class K
, class V
, class C
, class A
>
383 struct ParamTraits
<std::map
<K
, V
, C
, A
> > {
384 typedef std::map
<K
, V
, C
, A
> param_type
;
385 static void Write(Message
* m
, const param_type
& p
) {
386 WriteParam(m
, static_cast<int>(p
.size()));
387 typename
param_type::const_iterator iter
;
388 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
389 WriteParam(m
, iter
->first
);
390 WriteParam(m
, iter
->second
);
393 static bool Read(const Message
* m
,
394 base::PickleIterator
* iter
,
397 if (!ReadParam(m
, iter
, &size
) || size
< 0)
399 for (int i
= 0; i
< size
; ++i
) {
401 if (!ReadParam(m
, iter
, &k
))
404 if (!ReadParam(m
, iter
, &value
))
409 static void Log(const param_type
& p
, std::string
* l
) {
410 l
->append("<std::map>");
414 template <class A
, class B
>
415 struct ParamTraits
<std::pair
<A
, B
> > {
416 typedef std::pair
<A
, B
> param_type
;
417 static void Write(Message
* m
, const param_type
& p
) {
418 WriteParam(m
, p
.first
);
419 WriteParam(m
, p
.second
);
421 static bool Read(const Message
* m
,
422 base::PickleIterator
* iter
,
424 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
426 static void Log(const param_type
& p
, std::string
* l
) {
428 LogParam(p
.first
, l
);
430 LogParam(p
.second
, l
);
435 // Base ParamTraits ------------------------------------------------------------
438 struct IPC_EXPORT ParamTraits
<base::DictionaryValue
> {
439 typedef base::DictionaryValue param_type
;
440 static void Write(Message
* m
, const param_type
& p
);
441 static bool Read(const Message
* m
,
442 base::PickleIterator
* iter
,
444 static void Log(const param_type
& p
, std::string
* l
);
447 #if defined(OS_POSIX)
448 // FileDescriptors may be serialised over IPC channels on POSIX. On the
449 // receiving side, the FileDescriptor is a valid duplicate of the file
450 // descriptor which was transmitted: *it is not just a copy of the integer like
451 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
452 // this case, the receiving end will see a value of -1. *Zero is a valid file
455 // The received file descriptor will have the |auto_close| flag set to true. The
456 // code which handles the message is responsible for taking ownership of it.
457 // File descriptors are OS resources and must be closed when no longer needed.
459 // When sending a file descriptor, the file descriptor must be valid at the time
460 // of transmission. Since transmission is not synchronous, one should consider
461 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
462 // flag, which causes the file descriptor to be closed after writing.
464 struct IPC_EXPORT ParamTraits
<base::FileDescriptor
> {
465 typedef base::FileDescriptor param_type
;
466 static void Write(Message
* m
, const param_type
& p
);
467 static bool Read(const Message
* m
,
468 base::PickleIterator
* iter
,
470 static void Log(const param_type
& p
, std::string
* l
);
472 #endif // defined(OS_POSIX)
474 #if defined(OS_MACOSX) && !defined(OS_IOS)
476 struct IPC_EXPORT ParamTraits
<base::SharedMemoryHandle
> {
477 typedef base::SharedMemoryHandle param_type
;
478 static void Write(Message
* m
, const param_type
& p
);
479 static bool Read(const Message
* m
, base::PickleIterator
* iter
, param_type
* r
);
480 static void Log(const param_type
& p
, std::string
* l
);
485 struct IPC_EXPORT ParamTraits
<base::FilePath
> {
486 typedef base::FilePath param_type
;
487 static void Write(Message
* m
, const param_type
& p
);
488 static bool Read(const Message
* m
,
489 base::PickleIterator
* iter
,
491 static void Log(const param_type
& p
, std::string
* l
);
495 struct IPC_EXPORT ParamTraits
<base::ListValue
> {
496 typedef base::ListValue 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::NullableString16
> {
506 typedef base::NullableString16 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::File::Info
> {
516 typedef base::File::Info 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 SimilarTypeTraits
<base::File::Error
> {
531 struct SimilarTypeTraits
<HWND
> {
534 #endif // defined(OS_WIN)
537 struct IPC_EXPORT ParamTraits
<base::Time
> {
538 typedef base::Time param_type
;
539 static void Write(Message
* m
, const param_type
& p
);
540 static bool Read(const Message
* m
,
541 base::PickleIterator
* iter
,
543 static void Log(const param_type
& p
, std::string
* l
);
547 struct IPC_EXPORT ParamTraits
<base::TimeDelta
> {
548 typedef base::TimeDelta 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::TimeTicks
> {
558 typedef base::TimeTicks 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::TraceTicks
> {
568 typedef base::TraceTicks 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 ParamTraits
<base::Tuple
<>> {
578 typedef base::Tuple
<> param_type
;
579 static void Write(Message
* m
, const param_type
& p
) {
581 static bool Read(const Message
* m
,
582 base::PickleIterator
* iter
,
586 static void Log(const param_type
& p
, std::string
* l
) {
591 struct ParamTraits
<base::Tuple
<A
>> {
592 typedef base::Tuple
<A
> param_type
;
593 static void Write(Message
* m
, const param_type
& p
) {
594 WriteParam(m
, base::get
<0>(p
));
596 static bool Read(const Message
* m
,
597 base::PickleIterator
* iter
,
599 return ReadParam(m
, iter
, &base::get
<0>(*r
));
601 static void Log(const param_type
& p
, std::string
* l
) {
602 LogParam(base::get
<0>(p
), l
);
606 template <class A
, class B
>
607 struct ParamTraits
<base::Tuple
<A
, B
>> {
608 typedef base::Tuple
<A
, B
> param_type
;
609 static void Write(Message
* m
, const param_type
& p
) {
610 WriteParam(m
, base::get
<0>(p
));
611 WriteParam(m
, base::get
<1>(p
));
613 static bool Read(const Message
* m
,
614 base::PickleIterator
* iter
,
616 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
617 ReadParam(m
, iter
, &base::get
<1>(*r
)));
619 static void Log(const param_type
& p
, std::string
* l
) {
620 LogParam(base::get
<0>(p
), l
);
622 LogParam(base::get
<1>(p
), l
);
626 template <class A
, class B
, class C
>
627 struct ParamTraits
<base::Tuple
<A
, B
, C
>> {
628 typedef base::Tuple
<A
, B
, C
> param_type
;
629 static void Write(Message
* m
, const param_type
& p
) {
630 WriteParam(m
, base::get
<0>(p
));
631 WriteParam(m
, base::get
<1>(p
));
632 WriteParam(m
, base::get
<2>(p
));
634 static bool Read(const Message
* m
,
635 base::PickleIterator
* iter
,
637 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
638 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
639 ReadParam(m
, iter
, &base::get
<2>(*r
)));
641 static void Log(const param_type
& p
, std::string
* l
) {
642 LogParam(base::get
<0>(p
), l
);
644 LogParam(base::get
<1>(p
), l
);
646 LogParam(base::get
<2>(p
), l
);
650 template <class A
, class B
, class C
, class D
>
651 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
>> {
652 typedef base::Tuple
<A
, B
, C
, D
> param_type
;
653 static void Write(Message
* m
, const param_type
& p
) {
654 WriteParam(m
, base::get
<0>(p
));
655 WriteParam(m
, base::get
<1>(p
));
656 WriteParam(m
, base::get
<2>(p
));
657 WriteParam(m
, base::get
<3>(p
));
659 static bool Read(const Message
* m
,
660 base::PickleIterator
* iter
,
662 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
663 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
664 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
665 ReadParam(m
, iter
, &base::get
<3>(*r
)));
667 static void Log(const param_type
& p
, std::string
* l
) {
668 LogParam(base::get
<0>(p
), l
);
670 LogParam(base::get
<1>(p
), l
);
672 LogParam(base::get
<2>(p
), l
);
674 LogParam(base::get
<3>(p
), l
);
678 template <class A
, class B
, class C
, class D
, class E
>
679 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
, E
>> {
680 typedef base::Tuple
<A
, B
, C
, D
, E
> param_type
;
681 static void Write(Message
* m
, const param_type
& p
) {
682 WriteParam(m
, base::get
<0>(p
));
683 WriteParam(m
, base::get
<1>(p
));
684 WriteParam(m
, base::get
<2>(p
));
685 WriteParam(m
, base::get
<3>(p
));
686 WriteParam(m
, base::get
<4>(p
));
688 static bool Read(const Message
* m
,
689 base::PickleIterator
* iter
,
691 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
692 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
693 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
694 ReadParam(m
, iter
, &base::get
<3>(*r
)) &&
695 ReadParam(m
, iter
, &base::get
<4>(*r
)));
697 static void Log(const param_type
& p
, std::string
* l
) {
698 LogParam(base::get
<0>(p
), l
);
700 LogParam(base::get
<1>(p
), l
);
702 LogParam(base::get
<2>(p
), l
);
704 LogParam(base::get
<3>(p
), l
);
706 LogParam(base::get
<4>(p
), l
);
711 struct ParamTraits
<ScopedVector
<P
> > {
712 typedef ScopedVector
<P
> param_type
;
713 static void Write(Message
* m
, const param_type
& p
) {
714 WriteParam(m
, static_cast<int>(p
.size()));
715 for (size_t i
= 0; i
< p
.size(); i
++)
716 WriteParam(m
, *p
[i
]);
718 static bool Read(const Message
* m
,
719 base::PickleIterator
* iter
,
722 if (!iter
->ReadLength(&size
))
724 if (INT_MAX
/sizeof(P
) <= static_cast<size_t>(size
))
727 for (int i
= 0; i
< size
; i
++) {
729 if (!ReadParam(m
, iter
, (*r
)[i
]))
734 static void Log(const param_type
& p
, std::string
* l
) {
735 for (size_t i
= 0; i
< p
.size(); ++i
) {
743 template <typename NormalMap
,
747 struct ParamTraits
<base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> > {
748 typedef base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> param_type
;
749 typedef typename
param_type::key_type K
;
750 typedef typename
param_type::data_type V
;
751 static void Write(Message
* m
, const param_type
& p
) {
752 WriteParam(m
, static_cast<int>(p
.size()));
753 typename
param_type::const_iterator iter
;
754 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
755 WriteParam(m
, iter
->first
);
756 WriteParam(m
, iter
->second
);
759 static bool Read(const Message
* m
,
760 base::PickleIterator
* iter
,
763 if (!iter
->ReadLength(&size
))
765 for (int i
= 0; i
< size
; ++i
) {
767 if (!ReadParam(m
, iter
, &key
))
769 V
& value
= (*r
)[key
];
770 if (!ReadParam(m
, iter
, &value
))
775 static void Log(const param_type
& p
, std::string
* l
) {
776 l
->append("<base::SmallMap>");
781 struct ParamTraits
<scoped_ptr
<P
> > {
782 typedef scoped_ptr
<P
> param_type
;
783 static void Write(Message
* m
, const param_type
& p
) {
785 WriteParam(m
, valid
);
789 static bool Read(const Message
* m
,
790 base::PickleIterator
* iter
,
793 if (!ReadParam(m
, iter
, &valid
))
801 param_type
temp(new P());
802 if (!ReadParam(m
, iter
, temp
.get()))
808 static void Log(const param_type
& p
, std::string
* l
) {
816 // IPC types ParamTraits -------------------------------------------------------
818 // A ChannelHandle is basically a platform-inspecific wrapper around the
819 // fact that IPC endpoints are handled specially on POSIX. See above comments
820 // on FileDescriptor for more background.
822 struct IPC_EXPORT ParamTraits
<IPC::ChannelHandle
> {
823 typedef ChannelHandle param_type
;
824 static void Write(Message
* m
, const param_type
& p
);
825 static bool Read(const Message
* m
,
826 base::PickleIterator
* iter
,
828 static void Log(const param_type
& p
, std::string
* l
);
832 struct IPC_EXPORT ParamTraits
<LogData
> {
833 typedef LogData 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
<Message
> {
843 static void Write(Message
* m
, const Message
& p
);
844 static bool Read(const Message
* m
,
845 base::PickleIterator
* iter
,
847 static void Log(const Message
& p
, std::string
* l
);
850 // Windows ParamTraits ---------------------------------------------------------
854 struct IPC_EXPORT ParamTraits
<HANDLE
> {
855 typedef HANDLE param_type
;
856 static void Write(Message
* m
, const param_type
& p
);
857 static bool Read(const Message
* m
,
858 base::PickleIterator
* iter
,
860 static void Log(const param_type
& p
, std::string
* l
);
864 struct IPC_EXPORT ParamTraits
<LOGFONT
> {
865 typedef LOGFONT 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
<MSG
> {
875 typedef MSG 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
);
882 #endif // defined(OS_WIN)
884 //-----------------------------------------------------------------------------
885 // Generic message subclasses
887 // Used for asynchronous messages.
888 template <class ParamType
>
889 class MessageSchema
{
891 typedef ParamType Param
;
892 typedef typename
base::TupleTypes
<ParamType
>::ParamTuple RefParam
;
894 static void Write(Message
* msg
, const RefParam
& p
) IPC_MSG_NOINLINE
;
895 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
898 // defined in ipc_logging.cc
899 IPC_EXPORT
void GenerateLogData(const std::string
& channel
,
900 const Message
& message
,
901 LogData
* data
, bool get_params
);
904 #if defined(IPC_MESSAGE_LOG_ENABLED)
905 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
906 const std::string
& output_params
= msg
->output_params();
907 if (!l
->empty() && !output_params
.empty())
910 l
->append(output_params
);
913 template <class ReplyParamType
>
914 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
915 const Message
* msg
) {
916 if (msg
->received_time() != 0) {
917 std::string output_params
;
918 LogParam(reply_params
, &output_params
);
919 msg
->set_output_params(output_params
);
923 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
924 if (msg
->sent_time()) {
925 // Don't log the sync message after dispatch, as we don't have the
926 // output parameters at that point. Instead, save its data and log it
927 // with the outgoing reply message when it's sent.
928 LogData
* data
= new LogData
;
929 GenerateLogData("", *msg
, data
, true);
931 reply
->set_sync_log_data(data
);
935 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
937 template <class ReplyParamType
>
938 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
939 const Message
* msg
) {}
941 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
944 // This class assumes that its template argument is a RefTuple (a Tuple with
945 // reference elements). This would go into ipc_message_utils_impl.h, but it is
946 // also used by chrome_frame.
947 template <class RefTuple
>
948 class ParamDeserializer
: public MessageReplyDeserializer
{
950 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
952 bool SerializeOutputParameters(const IPC::Message
& msg
,
953 base::PickleIterator iter
) override
{
954 return ReadParam(&msg
, &iter
, &out_
);
960 // Used for synchronous messages.
961 template <class SendParamType
, class ReplyParamType
>
962 class SyncMessageSchema
{
964 typedef SendParamType SendParam
;
965 typedef typename
base::TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
966 typedef ReplyParamType ReplyParam
;
968 static void Write(Message
* msg
, const RefSendParam
& send
) IPC_MSG_NOINLINE
;
969 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
970 static bool ReadReplyParam(
972 typename
base::TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
974 template<class T
, class S
, class Method
>
975 static bool DispatchWithSendParams(bool ok
, const SendParam
& send_params
,
976 const Message
* msg
, T
* obj
, S
* sender
,
978 Message
* reply
= SyncMessage::GenerateReply(msg
);
980 typename
base::TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
981 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
982 WriteParam(reply
, reply_params
);
983 LogReplyParamsToMessage(reply_params
, msg
);
985 NOTREACHED() << "Error deserializing message " << msg
->type();
986 reply
->set_reply_error();
992 template<class T
, class Method
>
993 static bool DispatchDelayReplyWithSendParams(bool ok
,
994 const SendParam
& send_params
,
995 const Message
* msg
, T
* obj
,
997 Message
* reply
= SyncMessage::GenerateReply(msg
);
999 base::Tuple
<Message
&> t
= base::MakeRefTuple(*reply
);
1000 ConnectMessageAndReply(msg
, reply
);
1001 DispatchToMethod(obj
, func
, send_params
, &t
);
1003 NOTREACHED() << "Error deserializing message " << msg
->type();
1004 reply
->set_reply_error();
1010 template <typename
... Ts
>
1011 static void WriteReplyParams(Message
* reply
, Ts
... args
) {
1012 ReplyParam
p(args
...);
1013 WriteParam(reply
, p
);
1019 #endif // IPC_IPC_MESSAGE_UTILS_H_