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/format_macros.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/platform_file.h"
17 #include "base/strings/string16.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/tuple.h"
21 #include "ipc/ipc_message_start.h"
22 #include "ipc/ipc_param_traits.h"
23 #include "ipc/ipc_sync_message.h"
25 #if defined(COMPILER_GCC)
26 // GCC "helpfully" tries to inline template methods in release mode. Except we
27 // want the majority of the template junk being expanded once in the
28 // implementation file (and only provide the definitions in
29 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
30 // at every call site. Special note: GCC happily accepts the attribute before
31 // the method declaration, but only acts on it if it is after.
32 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
33 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
34 // the introduced noclone attribute, which will create specialized versions of
35 // functions/methods when certain types are constant.
36 // www.gnu.org/software/gcc/gcc-4.5/changes.html
37 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
39 #define IPC_MSG_NOINLINE __attribute__((noinline));
41 #elif defined(COMPILER_MSVC)
42 // MSVC++ doesn't do this.
43 #define IPC_MSG_NOINLINE
45 #error "Please add the noinline property for your new compiler here."
49 class DictionaryValue
;
52 class NullableString16
;
56 struct FileDescriptor
;
63 // -----------------------------------------------------------------------------
64 // How we send IPC message logs across channels.
65 struct IPC_EXPORT LogData
{
71 uint32 type
; // "User-defined" message type, from ipc_message.h.
73 int64 sent
; // Time that the message was sent (i.e. at Send()).
74 int64 receive
; // Time before it was dispatched (i.e. before calling
75 // OnMessageReceived).
76 int64 dispatch
; // Time after it was dispatched (i.e. after calling
77 // OnMessageReceived).
78 std::string message_name
;
82 //-----------------------------------------------------------------------------
84 // A dummy struct to place first just to allow leading commas for all
85 // members in the macro-generated constructor initializer lists.
90 static inline void WriteParam(Message
* m
, const P
& p
) {
91 typedef typename SimilarTypeTraits
<P
>::Type Type
;
92 ParamTraits
<Type
>::Write(m
, static_cast<const Type
& >(p
));
96 static inline bool WARN_UNUSED_RESULT
ReadParam(const Message
* m
,
99 typedef typename SimilarTypeTraits
<P
>::Type Type
;
100 return ParamTraits
<Type
>::Read(m
, iter
, reinterpret_cast<Type
* >(p
));
104 static inline void LogParam(const P
& p
, std::string
* l
) {
105 typedef typename SimilarTypeTraits
<P
>::Type Type
;
106 ParamTraits
<Type
>::Log(static_cast<const Type
& >(p
), l
);
109 // Primitive ParamTraits -------------------------------------------------------
112 struct ParamTraits
<bool> {
113 typedef bool param_type
;
114 static void Write(Message
* m
, const param_type
& p
) {
117 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
118 return m
->ReadBool(iter
, r
);
120 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
124 struct IPC_EXPORT ParamTraits
<unsigned char> {
125 typedef unsigned char param_type
;
126 static void Write(Message
* m
, const param_type
& p
);
127 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
128 static void Log(const param_type
& p
, std::string
* l
);
132 struct IPC_EXPORT ParamTraits
<unsigned short> {
133 typedef unsigned short param_type
;
134 static void Write(Message
* m
, const param_type
& p
);
135 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
136 static void Log(const param_type
& p
, std::string
* l
);
140 struct ParamTraits
<int> {
141 typedef int param_type
;
142 static void Write(Message
* m
, const param_type
& p
) {
145 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
146 return m
->ReadInt(iter
, r
);
148 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
152 struct ParamTraits
<unsigned int> {
153 typedef unsigned int param_type
;
154 static void Write(Message
* m
, const param_type
& p
) {
157 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
158 return m
->ReadInt(iter
, reinterpret_cast<int*>(r
));
160 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
164 struct ParamTraits
<long> {
165 typedef long param_type
;
166 static void Write(Message
* m
, const param_type
& p
) {
167 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
169 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
170 return m
->ReadLong(iter
, r
);
172 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
176 struct ParamTraits
<unsigned long> {
177 typedef unsigned long param_type
;
178 static void Write(Message
* m
, const param_type
& p
) {
179 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
181 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
182 return m
->ReadLong(iter
, reinterpret_cast<long*>(r
));
184 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
188 struct ParamTraits
<long long> {
189 typedef long long param_type
;
190 static void Write(Message
* m
, const param_type
& p
) {
191 m
->WriteInt64(static_cast<int64
>(p
));
193 static bool Read(const Message
* m
, PickleIterator
* iter
,
195 return m
->ReadInt64(iter
, reinterpret_cast<int64
*>(r
));
197 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
201 struct ParamTraits
<unsigned long long> {
202 typedef unsigned long long param_type
;
203 static void Write(Message
* m
, const param_type
& p
) {
206 static bool Read(const Message
* m
, PickleIterator
* iter
,
208 return m
->ReadInt64(iter
, reinterpret_cast<int64
*>(r
));
210 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
213 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
214 // should be sure to check the sanity of these values after receiving them over
217 struct IPC_EXPORT ParamTraits
<float> {
218 typedef float param_type
;
219 static void Write(Message
* m
, const param_type
& p
) {
222 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
223 return m
->ReadFloat(iter
, r
);
225 static void Log(const param_type
& p
, std::string
* l
);
229 struct IPC_EXPORT ParamTraits
<double> {
230 typedef double param_type
;
231 static void Write(Message
* m
, const param_type
& p
);
232 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
233 static void Log(const param_type
& p
, std::string
* l
);
236 // STL ParamTraits -------------------------------------------------------------
239 struct ParamTraits
<std::string
> {
240 typedef std::string param_type
;
241 static void Write(Message
* m
, const param_type
& p
) {
244 static bool Read(const Message
* m
, PickleIterator
* iter
,
246 return m
->ReadString(iter
, r
);
248 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
252 struct ParamTraits
<std::wstring
> {
253 typedef std::wstring param_type
;
254 static void Write(Message
* m
, const param_type
& p
) {
257 static bool Read(const Message
* m
, PickleIterator
* iter
,
259 return m
->ReadWString(iter
, r
);
261 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
264 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
266 #if !defined(WCHAR_T_IS_UTF16)
268 struct ParamTraits
<base::string16
> {
269 typedef base::string16 param_type
;
270 static void Write(Message
* m
, const param_type
& p
) {
273 static bool Read(const Message
* m
, PickleIterator
* iter
,
275 return m
->ReadString16(iter
, r
);
277 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
282 struct IPC_EXPORT ParamTraits
<std::vector
<char> > {
283 typedef std::vector
<char> param_type
;
284 static void Write(Message
* m
, const param_type
& p
);
285 static bool Read(const Message
*, PickleIterator
* iter
, param_type
* r
);
286 static void Log(const param_type
& p
, std::string
* l
);
290 struct IPC_EXPORT ParamTraits
<std::vector
<unsigned char> > {
291 typedef std::vector
<unsigned char> param_type
;
292 static void Write(Message
* m
, const param_type
& p
);
293 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
294 static void Log(const param_type
& p
, std::string
* l
);
298 struct IPC_EXPORT ParamTraits
<std::vector
<bool> > {
299 typedef std::vector
<bool> param_type
;
300 static void Write(Message
* m
, const param_type
& p
);
301 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
302 static void Log(const param_type
& p
, std::string
* l
);
306 struct ParamTraits
<std::vector
<P
> > {
307 typedef std::vector
<P
> param_type
;
308 static void Write(Message
* m
, const param_type
& p
) {
309 WriteParam(m
, static_cast<int>(p
.size()));
310 for (size_t i
= 0; i
< p
.size(); i
++)
313 static bool Read(const Message
* m
, PickleIterator
* iter
,
316 // ReadLength() checks for < 0 itself.
317 if (!m
->ReadLength(iter
, &size
))
319 // Resizing beforehand is not safe, see BUG 1006367 for details.
320 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
323 for (int i
= 0; i
< size
; i
++) {
324 if (!ReadParam(m
, iter
, &(*r
)[i
]))
329 static void Log(const param_type
& p
, std::string
* l
) {
330 for (size_t i
= 0; i
< p
.size(); ++i
) {
339 struct ParamTraits
<std::set
<P
> > {
340 typedef std::set
<P
> param_type
;
341 static void Write(Message
* m
, const param_type
& p
) {
342 WriteParam(m
, static_cast<int>(p
.size()));
343 typename
param_type::const_iterator iter
;
344 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
345 WriteParam(m
, *iter
);
347 static bool Read(const Message
* m
, PickleIterator
* iter
,
350 if (!m
->ReadLength(iter
, &size
))
352 for (int i
= 0; i
< size
; ++i
) {
354 if (!ReadParam(m
, iter
, &item
))
360 static void Log(const param_type
& p
, std::string
* l
) {
361 l
->append("<std::set>");
365 template <class K
, class V
>
366 struct ParamTraits
<std::map
<K
, V
> > {
367 typedef std::map
<K
, V
> param_type
;
368 static void Write(Message
* m
, const param_type
& p
) {
369 WriteParam(m
, static_cast<int>(p
.size()));
370 typename
param_type::const_iterator iter
;
371 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
372 WriteParam(m
, iter
->first
);
373 WriteParam(m
, iter
->second
);
376 static bool Read(const Message
* m
, PickleIterator
* iter
,
379 if (!ReadParam(m
, iter
, &size
) || size
< 0)
381 for (int i
= 0; i
< size
; ++i
) {
383 if (!ReadParam(m
, iter
, &k
))
386 if (!ReadParam(m
, iter
, &value
))
391 static void Log(const param_type
& p
, std::string
* l
) {
392 l
->append("<std::map>");
396 template <class A
, class B
>
397 struct ParamTraits
<std::pair
<A
, B
> > {
398 typedef std::pair
<A
, B
> param_type
;
399 static void Write(Message
* m
, const param_type
& p
) {
400 WriteParam(m
, p
.first
);
401 WriteParam(m
, p
.second
);
403 static bool Read(const Message
* m
, PickleIterator
* iter
,
405 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
407 static void Log(const param_type
& p
, std::string
* l
) {
409 LogParam(p
.first
, l
);
411 LogParam(p
.second
, l
);
416 // Base ParamTraits ------------------------------------------------------------
419 struct IPC_EXPORT ParamTraits
<base::DictionaryValue
> {
420 typedef base::DictionaryValue param_type
;
421 static void Write(Message
* m
, const param_type
& p
);
422 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
423 static void Log(const param_type
& p
, std::string
* l
);
426 #if defined(OS_POSIX)
427 // FileDescriptors may be serialised over IPC channels on POSIX. On the
428 // receiving side, the FileDescriptor is a valid duplicate of the file
429 // descriptor which was transmitted: *it is not just a copy of the integer like
430 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
431 // this case, the receiving end will see a value of -1. *Zero is a valid file
434 // The received file descriptor will have the |auto_close| flag set to true. The
435 // code which handles the message is responsible for taking ownership of it.
436 // File descriptors are OS resources and must be closed when no longer needed.
438 // When sending a file descriptor, the file descriptor must be valid at the time
439 // of transmission. Since transmission is not synchronous, one should consider
440 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
441 // flag, which causes the file descriptor to be closed after writing.
443 struct IPC_EXPORT ParamTraits
<base::FileDescriptor
> {
444 typedef base::FileDescriptor param_type
;
445 static void Write(Message
* m
, const param_type
& p
);
446 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
447 static void Log(const param_type
& p
, std::string
* l
);
449 #endif // defined(OS_POSIX)
452 struct IPC_EXPORT ParamTraits
<base::FilePath
> {
453 typedef base::FilePath param_type
;
454 static void Write(Message
* m
, const param_type
& p
);
455 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
456 static void Log(const param_type
& p
, std::string
* l
);
460 struct IPC_EXPORT ParamTraits
<base::ListValue
> {
461 typedef base::ListValue param_type
;
462 static void Write(Message
* m
, const param_type
& p
);
463 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
464 static void Log(const param_type
& p
, std::string
* l
);
468 struct IPC_EXPORT ParamTraits
<base::NullableString16
> {
469 typedef base::NullableString16 param_type
;
470 static void Write(Message
* m
, const param_type
& p
);
471 static bool Read(const Message
* m
, PickleIterator
* iter
,
473 static void Log(const param_type
& p
, std::string
* l
);
477 struct IPC_EXPORT ParamTraits
<base::PlatformFileInfo
> {
478 typedef base::PlatformFileInfo param_type
;
479 static void Write(Message
* m
, const param_type
& p
);
480 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
481 static void Log(const param_type
& p
, std::string
* l
);
485 struct SimilarTypeTraits
<base::PlatformFileError
> {
491 struct SimilarTypeTraits
<HWND
> {
494 #endif // defined(OS_WIN)
497 struct IPC_EXPORT ParamTraits
<base::Time
> {
498 typedef base::Time param_type
;
499 static void Write(Message
* m
, const param_type
& p
);
500 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
501 static void Log(const param_type
& p
, std::string
* l
);
505 struct IPC_EXPORT ParamTraits
<base::TimeDelta
> {
506 typedef base::TimeDelta param_type
;
507 static void Write(Message
* m
, const param_type
& p
);
508 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
509 static void Log(const param_type
& p
, std::string
* l
);
513 struct IPC_EXPORT ParamTraits
<base::TimeTicks
> {
514 typedef base::TimeTicks param_type
;
515 static void Write(Message
* m
, const param_type
& p
);
516 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
517 static void Log(const param_type
& p
, std::string
* l
);
521 struct ParamTraits
<Tuple0
> {
522 typedef Tuple0 param_type
;
523 static void Write(Message
* m
, const param_type
& p
) {
525 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
528 static void Log(const param_type
& p
, std::string
* l
) {
533 struct ParamTraits
< Tuple1
<A
> > {
534 typedef Tuple1
<A
> param_type
;
535 static void Write(Message
* m
, const param_type
& p
) {
538 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
539 return ReadParam(m
, iter
, &r
->a
);
541 static void Log(const param_type
& p
, std::string
* l
) {
546 template <class A
, class B
>
547 struct ParamTraits
< Tuple2
<A
, B
> > {
548 typedef Tuple2
<A
, B
> param_type
;
549 static void Write(Message
* m
, const param_type
& p
) {
553 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
554 return (ReadParam(m
, iter
, &r
->a
) &&
555 ReadParam(m
, iter
, &r
->b
));
557 static void Log(const param_type
& p
, std::string
* l
) {
564 template <class A
, class B
, class C
>
565 struct ParamTraits
< Tuple3
<A
, B
, C
> > {
566 typedef Tuple3
<A
, B
, C
> param_type
;
567 static void Write(Message
* m
, const param_type
& p
) {
572 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
573 return (ReadParam(m
, iter
, &r
->a
) &&
574 ReadParam(m
, iter
, &r
->b
) &&
575 ReadParam(m
, iter
, &r
->c
));
577 static void Log(const param_type
& p
, std::string
* l
) {
586 template <class A
, class B
, class C
, class D
>
587 struct ParamTraits
< Tuple4
<A
, B
, C
, D
> > {
588 typedef Tuple4
<A
, B
, C
, D
> param_type
;
589 static void Write(Message
* m
, const param_type
& p
) {
595 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
596 return (ReadParam(m
, iter
, &r
->a
) &&
597 ReadParam(m
, iter
, &r
->b
) &&
598 ReadParam(m
, iter
, &r
->c
) &&
599 ReadParam(m
, iter
, &r
->d
));
601 static void Log(const param_type
& p
, std::string
* l
) {
612 template <class A
, class B
, class C
, class D
, class E
>
613 struct ParamTraits
< Tuple5
<A
, B
, C
, D
, E
> > {
614 typedef Tuple5
<A
, B
, C
, D
, E
> param_type
;
615 static void Write(Message
* m
, const param_type
& p
) {
622 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
623 return (ReadParam(m
, iter
, &r
->a
) &&
624 ReadParam(m
, iter
, &r
->b
) &&
625 ReadParam(m
, iter
, &r
->c
) &&
626 ReadParam(m
, iter
, &r
->d
) &&
627 ReadParam(m
, iter
, &r
->e
));
629 static void Log(const param_type
& p
, std::string
* l
) {
643 struct ParamTraits
<ScopedVector
<P
> > {
644 typedef ScopedVector
<P
> param_type
;
645 static void Write(Message
* m
, const param_type
& p
) {
646 WriteParam(m
, static_cast<int>(p
.size()));
647 for (size_t i
= 0; i
< p
.size(); i
++)
648 WriteParam(m
, *p
[i
]);
650 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
652 if (!m
->ReadLength(iter
, &size
))
654 if (INT_MAX
/sizeof(P
) <= static_cast<size_t>(size
))
657 for (int i
= 0; i
< size
; i
++) {
659 if (!ReadParam(m
, iter
, (*r
)[i
]))
664 static void Log(const param_type
& p
, std::string
* l
) {
665 for (size_t i
= 0; i
< p
.size(); ++i
) {
673 // IPC types ParamTraits -------------------------------------------------------
675 // A ChannelHandle is basically a platform-inspecific wrapper around the
676 // fact that IPC endpoints are handled specially on POSIX. See above comments
677 // on FileDescriptor for more background.
679 struct IPC_EXPORT ParamTraits
<IPC::ChannelHandle
> {
680 typedef ChannelHandle param_type
;
681 static void Write(Message
* m
, const param_type
& p
);
682 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
683 static void Log(const param_type
& p
, std::string
* l
);
687 struct IPC_EXPORT ParamTraits
<LogData
> {
688 typedef LogData param_type
;
689 static void Write(Message
* m
, const param_type
& p
);
690 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
691 static void Log(const param_type
& p
, std::string
* l
);
695 struct IPC_EXPORT ParamTraits
<Message
> {
696 static void Write(Message
* m
, const Message
& p
);
697 static bool Read(const Message
* m
, PickleIterator
* iter
, Message
* r
);
698 static void Log(const Message
& p
, std::string
* l
);
701 // Windows ParamTraits ---------------------------------------------------------
705 struct IPC_EXPORT ParamTraits
<HANDLE
> {
706 typedef HANDLE param_type
;
707 static void Write(Message
* m
, const param_type
& p
);
708 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
709 static void Log(const param_type
& p
, std::string
* l
);
713 struct IPC_EXPORT ParamTraits
<LOGFONT
> {
714 typedef LOGFONT param_type
;
715 static void Write(Message
* m
, const param_type
& p
);
716 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
717 static void Log(const param_type
& p
, std::string
* l
);
721 struct IPC_EXPORT ParamTraits
<MSG
> {
722 typedef MSG param_type
;
723 static void Write(Message
* m
, const param_type
& p
);
724 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
725 static void Log(const param_type
& p
, std::string
* l
);
727 #endif // defined(OS_WIN)
729 //-----------------------------------------------------------------------------
730 // Generic message subclasses
732 // Used for asynchronous messages.
733 template <class ParamType
>
734 class MessageSchema
{
736 typedef ParamType Param
;
737 typedef typename TupleTypes
<ParamType
>::ParamTuple RefParam
;
739 static void Write(Message
* msg
, const RefParam
& p
) IPC_MSG_NOINLINE
;
740 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
743 // defined in ipc_logging.cc
744 IPC_EXPORT
void GenerateLogData(const std::string
& channel
,
745 const Message
& message
,
746 LogData
* data
, bool get_params
);
749 #if defined(IPC_MESSAGE_LOG_ENABLED)
750 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
751 const std::string
& output_params
= msg
->output_params();
752 if (!l
->empty() && !output_params
.empty())
755 l
->append(output_params
);
758 template <class ReplyParamType
>
759 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
760 const Message
* msg
) {
761 if (msg
->received_time() != 0) {
762 std::string output_params
;
763 LogParam(reply_params
, &output_params
);
764 msg
->set_output_params(output_params
);
768 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
769 if (msg
->sent_time()) {
770 // Don't log the sync message after dispatch, as we don't have the
771 // output parameters at that point. Instead, save its data and log it
772 // with the outgoing reply message when it's sent.
773 LogData
* data
= new LogData
;
774 GenerateLogData("", *msg
, data
, true);
776 reply
->set_sync_log_data(data
);
780 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
782 template <class ReplyParamType
>
783 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
784 const Message
* msg
) {}
786 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
789 // This class assumes that its template argument is a RefTuple (a Tuple with
790 // reference elements). This would go into ipc_message_utils_impl.h, but it is
791 // also used by chrome_frame.
792 template <class RefTuple
>
793 class ParamDeserializer
: public MessageReplyDeserializer
{
795 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
797 bool SerializeOutputParameters(const IPC::Message
& msg
, PickleIterator iter
) {
798 return ReadParam(&msg
, &iter
, &out_
);
804 // Used for synchronous messages.
805 template <class SendParamType
, class ReplyParamType
>
806 class SyncMessageSchema
{
808 typedef SendParamType SendParam
;
809 typedef typename TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
810 typedef ReplyParamType ReplyParam
;
812 static void Write(Message
* msg
, const RefSendParam
& send
) IPC_MSG_NOINLINE
;
813 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
814 static bool ReadReplyParam(
816 typename TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
818 template<class T
, class S
, class Method
>
819 static bool DispatchWithSendParams(bool ok
, const SendParam
& send_params
,
820 const Message
* msg
, T
* obj
, S
* sender
,
822 Message
* reply
= SyncMessage::GenerateReply(msg
);
824 typename TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
825 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
826 WriteParam(reply
, reply_params
);
827 LogReplyParamsToMessage(reply_params
, msg
);
829 NOTREACHED() << "Error deserializing message " << msg
->type();
830 reply
->set_reply_error();
836 template<class T
, class Method
>
837 static bool DispatchDelayReplyWithSendParams(bool ok
,
838 const SendParam
& send_params
,
839 const Message
* msg
, T
* obj
,
841 Message
* reply
= SyncMessage::GenerateReply(msg
);
843 Tuple1
<Message
&> t
= MakeRefTuple(*reply
);
844 ConnectMessageAndReply(msg
, reply
);
845 DispatchToMethod(obj
, func
, send_params
, &t
);
847 NOTREACHED() << "Error deserializing message " << msg
->type();
848 reply
->set_reply_error();
854 template<typename TA
>
855 static void WriteReplyParams(Message
* reply
, TA a
) {
857 WriteParam(reply
, p
);
860 template<typename TA
, typename TB
>
861 static void WriteReplyParams(Message
* reply
, TA a
, TB b
) {
863 WriteParam(reply
, p
);
866 template<typename TA
, typename TB
, typename TC
>
867 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
) {
868 ReplyParam
p(a
, b
, c
);
869 WriteParam(reply
, p
);
872 template<typename TA
, typename TB
, typename TC
, typename TD
>
873 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
, TD d
) {
874 ReplyParam
p(a
, b
, c
, d
);
875 WriteParam(reply
, p
);
878 template<typename TA
, typename TB
, typename TC
, typename TD
, typename TE
>
879 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
, TD d
, TE e
) {
880 ReplyParam
p(a
, b
, c
, d
, e
);
881 WriteParam(reply
, p
);
887 #endif // IPC_IPC_MESSAGE_UTILS_H_