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
ReadParam(const Message
* m
,
100 PickleIterator
* iter
,
102 typedef typename SimilarTypeTraits
<P
>::Type Type
;
103 return ParamTraits
<Type
>::Read(m
, iter
, reinterpret_cast<Type
* >(p
));
107 static inline void LogParam(const P
& p
, std::string
* l
) {
108 typedef typename SimilarTypeTraits
<P
>::Type Type
;
109 ParamTraits
<Type
>::Log(static_cast<const Type
& >(p
), l
);
112 // Primitive ParamTraits -------------------------------------------------------
115 struct ParamTraits
<bool> {
116 typedef bool param_type
;
117 static void Write(Message
* m
, const param_type
& p
) {
120 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
121 return iter
->ReadBool(r
);
123 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
127 struct IPC_EXPORT ParamTraits
<unsigned char> {
128 typedef unsigned char param_type
;
129 static void Write(Message
* m
, const param_type
& p
);
130 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
131 static void Log(const param_type
& p
, std::string
* l
);
135 struct IPC_EXPORT ParamTraits
<unsigned short> {
136 typedef unsigned short param_type
;
137 static void Write(Message
* m
, const param_type
& p
);
138 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
139 static void Log(const param_type
& p
, std::string
* l
);
143 struct ParamTraits
<int> {
144 typedef int param_type
;
145 static void Write(Message
* m
, const param_type
& p
) {
148 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
149 return iter
->ReadInt(r
);
151 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
155 struct ParamTraits
<unsigned int> {
156 typedef unsigned int param_type
;
157 static void Write(Message
* m
, const param_type
& p
) {
160 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
161 return iter
->ReadInt(reinterpret_cast<int*>(r
));
163 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
167 struct ParamTraits
<long> {
168 typedef long param_type
;
169 static void Write(Message
* m
, const param_type
& p
) {
170 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
172 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
173 return iter
->ReadLong(r
);
175 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
179 struct ParamTraits
<unsigned long> {
180 typedef unsigned long param_type
;
181 static void Write(Message
* m
, const param_type
& p
) {
182 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
184 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
185 return iter
->ReadLong(reinterpret_cast<long*>(r
));
187 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
191 struct ParamTraits
<long long> {
192 typedef long long param_type
;
193 static void Write(Message
* m
, const param_type
& p
) {
194 m
->WriteInt64(static_cast<int64
>(p
));
196 static bool Read(const Message
* m
, PickleIterator
* iter
,
198 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
200 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
204 struct ParamTraits
<unsigned long long> {
205 typedef unsigned long long param_type
;
206 static void Write(Message
* m
, const param_type
& p
) {
209 static bool Read(const Message
* m
, PickleIterator
* iter
,
211 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
213 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
216 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
217 // should be sure to check the sanity of these values after receiving them over
220 struct IPC_EXPORT ParamTraits
<float> {
221 typedef float param_type
;
222 static void Write(Message
* m
, const param_type
& p
) {
225 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
226 return iter
->ReadFloat(r
);
228 static void Log(const param_type
& p
, std::string
* l
);
232 struct IPC_EXPORT ParamTraits
<double> {
233 typedef double param_type
;
234 static void Write(Message
* m
, const param_type
& p
);
235 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
236 static void Log(const param_type
& p
, std::string
* l
);
239 // STL ParamTraits -------------------------------------------------------------
242 struct ParamTraits
<std::string
> {
243 typedef std::string param_type
;
244 static void Write(Message
* m
, const param_type
& p
) {
247 static bool Read(const Message
* m
, PickleIterator
* iter
,
249 return iter
->ReadString(r
);
251 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
255 struct ParamTraits
<base::string16
> {
256 typedef base::string16 param_type
;
257 static void Write(Message
* m
, const param_type
& p
) {
260 static bool Read(const Message
* m
, PickleIterator
* iter
,
262 return iter
->ReadString16(r
);
264 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
268 struct IPC_EXPORT ParamTraits
<std::vector
<char> > {
269 typedef std::vector
<char> param_type
;
270 static void Write(Message
* m
, const param_type
& p
);
271 static bool Read(const Message
*, PickleIterator
* iter
, param_type
* r
);
272 static void Log(const param_type
& p
, std::string
* l
);
276 struct IPC_EXPORT ParamTraits
<std::vector
<unsigned char> > {
277 typedef std::vector
<unsigned char> param_type
;
278 static void Write(Message
* m
, const param_type
& p
);
279 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
280 static void Log(const param_type
& p
, std::string
* l
);
284 struct IPC_EXPORT ParamTraits
<std::vector
<bool> > {
285 typedef std::vector
<bool> param_type
;
286 static void Write(Message
* m
, const param_type
& p
);
287 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
288 static void Log(const param_type
& p
, std::string
* l
);
292 struct ParamTraits
<std::vector
<P
> > {
293 typedef std::vector
<P
> param_type
;
294 static void Write(Message
* m
, const param_type
& p
) {
295 WriteParam(m
, static_cast<int>(p
.size()));
296 for (size_t i
= 0; i
< p
.size(); i
++)
299 static bool Read(const Message
* m
, PickleIterator
* iter
,
302 // ReadLength() checks for < 0 itself.
303 if (!iter
->ReadLength(&size
))
305 // Resizing beforehand is not safe, see BUG 1006367 for details.
306 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
309 for (int i
= 0; i
< size
; i
++) {
310 if (!ReadParam(m
, iter
, &(*r
)[i
]))
315 static void Log(const param_type
& p
, std::string
* l
) {
316 for (size_t i
= 0; i
< p
.size(); ++i
) {
325 struct ParamTraits
<std::set
<P
> > {
326 typedef std::set
<P
> param_type
;
327 static void Write(Message
* m
, const param_type
& p
) {
328 WriteParam(m
, static_cast<int>(p
.size()));
329 typename
param_type::const_iterator iter
;
330 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
331 WriteParam(m
, *iter
);
333 static bool Read(const Message
* m
, PickleIterator
* iter
,
336 if (!iter
->ReadLength(&size
))
338 for (int i
= 0; i
< size
; ++i
) {
340 if (!ReadParam(m
, iter
, &item
))
346 static void Log(const param_type
& p
, std::string
* l
) {
347 l
->append("<std::set>");
351 template <class K
, class V
, class C
, class A
>
352 struct ParamTraits
<std::map
<K
, V
, C
, A
> > {
353 typedef std::map
<K
, V
, C
, A
> param_type
;
354 static void Write(Message
* m
, const param_type
& p
) {
355 WriteParam(m
, static_cast<int>(p
.size()));
356 typename
param_type::const_iterator iter
;
357 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
358 WriteParam(m
, iter
->first
);
359 WriteParam(m
, iter
->second
);
362 static bool Read(const Message
* m
, PickleIterator
* iter
,
365 if (!ReadParam(m
, iter
, &size
) || size
< 0)
367 for (int i
= 0; i
< size
; ++i
) {
369 if (!ReadParam(m
, iter
, &k
))
372 if (!ReadParam(m
, iter
, &value
))
377 static void Log(const param_type
& p
, std::string
* l
) {
378 l
->append("<std::map>");
382 template <class A
, class B
>
383 struct ParamTraits
<std::pair
<A
, B
> > {
384 typedef std::pair
<A
, B
> param_type
;
385 static void Write(Message
* m
, const param_type
& p
) {
386 WriteParam(m
, p
.first
);
387 WriteParam(m
, p
.second
);
389 static bool Read(const Message
* m
, PickleIterator
* iter
,
391 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
393 static void Log(const param_type
& p
, std::string
* l
) {
395 LogParam(p
.first
, l
);
397 LogParam(p
.second
, l
);
402 // Base ParamTraits ------------------------------------------------------------
405 struct IPC_EXPORT ParamTraits
<base::DictionaryValue
> {
406 typedef base::DictionaryValue param_type
;
407 static void Write(Message
* m
, const param_type
& p
);
408 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
409 static void Log(const param_type
& p
, std::string
* l
);
412 #if defined(OS_POSIX)
413 // FileDescriptors may be serialised over IPC channels on POSIX. On the
414 // receiving side, the FileDescriptor is a valid duplicate of the file
415 // descriptor which was transmitted: *it is not just a copy of the integer like
416 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
417 // this case, the receiving end will see a value of -1. *Zero is a valid file
420 // The received file descriptor will have the |auto_close| flag set to true. The
421 // code which handles the message is responsible for taking ownership of it.
422 // File descriptors are OS resources and must be closed when no longer needed.
424 // When sending a file descriptor, the file descriptor must be valid at the time
425 // of transmission. Since transmission is not synchronous, one should consider
426 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
427 // flag, which causes the file descriptor to be closed after writing.
429 struct IPC_EXPORT ParamTraits
<base::FileDescriptor
> {
430 typedef base::FileDescriptor param_type
;
431 static void Write(Message
* m
, const param_type
& p
);
432 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
433 static void Log(const param_type
& p
, std::string
* l
);
435 #endif // defined(OS_POSIX)
438 struct IPC_EXPORT ParamTraits
<base::FilePath
> {
439 typedef base::FilePath param_type
;
440 static void Write(Message
* m
, const param_type
& p
);
441 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
442 static void Log(const param_type
& p
, std::string
* l
);
446 struct IPC_EXPORT ParamTraits
<base::ListValue
> {
447 typedef base::ListValue param_type
;
448 static void Write(Message
* m
, const param_type
& p
);
449 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
450 static void Log(const param_type
& p
, std::string
* l
);
454 struct IPC_EXPORT ParamTraits
<base::NullableString16
> {
455 typedef base::NullableString16 param_type
;
456 static void Write(Message
* m
, const param_type
& p
);
457 static bool Read(const Message
* m
, PickleIterator
* iter
,
459 static void Log(const param_type
& p
, std::string
* l
);
463 struct IPC_EXPORT ParamTraits
<base::File::Info
> {
464 typedef base::File::Info param_type
;
465 static void Write(Message
* m
, const param_type
& p
);
466 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
467 static void Log(const param_type
& p
, std::string
* l
);
471 struct SimilarTypeTraits
<base::File::Error
> {
477 struct SimilarTypeTraits
<HWND
> {
480 #endif // defined(OS_WIN)
483 struct IPC_EXPORT ParamTraits
<base::Time
> {
484 typedef base::Time param_type
;
485 static void Write(Message
* m
, const param_type
& p
);
486 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
487 static void Log(const param_type
& p
, std::string
* l
);
491 struct IPC_EXPORT ParamTraits
<base::TimeDelta
> {
492 typedef base::TimeDelta param_type
;
493 static void Write(Message
* m
, const param_type
& p
);
494 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
495 static void Log(const param_type
& p
, std::string
* l
);
499 struct IPC_EXPORT ParamTraits
<base::TimeTicks
> {
500 typedef base::TimeTicks param_type
;
501 static void Write(Message
* m
, const param_type
& p
);
502 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
503 static void Log(const param_type
& p
, std::string
* l
);
507 struct IPC_EXPORT ParamTraits
<base::TraceTicks
> {
508 typedef base::TraceTicks param_type
;
509 static void Write(Message
* m
, const param_type
& p
);
510 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
511 static void Log(const param_type
& p
, std::string
* l
);
515 struct ParamTraits
<base::Tuple
<>> {
516 typedef base::Tuple
<> param_type
;
517 static void Write(Message
* m
, const param_type
& p
) {
519 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
522 static void Log(const param_type
& p
, std::string
* l
) {
527 struct ParamTraits
<base::Tuple
<A
>> {
528 typedef base::Tuple
<A
> param_type
;
529 static void Write(Message
* m
, const param_type
& p
) {
530 WriteParam(m
, base::get
<0>(p
));
532 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
533 return ReadParam(m
, iter
, &base::get
<0>(*r
));
535 static void Log(const param_type
& p
, std::string
* l
) {
536 LogParam(base::get
<0>(p
), l
);
540 template <class A
, class B
>
541 struct ParamTraits
<base::Tuple
<A
, B
>> {
542 typedef base::Tuple
<A
, B
> param_type
;
543 static void Write(Message
* m
, const param_type
& p
) {
544 WriteParam(m
, base::get
<0>(p
));
545 WriteParam(m
, base::get
<1>(p
));
547 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
548 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
549 ReadParam(m
, iter
, &base::get
<1>(*r
)));
551 static void Log(const param_type
& p
, std::string
* l
) {
552 LogParam(base::get
<0>(p
), l
);
554 LogParam(base::get
<1>(p
), l
);
558 template <class A
, class B
, class C
>
559 struct ParamTraits
<base::Tuple
<A
, B
, C
>> {
560 typedef base::Tuple
<A
, B
, C
> param_type
;
561 static void Write(Message
* m
, const param_type
& p
) {
562 WriteParam(m
, base::get
<0>(p
));
563 WriteParam(m
, base::get
<1>(p
));
564 WriteParam(m
, base::get
<2>(p
));
566 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
567 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
568 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
569 ReadParam(m
, iter
, &base::get
<2>(*r
)));
571 static void Log(const param_type
& p
, std::string
* l
) {
572 LogParam(base::get
<0>(p
), l
);
574 LogParam(base::get
<1>(p
), l
);
576 LogParam(base::get
<2>(p
), l
);
580 template <class A
, class B
, class C
, class D
>
581 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
>> {
582 typedef base::Tuple
<A
, B
, C
, D
> param_type
;
583 static void Write(Message
* m
, const param_type
& p
) {
584 WriteParam(m
, base::get
<0>(p
));
585 WriteParam(m
, base::get
<1>(p
));
586 WriteParam(m
, base::get
<2>(p
));
587 WriteParam(m
, base::get
<3>(p
));
589 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
590 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
591 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
592 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
593 ReadParam(m
, iter
, &base::get
<3>(*r
)));
595 static void Log(const param_type
& p
, std::string
* l
) {
596 LogParam(base::get
<0>(p
), l
);
598 LogParam(base::get
<1>(p
), l
);
600 LogParam(base::get
<2>(p
), l
);
602 LogParam(base::get
<3>(p
), l
);
606 template <class A
, class B
, class C
, class D
, class E
>
607 struct ParamTraits
<base::Tuple
<A
, B
, C
, D
, E
>> {
608 typedef base::Tuple
<A
, B
, C
, D
, E
> 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
));
612 WriteParam(m
, base::get
<2>(p
));
613 WriteParam(m
, base::get
<3>(p
));
614 WriteParam(m
, base::get
<4>(p
));
616 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
617 return (ReadParam(m
, iter
, &base::get
<0>(*r
)) &&
618 ReadParam(m
, iter
, &base::get
<1>(*r
)) &&
619 ReadParam(m
, iter
, &base::get
<2>(*r
)) &&
620 ReadParam(m
, iter
, &base::get
<3>(*r
)) &&
621 ReadParam(m
, iter
, &base::get
<4>(*r
)));
623 static void Log(const param_type
& p
, std::string
* l
) {
624 LogParam(base::get
<0>(p
), l
);
626 LogParam(base::get
<1>(p
), l
);
628 LogParam(base::get
<2>(p
), l
);
630 LogParam(base::get
<3>(p
), l
);
632 LogParam(base::get
<4>(p
), l
);
637 struct ParamTraits
<ScopedVector
<P
> > {
638 typedef ScopedVector
<P
> param_type
;
639 static void Write(Message
* m
, const param_type
& p
) {
640 WriteParam(m
, static_cast<int>(p
.size()));
641 for (size_t i
= 0; i
< p
.size(); i
++)
642 WriteParam(m
, *p
[i
]);
644 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
646 if (!iter
->ReadLength(&size
))
648 if (INT_MAX
/sizeof(P
) <= static_cast<size_t>(size
))
651 for (int i
= 0; i
< size
; i
++) {
653 if (!ReadParam(m
, iter
, (*r
)[i
]))
658 static void Log(const param_type
& p
, std::string
* l
) {
659 for (size_t i
= 0; i
< p
.size(); ++i
) {
667 template <typename NormalMap
,
671 struct ParamTraits
<base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> > {
672 typedef base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> param_type
;
673 typedef typename
param_type::key_type K
;
674 typedef typename
param_type::data_type V
;
675 static void Write(Message
* m
, const param_type
& p
) {
676 WriteParam(m
, static_cast<int>(p
.size()));
677 typename
param_type::const_iterator iter
;
678 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
679 WriteParam(m
, iter
->first
);
680 WriteParam(m
, iter
->second
);
683 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
685 if (!iter
->ReadLength(&size
))
687 for (int i
= 0; i
< size
; ++i
) {
689 if (!ReadParam(m
, iter
, &key
))
691 V
& value
= (*r
)[key
];
692 if (!ReadParam(m
, iter
, &value
))
697 static void Log(const param_type
& p
, std::string
* l
) {
698 l
->append("<base::SmallMap>");
703 struct ParamTraits
<scoped_ptr
<P
> > {
704 typedef scoped_ptr
<P
> param_type
;
705 static void Write(Message
* m
, const param_type
& p
) {
707 WriteParam(m
, valid
);
711 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
713 if (!ReadParam(m
, iter
, &valid
))
721 param_type
temp(new P());
722 if (!ReadParam(m
, iter
, temp
.get()))
728 static void Log(const param_type
& p
, std::string
* l
) {
736 // IPC types ParamTraits -------------------------------------------------------
738 // A ChannelHandle is basically a platform-inspecific wrapper around the
739 // fact that IPC endpoints are handled specially on POSIX. See above comments
740 // on FileDescriptor for more background.
742 struct IPC_EXPORT ParamTraits
<IPC::ChannelHandle
> {
743 typedef ChannelHandle param_type
;
744 static void Write(Message
* m
, const param_type
& p
);
745 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
746 static void Log(const param_type
& p
, std::string
* l
);
750 struct IPC_EXPORT ParamTraits
<LogData
> {
751 typedef LogData param_type
;
752 static void Write(Message
* m
, const param_type
& p
);
753 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
754 static void Log(const param_type
& p
, std::string
* l
);
758 struct IPC_EXPORT ParamTraits
<Message
> {
759 static void Write(Message
* m
, const Message
& p
);
760 static bool Read(const Message
* m
, PickleIterator
* iter
, Message
* r
);
761 static void Log(const Message
& p
, std::string
* l
);
764 // Windows ParamTraits ---------------------------------------------------------
768 struct IPC_EXPORT ParamTraits
<HANDLE
> {
769 typedef HANDLE param_type
;
770 static void Write(Message
* m
, const param_type
& p
);
771 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
772 static void Log(const param_type
& p
, std::string
* l
);
776 struct IPC_EXPORT ParamTraits
<LOGFONT
> {
777 typedef LOGFONT param_type
;
778 static void Write(Message
* m
, const param_type
& p
);
779 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
780 static void Log(const param_type
& p
, std::string
* l
);
784 struct IPC_EXPORT ParamTraits
<MSG
> {
785 typedef MSG param_type
;
786 static void Write(Message
* m
, const param_type
& p
);
787 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
788 static void Log(const param_type
& p
, std::string
* l
);
790 #endif // defined(OS_WIN)
792 //-----------------------------------------------------------------------------
793 // Generic message subclasses
795 // Used for asynchronous messages.
796 template <class ParamType
>
797 class MessageSchema
{
799 typedef ParamType Param
;
800 typedef typename
base::TupleTypes
<ParamType
>::ParamTuple RefParam
;
802 static void Write(Message
* msg
, const RefParam
& p
) IPC_MSG_NOINLINE
;
803 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
806 // defined in ipc_logging.cc
807 IPC_EXPORT
void GenerateLogData(const std::string
& channel
,
808 const Message
& message
,
809 LogData
* data
, bool get_params
);
812 #if defined(IPC_MESSAGE_LOG_ENABLED)
813 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
814 const std::string
& output_params
= msg
->output_params();
815 if (!l
->empty() && !output_params
.empty())
818 l
->append(output_params
);
821 template <class ReplyParamType
>
822 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
823 const Message
* msg
) {
824 if (msg
->received_time() != 0) {
825 std::string output_params
;
826 LogParam(reply_params
, &output_params
);
827 msg
->set_output_params(output_params
);
831 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
832 if (msg
->sent_time()) {
833 // Don't log the sync message after dispatch, as we don't have the
834 // output parameters at that point. Instead, save its data and log it
835 // with the outgoing reply message when it's sent.
836 LogData
* data
= new LogData
;
837 GenerateLogData("", *msg
, data
, true);
839 reply
->set_sync_log_data(data
);
843 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
845 template <class ReplyParamType
>
846 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
847 const Message
* msg
) {}
849 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
852 // This class assumes that its template argument is a RefTuple (a Tuple with
853 // reference elements). This would go into ipc_message_utils_impl.h, but it is
854 // also used by chrome_frame.
855 template <class RefTuple
>
856 class ParamDeserializer
: public MessageReplyDeserializer
{
858 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
860 bool SerializeOutputParameters(const IPC::Message
& msg
,
861 PickleIterator iter
) override
{
862 return ReadParam(&msg
, &iter
, &out_
);
868 // Used for synchronous messages.
869 template <class SendParamType
, class ReplyParamType
>
870 class SyncMessageSchema
{
872 typedef SendParamType SendParam
;
873 typedef typename
base::TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
874 typedef ReplyParamType ReplyParam
;
876 static void Write(Message
* msg
, const RefSendParam
& send
) IPC_MSG_NOINLINE
;
877 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
878 static bool ReadReplyParam(
880 typename
base::TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
882 template<class T
, class S
, class Method
>
883 static bool DispatchWithSendParams(bool ok
, const SendParam
& send_params
,
884 const Message
* msg
, T
* obj
, S
* sender
,
886 Message
* reply
= SyncMessage::GenerateReply(msg
);
888 typename
base::TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
889 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
890 WriteParam(reply
, reply_params
);
891 LogReplyParamsToMessage(reply_params
, msg
);
893 NOTREACHED() << "Error deserializing message " << msg
->type();
894 reply
->set_reply_error();
900 template<class T
, class Method
>
901 static bool DispatchDelayReplyWithSendParams(bool ok
,
902 const SendParam
& send_params
,
903 const Message
* msg
, T
* obj
,
905 Message
* reply
= SyncMessage::GenerateReply(msg
);
907 base::Tuple
<Message
&> t
= base::MakeRefTuple(*reply
);
908 ConnectMessageAndReply(msg
, reply
);
909 DispatchToMethod(obj
, func
, send_params
, &t
);
911 NOTREACHED() << "Error deserializing message " << msg
->type();
912 reply
->set_reply_error();
918 template <typename
... Ts
>
919 static void WriteReplyParams(Message
* reply
, Ts
... args
) {
920 ReplyParam
p(args
...);
921 WriteParam(reply
, p
);
927 #endif // IPC_IPC_MESSAGE_UTILS_H_