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
;
58 struct FileDescriptor
;
65 // -----------------------------------------------------------------------------
66 // How we send IPC message logs across channels.
67 struct IPC_EXPORT LogData
{
73 uint32 type
; // "User-defined" message type, from ipc_message.h.
75 int64 sent
; // Time that the message was sent (i.e. at Send()).
76 int64 receive
; // Time before it was dispatched (i.e. before calling
77 // OnMessageReceived).
78 int64 dispatch
; // Time after it was dispatched (i.e. after calling
79 // OnMessageReceived).
80 std::string message_name
;
84 //-----------------------------------------------------------------------------
86 // A dummy struct to place first just to allow leading commas for all
87 // members in the macro-generated constructor initializer lists.
92 static inline void WriteParam(Message
* m
, const P
& p
) {
93 typedef typename SimilarTypeTraits
<P
>::Type Type
;
94 ParamTraits
<Type
>::Write(m
, static_cast<const Type
& >(p
));
98 static inline bool WARN_UNUSED_RESULT
ReadParam(const Message
* m
,
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
, PickleIterator
* iter
, param_type
* r
) {
120 return iter
->ReadBool(r
);
122 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
126 struct IPC_EXPORT ParamTraits
<unsigned char> {
127 typedef unsigned char param_type
;
128 static void Write(Message
* m
, const param_type
& p
);
129 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
130 static void Log(const param_type
& p
, std::string
* l
);
134 struct IPC_EXPORT ParamTraits
<unsigned short> {
135 typedef unsigned short param_type
;
136 static void Write(Message
* m
, const param_type
& p
);
137 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
138 static void Log(const param_type
& p
, std::string
* l
);
142 struct ParamTraits
<int> {
143 typedef int param_type
;
144 static void Write(Message
* m
, const param_type
& p
) {
147 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
148 return iter
->ReadInt(r
);
150 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
154 struct ParamTraits
<unsigned int> {
155 typedef unsigned int param_type
;
156 static void Write(Message
* m
, const param_type
& p
) {
159 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
160 return iter
->ReadInt(reinterpret_cast<int*>(r
));
162 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
166 struct ParamTraits
<long> {
167 typedef long param_type
;
168 static void Write(Message
* m
, const param_type
& p
) {
169 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
171 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
172 return iter
->ReadLong(r
);
174 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
178 struct ParamTraits
<unsigned long> {
179 typedef unsigned long param_type
;
180 static void Write(Message
* m
, const param_type
& p
) {
181 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
183 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
184 return iter
->ReadLong(reinterpret_cast<long*>(r
));
186 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
190 struct ParamTraits
<long long> {
191 typedef long long param_type
;
192 static void Write(Message
* m
, const param_type
& p
) {
193 m
->WriteInt64(static_cast<int64
>(p
));
195 static bool Read(const Message
* m
, PickleIterator
* iter
,
197 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
199 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
203 struct ParamTraits
<unsigned long long> {
204 typedef unsigned long long param_type
;
205 static void Write(Message
* m
, const param_type
& p
) {
208 static bool Read(const Message
* m
, PickleIterator
* iter
,
210 return iter
->ReadInt64(reinterpret_cast<int64
*>(r
));
212 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
215 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
216 // should be sure to check the sanity of these values after receiving them over
219 struct IPC_EXPORT ParamTraits
<float> {
220 typedef float param_type
;
221 static void Write(Message
* m
, const param_type
& p
) {
224 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
225 return iter
->ReadFloat(r
);
227 static void Log(const param_type
& p
, std::string
* l
);
231 struct IPC_EXPORT ParamTraits
<double> {
232 typedef double param_type
;
233 static void Write(Message
* m
, const param_type
& p
);
234 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
235 static void Log(const param_type
& p
, std::string
* l
);
238 // STL ParamTraits -------------------------------------------------------------
241 struct ParamTraits
<std::string
> {
242 typedef std::string param_type
;
243 static void Write(Message
* m
, const param_type
& p
) {
246 static bool Read(const Message
* m
, PickleIterator
* iter
,
248 return iter
->ReadString(r
);
250 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
254 struct ParamTraits
<base::string16
> {
255 typedef base::string16 param_type
;
256 static void Write(Message
* m
, const param_type
& p
) {
259 static bool Read(const Message
* m
, PickleIterator
* iter
,
261 return iter
->ReadString16(r
);
263 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
267 struct IPC_EXPORT ParamTraits
<std::vector
<char> > {
268 typedef std::vector
<char> param_type
;
269 static void Write(Message
* m
, const param_type
& p
);
270 static bool Read(const Message
*, PickleIterator
* iter
, param_type
* r
);
271 static void Log(const param_type
& p
, std::string
* l
);
275 struct IPC_EXPORT ParamTraits
<std::vector
<unsigned char> > {
276 typedef std::vector
<unsigned char> param_type
;
277 static void Write(Message
* m
, const param_type
& p
);
278 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
279 static void Log(const param_type
& p
, std::string
* l
);
283 struct IPC_EXPORT ParamTraits
<std::vector
<bool> > {
284 typedef std::vector
<bool> param_type
;
285 static void Write(Message
* m
, const param_type
& p
);
286 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
287 static void Log(const param_type
& p
, std::string
* l
);
291 struct ParamTraits
<std::vector
<P
> > {
292 typedef std::vector
<P
> param_type
;
293 static void Write(Message
* m
, const param_type
& p
) {
294 WriteParam(m
, static_cast<int>(p
.size()));
295 for (size_t i
= 0; i
< p
.size(); i
++)
298 static bool Read(const Message
* m
, PickleIterator
* iter
,
301 // ReadLength() checks for < 0 itself.
302 if (!iter
->ReadLength(&size
))
304 // Resizing beforehand is not safe, see BUG 1006367 for details.
305 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
308 for (int i
= 0; i
< size
; i
++) {
309 if (!ReadParam(m
, iter
, &(*r
)[i
]))
314 static void Log(const param_type
& p
, std::string
* l
) {
315 for (size_t i
= 0; i
< p
.size(); ++i
) {
324 struct ParamTraits
<std::set
<P
> > {
325 typedef std::set
<P
> param_type
;
326 static void Write(Message
* m
, const param_type
& p
) {
327 WriteParam(m
, static_cast<int>(p
.size()));
328 typename
param_type::const_iterator iter
;
329 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
330 WriteParam(m
, *iter
);
332 static bool Read(const Message
* m
, PickleIterator
* iter
,
335 if (!iter
->ReadLength(&size
))
337 for (int i
= 0; i
< size
; ++i
) {
339 if (!ReadParam(m
, iter
, &item
))
345 static void Log(const param_type
& p
, std::string
* l
) {
346 l
->append("<std::set>");
350 template <class K
, class V
, class C
, class A
>
351 struct ParamTraits
<std::map
<K
, V
, C
, A
> > {
352 typedef std::map
<K
, V
, C
, A
> 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
->first
);
358 WriteParam(m
, iter
->second
);
361 static bool Read(const Message
* m
, PickleIterator
* iter
,
364 if (!ReadParam(m
, iter
, &size
) || size
< 0)
366 for (int i
= 0; i
< size
; ++i
) {
368 if (!ReadParam(m
, iter
, &k
))
371 if (!ReadParam(m
, iter
, &value
))
376 static void Log(const param_type
& p
, std::string
* l
) {
377 l
->append("<std::map>");
381 template <class A
, class B
>
382 struct ParamTraits
<std::pair
<A
, B
> > {
383 typedef std::pair
<A
, B
> param_type
;
384 static void Write(Message
* m
, const param_type
& p
) {
385 WriteParam(m
, p
.first
);
386 WriteParam(m
, p
.second
);
388 static bool Read(const Message
* m
, PickleIterator
* iter
,
390 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
392 static void Log(const param_type
& p
, std::string
* l
) {
394 LogParam(p
.first
, l
);
396 LogParam(p
.second
, l
);
401 // Base ParamTraits ------------------------------------------------------------
404 struct IPC_EXPORT ParamTraits
<base::DictionaryValue
> {
405 typedef base::DictionaryValue param_type
;
406 static void Write(Message
* m
, const param_type
& p
);
407 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
408 static void Log(const param_type
& p
, std::string
* l
);
411 #if defined(OS_POSIX)
412 // FileDescriptors may be serialised over IPC channels on POSIX. On the
413 // receiving side, the FileDescriptor is a valid duplicate of the file
414 // descriptor which was transmitted: *it is not just a copy of the integer like
415 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
416 // this case, the receiving end will see a value of -1. *Zero is a valid file
419 // The received file descriptor will have the |auto_close| flag set to true. The
420 // code which handles the message is responsible for taking ownership of it.
421 // File descriptors are OS resources and must be closed when no longer needed.
423 // When sending a file descriptor, the file descriptor must be valid at the time
424 // of transmission. Since transmission is not synchronous, one should consider
425 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
426 // flag, which causes the file descriptor to be closed after writing.
428 struct IPC_EXPORT ParamTraits
<base::FileDescriptor
> {
429 typedef base::FileDescriptor param_type
;
430 static void Write(Message
* m
, const param_type
& p
);
431 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
432 static void Log(const param_type
& p
, std::string
* l
);
434 #endif // defined(OS_POSIX)
437 struct IPC_EXPORT ParamTraits
<base::FilePath
> {
438 typedef base::FilePath param_type
;
439 static void Write(Message
* m
, const param_type
& p
);
440 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
441 static void Log(const param_type
& p
, std::string
* l
);
445 struct IPC_EXPORT ParamTraits
<base::ListValue
> {
446 typedef base::ListValue param_type
;
447 static void Write(Message
* m
, const param_type
& p
);
448 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
449 static void Log(const param_type
& p
, std::string
* l
);
453 struct IPC_EXPORT ParamTraits
<base::NullableString16
> {
454 typedef base::NullableString16 param_type
;
455 static void Write(Message
* m
, const param_type
& p
);
456 static bool Read(const Message
* m
, PickleIterator
* iter
,
458 static void Log(const param_type
& p
, std::string
* l
);
462 struct IPC_EXPORT ParamTraits
<base::File::Info
> {
463 typedef base::File::Info param_type
;
464 static void Write(Message
* m
, const param_type
& p
);
465 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
466 static void Log(const param_type
& p
, std::string
* l
);
470 struct SimilarTypeTraits
<base::File::Error
> {
476 struct SimilarTypeTraits
<HWND
> {
479 #endif // defined(OS_WIN)
482 struct IPC_EXPORT ParamTraits
<base::Time
> {
483 typedef base::Time param_type
;
484 static void Write(Message
* m
, const param_type
& p
);
485 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
486 static void Log(const param_type
& p
, std::string
* l
);
490 struct IPC_EXPORT ParamTraits
<base::TimeDelta
> {
491 typedef base::TimeDelta param_type
;
492 static void Write(Message
* m
, const param_type
& p
);
493 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
494 static void Log(const param_type
& p
, std::string
* l
);
498 struct IPC_EXPORT ParamTraits
<base::TimeTicks
> {
499 typedef base::TimeTicks param_type
;
500 static void Write(Message
* m
, const param_type
& p
);
501 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
502 static void Log(const param_type
& p
, std::string
* l
);
506 struct ParamTraits
<Tuple
<>> {
507 typedef Tuple
<> param_type
;
508 static void Write(Message
* m
, const param_type
& p
) {
510 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
513 static void Log(const param_type
& p
, std::string
* l
) {
518 struct ParamTraits
<Tuple
<A
>> {
519 typedef Tuple
<A
> param_type
;
520 static void Write(Message
* m
, const param_type
& p
) {
521 WriteParam(m
, get
<0>(p
));
523 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
524 return ReadParam(m
, iter
, &get
<0>(*r
));
526 static void Log(const param_type
& p
, std::string
* l
) {
527 LogParam(get
<0>(p
), l
);
531 template <class A
, class B
>
532 struct ParamTraits
< Tuple
<A
, B
> > {
533 typedef Tuple
<A
, B
> param_type
;
534 static void Write(Message
* m
, const param_type
& p
) {
535 WriteParam(m
, get
<0>(p
));
536 WriteParam(m
, get
<1>(p
));
538 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
539 return (ReadParam(m
, iter
, &get
<0>(*r
)) &&
540 ReadParam(m
, iter
, &get
<1>(*r
)));
542 static void Log(const param_type
& p
, std::string
* l
) {
543 LogParam(get
<0>(p
), l
);
545 LogParam(get
<1>(p
), l
);
549 template <class A
, class B
, class C
>
550 struct ParamTraits
< Tuple
<A
, B
, C
> > {
551 typedef Tuple
<A
, B
, C
> param_type
;
552 static void Write(Message
* m
, const param_type
& p
) {
553 WriteParam(m
, get
<0>(p
));
554 WriteParam(m
, get
<1>(p
));
555 WriteParam(m
, get
<2>(p
));
557 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
558 return (ReadParam(m
, iter
, &get
<0>(*r
)) &&
559 ReadParam(m
, iter
, &get
<1>(*r
)) &&
560 ReadParam(m
, iter
, &get
<2>(*r
)));
562 static void Log(const param_type
& p
, std::string
* l
) {
563 LogParam(get
<0>(p
), l
);
565 LogParam(get
<1>(p
), l
);
567 LogParam(get
<2>(p
), l
);
571 template <class A
, class B
, class C
, class D
>
572 struct ParamTraits
< Tuple
<A
, B
, C
, D
> > {
573 typedef Tuple
<A
, B
, C
, D
> param_type
;
574 static void Write(Message
* m
, const param_type
& p
) {
575 WriteParam(m
, get
<0>(p
));
576 WriteParam(m
, get
<1>(p
));
577 WriteParam(m
, get
<2>(p
));
578 WriteParam(m
, get
<3>(p
));
580 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
581 return (ReadParam(m
, iter
, &get
<0>(*r
)) &&
582 ReadParam(m
, iter
, &get
<1>(*r
)) &&
583 ReadParam(m
, iter
, &get
<2>(*r
)) &&
584 ReadParam(m
, iter
, &get
<3>(*r
)));
586 static void Log(const param_type
& p
, std::string
* l
) {
587 LogParam(get
<0>(p
), l
);
589 LogParam(get
<1>(p
), l
);
591 LogParam(get
<2>(p
), l
);
593 LogParam(get
<3>(p
), l
);
597 template <class A
, class B
, class C
, class D
, class E
>
598 struct ParamTraits
< Tuple
<A
, B
, C
, D
, E
> > {
599 typedef Tuple
<A
, B
, C
, D
, E
> param_type
;
600 static void Write(Message
* m
, const param_type
& p
) {
601 WriteParam(m
, get
<0>(p
));
602 WriteParam(m
, get
<1>(p
));
603 WriteParam(m
, get
<2>(p
));
604 WriteParam(m
, get
<3>(p
));
605 WriteParam(m
, get
<4>(p
));
607 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
608 return (ReadParam(m
, iter
, &get
<0>(*r
)) &&
609 ReadParam(m
, iter
, &get
<1>(*r
)) &&
610 ReadParam(m
, iter
, &get
<2>(*r
)) &&
611 ReadParam(m
, iter
, &get
<3>(*r
)) &&
612 ReadParam(m
, iter
, &get
<4>(*r
)));
614 static void Log(const param_type
& p
, std::string
* l
) {
615 LogParam(get
<0>(p
), l
);
617 LogParam(get
<1>(p
), l
);
619 LogParam(get
<2>(p
), l
);
621 LogParam(get
<3>(p
), l
);
623 LogParam(get
<4>(p
), l
);
628 struct ParamTraits
<ScopedVector
<P
> > {
629 typedef ScopedVector
<P
> param_type
;
630 static void Write(Message
* m
, const param_type
& p
) {
631 WriteParam(m
, static_cast<int>(p
.size()));
632 for (size_t i
= 0; i
< p
.size(); i
++)
633 WriteParam(m
, *p
[i
]);
635 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
637 if (!iter
->ReadLength(&size
))
639 if (INT_MAX
/sizeof(P
) <= static_cast<size_t>(size
))
642 for (int i
= 0; i
< size
; i
++) {
644 if (!ReadParam(m
, iter
, (*r
)[i
]))
649 static void Log(const param_type
& p
, std::string
* l
) {
650 for (size_t i
= 0; i
< p
.size(); ++i
) {
658 template <typename NormalMap
,
662 struct ParamTraits
<base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> > {
663 typedef base::SmallMap
<NormalMap
, kArraySize
, EqualKey
, MapInit
> param_type
;
664 typedef typename
param_type::key_type K
;
665 typedef typename
param_type::data_type V
;
666 static void Write(Message
* m
, const param_type
& p
) {
667 WriteParam(m
, static_cast<int>(p
.size()));
668 typename
param_type::const_iterator iter
;
669 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
670 WriteParam(m
, iter
->first
);
671 WriteParam(m
, iter
->second
);
674 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
676 if (!iter
->ReadLength(&size
))
678 for (int i
= 0; i
< size
; ++i
) {
680 if (!ReadParam(m
, iter
, &key
))
682 V
& value
= (*r
)[key
];
683 if (!ReadParam(m
, iter
, &value
))
688 static void Log(const param_type
& p
, std::string
* l
) {
689 l
->append("<base::SmallMap>");
694 struct ParamTraits
<scoped_ptr
<P
> > {
695 typedef scoped_ptr
<P
> param_type
;
696 static void Write(Message
* m
, const param_type
& p
) {
698 WriteParam(m
, valid
);
702 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
704 if (!ReadParam(m
, iter
, &valid
))
712 param_type
temp(new P());
713 if (!ReadParam(m
, iter
, temp
.get()))
719 static void Log(const param_type
& p
, std::string
* l
) {
727 // IPC types ParamTraits -------------------------------------------------------
729 // A ChannelHandle is basically a platform-inspecific wrapper around the
730 // fact that IPC endpoints are handled specially on POSIX. See above comments
731 // on FileDescriptor for more background.
733 struct IPC_EXPORT ParamTraits
<IPC::ChannelHandle
> {
734 typedef ChannelHandle param_type
;
735 static void Write(Message
* m
, const param_type
& p
);
736 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
737 static void Log(const param_type
& p
, std::string
* l
);
741 struct IPC_EXPORT ParamTraits
<LogData
> {
742 typedef LogData param_type
;
743 static void Write(Message
* m
, const param_type
& p
);
744 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
745 static void Log(const param_type
& p
, std::string
* l
);
749 struct IPC_EXPORT ParamTraits
<Message
> {
750 static void Write(Message
* m
, const Message
& p
);
751 static bool Read(const Message
* m
, PickleIterator
* iter
, Message
* r
);
752 static void Log(const Message
& p
, std::string
* l
);
755 // Windows ParamTraits ---------------------------------------------------------
759 struct IPC_EXPORT ParamTraits
<HANDLE
> {
760 typedef HANDLE param_type
;
761 static void Write(Message
* m
, const param_type
& p
);
762 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
763 static void Log(const param_type
& p
, std::string
* l
);
767 struct IPC_EXPORT ParamTraits
<LOGFONT
> {
768 typedef LOGFONT param_type
;
769 static void Write(Message
* m
, const param_type
& p
);
770 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
771 static void Log(const param_type
& p
, std::string
* l
);
775 struct IPC_EXPORT ParamTraits
<MSG
> {
776 typedef MSG param_type
;
777 static void Write(Message
* m
, const param_type
& p
);
778 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
779 static void Log(const param_type
& p
, std::string
* l
);
781 #endif // defined(OS_WIN)
783 //-----------------------------------------------------------------------------
784 // Generic message subclasses
786 // Used for asynchronous messages.
787 template <class ParamType
>
788 class MessageSchema
{
790 typedef ParamType Param
;
791 typedef typename TupleTypes
<ParamType
>::ParamTuple RefParam
;
793 static void Write(Message
* msg
, const RefParam
& p
) IPC_MSG_NOINLINE
;
794 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
797 // defined in ipc_logging.cc
798 IPC_EXPORT
void GenerateLogData(const std::string
& channel
,
799 const Message
& message
,
800 LogData
* data
, bool get_params
);
803 #if defined(IPC_MESSAGE_LOG_ENABLED)
804 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
805 const std::string
& output_params
= msg
->output_params();
806 if (!l
->empty() && !output_params
.empty())
809 l
->append(output_params
);
812 template <class ReplyParamType
>
813 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
814 const Message
* msg
) {
815 if (msg
->received_time() != 0) {
816 std::string output_params
;
817 LogParam(reply_params
, &output_params
);
818 msg
->set_output_params(output_params
);
822 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
823 if (msg
->sent_time()) {
824 // Don't log the sync message after dispatch, as we don't have the
825 // output parameters at that point. Instead, save its data and log it
826 // with the outgoing reply message when it's sent.
827 LogData
* data
= new LogData
;
828 GenerateLogData("", *msg
, data
, true);
830 reply
->set_sync_log_data(data
);
834 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
836 template <class ReplyParamType
>
837 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
838 const Message
* msg
) {}
840 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
843 // This class assumes that its template argument is a RefTuple (a Tuple with
844 // reference elements). This would go into ipc_message_utils_impl.h, but it is
845 // also used by chrome_frame.
846 template <class RefTuple
>
847 class ParamDeserializer
: public MessageReplyDeserializer
{
849 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
851 bool SerializeOutputParameters(const IPC::Message
& msg
,
852 PickleIterator iter
) override
{
853 return ReadParam(&msg
, &iter
, &out_
);
859 // Used for synchronous messages.
860 template <class SendParamType
, class ReplyParamType
>
861 class SyncMessageSchema
{
863 typedef SendParamType SendParam
;
864 typedef typename TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
865 typedef ReplyParamType ReplyParam
;
867 static void Write(Message
* msg
, const RefSendParam
& send
) IPC_MSG_NOINLINE
;
868 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
869 static bool ReadReplyParam(
871 typename TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
873 template<class T
, class S
, class Method
>
874 static bool DispatchWithSendParams(bool ok
, const SendParam
& send_params
,
875 const Message
* msg
, T
* obj
, S
* sender
,
877 Message
* reply
= SyncMessage::GenerateReply(msg
);
879 typename TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
880 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
881 WriteParam(reply
, reply_params
);
882 LogReplyParamsToMessage(reply_params
, msg
);
884 NOTREACHED() << "Error deserializing message " << msg
->type();
885 reply
->set_reply_error();
891 template<class T
, class Method
>
892 static bool DispatchDelayReplyWithSendParams(bool ok
,
893 const SendParam
& send_params
,
894 const Message
* msg
, T
* obj
,
896 Message
* reply
= SyncMessage::GenerateReply(msg
);
898 Tuple
<Message
&> t
= MakeRefTuple(*reply
);
899 ConnectMessageAndReply(msg
, reply
);
900 DispatchToMethod(obj
, func
, send_params
, &t
);
902 NOTREACHED() << "Error deserializing message " << msg
->type();
903 reply
->set_reply_error();
909 template <typename
... Ts
>
910 static void WriteReplyParams(Message
* reply
, Ts
... args
) {
911 ReplyParam
p(args
...);
912 WriteParam(reply
, p
);
918 #endif // IPC_IPC_MESSAGE_UTILS_H_