1 // Copyright (c) 2011 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_
15 #include "base/format_macros.h"
16 #include "base/string16.h"
17 #include "base/stringprintf.h"
18 #include "base/string_util.h"
19 #include "base/tuple.h"
20 #include "ipc/ipc_param_traits.h"
21 #include "ipc/ipc_sync_message.h"
23 #if defined(COMPILER_GCC)
24 // GCC "helpfully" tries to inline template methods in release mode. Except we
25 // want the majority of the template junk being expanded once in the
26 // implementation file (and only provide the definitions in
27 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
28 // at every call site. Special note: GCC happily accepts the attribute before
29 // the method declaration, but only acts on it if it is after.
30 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
31 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
32 // the introduced noclone attribute, which will create specialized versions of
33 // functions/methods when certain types are constant.
34 // www.gnu.org/software/gcc/gcc-4.5/changes.html
35 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
37 #define IPC_MSG_NOINLINE __attribute__((noinline));
39 #elif defined(COMPILER_MSVC)
40 // MSVC++ doesn't do this.
41 #define IPC_MSG_NOINLINE
43 #error "Please add the noinline property for your new compiler here."
46 // Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
47 // base. Messages have unique IDs across channels in order for the IPC logging
48 // code to figure out the message class from its ID.
49 enum IPCMessageStart
{
50 AutomationMsgStart
= 0,
53 ProfileImportMsgStart
,
62 FirefoxImporterUnittestMsgStart
,
63 FileUtilitiesMsgStart
,
81 DeviceOrientationMsgStart
,
82 DesktopNotificationMsgStart
,
93 TextInputClientMsgStart
,
94 ChromeUtilityMsgStart
,
95 LastIPCMsgStart
// Must come last.
98 class DictionaryValue
;
101 class NullableString16
;
106 struct FileDescriptor
;
111 struct ChannelHandle
;
113 //-----------------------------------------------------------------------------
114 // An iterator class for reading the fields contained within a Message.
116 class MessageIterator
{
118 explicit MessageIterator(const Message
& m
) : msg_(m
), iter_(NULL
) {
120 int NextInt() const {
122 if (!msg_
.ReadInt(&iter_
, &val
))
126 const std::string
NextString() const {
128 if (!msg_
.ReadString(&iter_
, &val
))
132 const std::wstring
NextWString() const {
134 if (!msg_
.ReadWString(&iter_
, &val
))
138 void NextData(const char** data
, int* length
) const {
139 if (!msg_
.ReadData(&iter_
, data
, length
)) {
148 //-----------------------------------------------------------------------------
149 // A dummy struct to place first just to allow leading commas for all
150 // members in the macro-generated constructor initializer lists.
154 //-----------------------------------------------------------------------------
155 // ParamTraits specializations, etc.
158 static inline void WriteParam(Message
* m
, const P
& p
) {
159 typedef typename SimilarTypeTraits
<P
>::Type Type
;
160 ParamTraits
<Type
>::Write(m
, static_cast<const Type
& >(p
));
164 static inline bool WARN_UNUSED_RESULT
ReadParam(const Message
* m
, void** iter
,
166 typedef typename SimilarTypeTraits
<P
>::Type Type
;
167 return ParamTraits
<Type
>::Read(m
, iter
, reinterpret_cast<Type
* >(p
));
171 static inline void LogParam(const P
& p
, std::string
* l
) {
172 typedef typename SimilarTypeTraits
<P
>::Type Type
;
173 ParamTraits
<Type
>::Log(static_cast<const Type
& >(p
), l
);
177 struct ParamTraits
<bool> {
178 typedef bool param_type
;
179 static void Write(Message
* m
, const param_type
& p
) {
182 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
183 return m
->ReadBool(iter
, r
);
185 static void Log(const param_type
& p
, std::string
* l
) {
186 l
->append(p
? "true" : "false");
191 struct ParamTraits
<int> {
192 typedef int param_type
;
193 static void Write(Message
* m
, const param_type
& p
) {
196 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
197 return m
->ReadInt(iter
, r
);
199 static void Log(const param_type
& p
, std::string
* l
);
203 struct ParamTraits
<unsigned int> {
204 typedef unsigned int param_type
;
205 static void Write(Message
* m
, const param_type
& p
) {
208 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
209 return m
->ReadInt(iter
, reinterpret_cast<int*>(r
));
211 static void Log(const param_type
& p
, std::string
* l
);
215 struct ParamTraits
<long> {
216 typedef long param_type
;
217 static void Write(Message
* m
, const param_type
& p
) {
220 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
221 return m
->ReadLong(iter
, r
);
223 static void Log(const param_type
& p
, std::string
* l
);
227 struct ParamTraits
<unsigned long> {
228 typedef unsigned long param_type
;
229 static void Write(Message
* m
, const param_type
& p
) {
232 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
233 return m
->ReadLong(iter
, reinterpret_cast<long*>(r
));
235 static void Log(const param_type
& p
, std::string
* l
);
239 struct ParamTraits
<long long> {
240 typedef long long param_type
;
241 static void Write(Message
* m
, const param_type
& p
) {
242 m
->WriteInt64(static_cast<int64
>(p
));
244 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
245 return m
->ReadInt64(iter
, reinterpret_cast<int64
*>(r
));
247 static void Log(const param_type
& p
, std::string
* l
);
251 struct ParamTraits
<unsigned long long> {
252 typedef unsigned long long param_type
;
253 static void Write(Message
* m
, const param_type
& p
) {
256 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
257 return m
->ReadInt64(iter
, reinterpret_cast<int64
*>(r
));
259 static void Log(const param_type
& p
, std::string
* l
);
263 struct ParamTraits
<unsigned short> {
264 typedef unsigned short param_type
;
265 static void Write(Message
* m
, const param_type
& p
);
266 static bool Read(const Message
* m
, void** iter
, param_type
* r
);
267 static void Log(const param_type
& p
, std::string
* l
);
270 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
271 // should be sure to check the sanity of these values after receiving them over
274 struct ParamTraits
<float> {
275 typedef float param_type
;
276 static void Write(Message
* m
, const param_type
& p
) {
277 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(param_type
));
279 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
282 if (!m
->ReadData(iter
, &data
, &data_size
) ||
283 data_size
!= sizeof(param_type
)) {
287 memcpy(r
, data
, sizeof(param_type
));
290 static void Log(const param_type
& p
, std::string
* l
) {
291 l
->append(StringPrintf("%e", p
));
296 struct ParamTraits
<double> {
297 typedef double param_type
;
298 static void Write(Message
* m
, const param_type
& p
) {
299 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(param_type
));
301 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
304 if (!m
->ReadData(iter
, &data
, &data_size
) ||
305 data_size
!= sizeof(param_type
)) {
309 memcpy(r
, data
, sizeof(param_type
));
312 static void Log(const param_type
& p
, std::string
* l
) {
313 l
->append(StringPrintf("%e", p
));
318 struct ParamTraits
<base::Time
> {
319 typedef base::Time param_type
;
320 static void Write(Message
* m
, const param_type
& p
);
321 static bool Read(const Message
* m
, void** iter
, param_type
* r
);
322 static void Log(const param_type
& p
, std::string
* l
);
326 struct ParamTraits
<base::TimeDelta
> {
327 typedef base::TimeDelta param_type
;
328 static void Write(Message
* m
, const param_type
& p
);
329 static bool Read(const Message
* m
, void** iter
, param_type
* r
);
330 static void Log(const param_type
& p
, std::string
* l
);
335 struct ParamTraits
<LOGFONT
> {
336 typedef LOGFONT param_type
;
337 static void Write(Message
* m
, const param_type
& p
) {
338 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(LOGFONT
));
340 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
343 bool result
= m
->ReadData(iter
, &data
, &data_size
);
344 if (result
&& data_size
== sizeof(LOGFONT
)) {
345 memcpy(r
, data
, sizeof(LOGFONT
));
353 static void Log(const param_type
& p
, std::string
* l
) {
354 l
->append(StringPrintf("<LOGFONT>"));
359 struct ParamTraits
<MSG
> {
360 typedef MSG param_type
;
361 static void Write(Message
* m
, const param_type
& p
) {
362 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(MSG
));
364 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
367 bool result
= m
->ReadData(iter
, &data
, &data_size
);
368 if (result
&& data_size
== sizeof(MSG
)) {
369 memcpy(r
, data
, sizeof(MSG
));
377 static void Log(const param_type
& p
, std::string
* l
) {
381 #endif // defined(OS_WIN)
384 struct ParamTraits
<DictionaryValue
> {
385 typedef DictionaryValue param_type
;
386 static void Write(Message
* m
, const param_type
& p
);
387 static bool Read(const Message
* m
, void** iter
, param_type
* r
);
388 static void Log(const param_type
& p
, std::string
* l
);
392 struct ParamTraits
<ListValue
> {
393 typedef ListValue param_type
;
394 static void Write(Message
* m
, const param_type
& p
);
395 static bool Read(const Message
* m
, void** iter
, param_type
* r
);
396 static void Log(const param_type
& p
, std::string
* l
);
400 struct ParamTraits
<std::string
> {
401 typedef std::string param_type
;
402 static void Write(Message
* m
, const param_type
& p
) {
405 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
406 return m
->ReadString(iter
, r
);
408 static void Log(const param_type
& p
, std::string
* l
) {
413 template<typename CharType
>
414 static void LogBytes(const std::vector
<CharType
>& data
, std::string
* out
) {
416 // Windows has a GUI for logging, which can handle arbitrary binary data.
417 for (size_t i
= 0; i
< data
.size(); ++i
)
418 out
->push_back(data
[i
]);
420 // On POSIX, we log to stdout, which we assume can display ASCII.
421 static const size_t kMaxBytesToLog
= 100;
422 for (size_t i
= 0; i
< std::min(data
.size(), kMaxBytesToLog
); ++i
) {
423 if (isprint(data
[i
]))
424 out
->push_back(data
[i
]);
426 out
->append(StringPrintf("[%02X]", static_cast<unsigned char>(data
[i
])));
428 if (data
.size() > kMaxBytesToLog
) {
430 StringPrintf(" and %u more bytes",
431 static_cast<unsigned>(data
.size() - kMaxBytesToLog
)));
437 struct ParamTraits
<std::vector
<unsigned char> > {
438 typedef std::vector
<unsigned char> param_type
;
439 static void Write(Message
* m
, const param_type
& p
) {
441 m
->WriteData(NULL
, 0);
443 m
->WriteData(reinterpret_cast<const char*>(&p
.front()),
444 static_cast<int>(p
.size()));
447 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
450 if (!m
->ReadData(iter
, &data
, &data_size
) || data_size
< 0)
452 r
->resize(data_size
);
454 memcpy(&r
->front(), data
, data_size
);
457 static void Log(const param_type
& p
, std::string
* l
) {
463 struct ParamTraits
<std::vector
<char> > {
464 typedef std::vector
<char> param_type
;
465 static void Write(Message
* m
, const param_type
& p
) {
467 m
->WriteData(NULL
, 0);
469 m
->WriteData(&p
.front(), static_cast<int>(p
.size()));
472 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
475 if (!m
->ReadData(iter
, &data
, &data_size
) || data_size
< 0)
477 r
->resize(data_size
);
479 memcpy(&r
->front(), data
, data_size
);
482 static void Log(const param_type
& p
, std::string
* l
) {
488 struct ParamTraits
<std::vector
<P
> > {
489 typedef std::vector
<P
> param_type
;
490 static void Write(Message
* m
, const param_type
& p
) {
491 WriteParam(m
, static_cast<int>(p
.size()));
492 for (size_t i
= 0; i
< p
.size(); i
++)
495 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
497 // ReadLength() checks for < 0 itself.
498 if (!m
->ReadLength(iter
, &size
))
500 // Resizing beforehand is not safe, see BUG 1006367 for details.
501 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
504 for (int i
= 0; i
< size
; i
++) {
505 if (!ReadParam(m
, iter
, &(*r
)[i
]))
510 static void Log(const param_type
& p
, std::string
* l
) {
511 for (size_t i
= 0; i
< p
.size(); ++i
) {
520 struct ParamTraits
<std::set
<P
> > {
521 typedef std::set
<P
> param_type
;
522 static void Write(Message
* m
, const param_type
& p
) {
523 WriteParam(m
, static_cast<int>(p
.size()));
524 typename
param_type::const_iterator iter
;
525 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
526 WriteParam(m
, *iter
);
528 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
530 if (!m
->ReadLength(iter
, &size
))
532 for (int i
= 0; i
< size
; ++i
) {
534 if (!ReadParam(m
, iter
, &item
))
540 static void Log(const param_type
& p
, std::string
* l
) {
541 l
->append("<std::set>");
546 template <class K
, class V
>
547 struct ParamTraits
<std::map
<K
, V
> > {
548 typedef std::map
<K
, V
> param_type
;
549 static void Write(Message
* m
, const param_type
& p
) {
550 WriteParam(m
, static_cast<int>(p
.size()));
551 typename
param_type::const_iterator iter
;
552 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
553 WriteParam(m
, iter
->first
);
554 WriteParam(m
, iter
->second
);
557 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
559 if (!ReadParam(m
, iter
, &size
) || size
< 0)
561 for (int i
= 0; i
< size
; ++i
) {
563 if (!ReadParam(m
, iter
, &k
))
566 if (!ReadParam(m
, iter
, &value
))
571 static void Log(const param_type
& p
, std::string
* l
) {
572 l
->append("<std::map>");
578 struct ParamTraits
<std::wstring
> {
579 typedef std::wstring param_type
;
580 static void Write(Message
* m
, const param_type
& p
) {
583 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
584 return m
->ReadWString(iter
, r
);
586 static void Log(const param_type
& p
, std::string
* l
);
589 template <class A
, class B
>
590 struct ParamTraits
<std::pair
<A
, B
> > {
591 typedef std::pair
<A
, B
> param_type
;
592 static void Write(Message
* m
, const param_type
& p
) {
593 WriteParam(m
, p
.first
);
594 WriteParam(m
, p
.second
);
596 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
597 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
599 static void Log(const param_type
& p
, std::string
* l
) {
601 LogParam(p
.first
, l
);
603 LogParam(p
.second
, l
);
609 struct ParamTraits
<NullableString16
> {
610 typedef NullableString16 param_type
;
611 static void Write(Message
* m
, const param_type
& p
);
612 static bool Read(const Message
* m
, void** iter
, param_type
* r
);
613 static void Log(const param_type
& p
, std::string
* l
);
616 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
618 #if !defined(WCHAR_T_IS_UTF16)
620 struct ParamTraits
<string16
> {
621 typedef string16 param_type
;
622 static void Write(Message
* m
, const param_type
& p
) {
625 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
626 return m
->ReadString16(iter
, r
);
628 static void Log(const param_type
& p
, std::string
* l
);
632 // and, a few more useful types...
635 struct ParamTraits
<HANDLE
> {
636 typedef HANDLE param_type
;
637 static void Write(Message
* m
, const param_type
& p
) {
638 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
640 m
->WriteUInt32(reinterpret_cast<uint32
>(p
));
642 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
643 DCHECK_EQ(sizeof(param_type
), sizeof(uint32
));
644 return m
->ReadUInt32(iter
, reinterpret_cast<uint32
*>(r
));
646 static void Log(const param_type
& p
, std::string
* l
) {
647 l
->append(StringPrintf("0x%X", p
));
652 struct ParamTraits
<HCURSOR
> {
653 typedef HCURSOR param_type
;
654 static void Write(Message
* m
, const param_type
& p
) {
655 m
->WriteUInt32(reinterpret_cast<uint32
>(p
));
657 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
658 DCHECK_EQ(sizeof(param_type
), sizeof(uint32
));
659 return m
->ReadUInt32(iter
, reinterpret_cast<uint32
*>(r
));
661 static void Log(const param_type
& p
, std::string
* l
) {
662 l
->append(StringPrintf("0x%X", p
));
667 struct ParamTraits
<HACCEL
> {
668 typedef HACCEL param_type
;
669 static void Write(Message
* m
, const param_type
& p
) {
670 m
->WriteUInt32(reinterpret_cast<uint32
>(p
));
672 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
673 DCHECK_EQ(sizeof(param_type
), sizeof(uint32
));
674 return m
->ReadUInt32(iter
, reinterpret_cast<uint32
*>(r
));
679 struct ParamTraits
<POINT
> {
680 typedef POINT param_type
;
681 static void Write(Message
* m
, const param_type
& p
) {
685 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
687 if (!m
->ReadInt(iter
, &x
) || !m
->ReadInt(iter
, &y
))
693 static void Log(const param_type
& p
, std::string
* l
) {
694 l
->append(StringPrintf("(%d, %d)", p
.x
, p
.y
));
697 #endif // defined(OS_WIN)
700 struct ParamTraits
<FilePath
> {
701 typedef FilePath param_type
;
702 static void Write(Message
* m
, const param_type
& p
);
703 static bool Read(const Message
* m
, void** iter
, param_type
* r
);
704 static void Log(const param_type
& p
, std::string
* l
);
707 #if defined(OS_POSIX)
708 // FileDescriptors may be serialised over IPC channels on POSIX. On the
709 // receiving side, the FileDescriptor is a valid duplicate of the file
710 // descriptor which was transmitted: *it is not just a copy of the integer like
711 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
712 // this case, the receiving end will see a value of -1. *Zero is a valid file
715 // The received file descriptor will have the |auto_close| flag set to true. The
716 // code which handles the message is responsible for taking ownership of it.
717 // File descriptors are OS resources and must be closed when no longer needed.
719 // When sending a file descriptor, the file descriptor must be valid at the time
720 // of transmission. Since transmission is not synchronous, one should consider
721 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
722 // flag, which causes the file descriptor to be closed after writing.
724 struct ParamTraits
<base::FileDescriptor
> {
725 typedef base::FileDescriptor param_type
;
726 static void Write(Message
* m
, const param_type
& p
);
727 static bool Read(const Message
* m
, void** iter
, param_type
* r
);
728 static void Log(const param_type
& p
, std::string
* l
);
730 #endif // defined(OS_POSIX)
732 // A ChannelHandle is basically a platform-inspecific wrapper around the
733 // fact that IPC endpoints are handled specially on POSIX. See above comments
734 // on FileDescriptor for more background.
736 struct ParamTraits
<IPC::ChannelHandle
> {
737 typedef ChannelHandle param_type
;
738 static void Write(Message
* m
, const param_type
& p
);
739 static bool Read(const Message
* m
, void** iter
, param_type
* r
);
740 static void Log(const param_type
& p
, std::string
* l
);
745 struct ParamTraits
<XFORM
> {
746 typedef XFORM param_type
;
747 static void Write(Message
* m
, const param_type
& p
) {
748 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(XFORM
));
750 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
753 bool result
= m
->ReadData(iter
, &data
, &data_size
);
754 if (result
&& data_size
== sizeof(XFORM
)) {
755 memcpy(r
, data
, sizeof(XFORM
));
763 static void Log(const param_type
& p
, std::string
* l
) {
764 l
->append("<XFORM>");
767 #endif // defined(OS_WIN)
775 uint32 type
; // "User-defined" message type, from ipc_message.h.
777 int64 sent
; // Time that the message was sent (i.e. at Send()).
778 int64 receive
; // Time before it was dispatched (i.e. before calling
779 // OnMessageReceived).
780 int64 dispatch
; // Time after it was dispatched (i.e. after calling
781 // OnMessageReceived).
782 std::string message_name
;
787 struct ParamTraits
<LogData
> {
788 typedef LogData param_type
;
789 static void Write(Message
* m
, const param_type
& p
);
790 static bool Read(const Message
* m
, void** iter
, param_type
* r
);
791 static void Log(const param_type
& p
, std::string
* l
) {
792 // Doesn't make sense to implement this!
797 struct ParamTraits
<Message
> {
798 static void Write(Message
* m
, const Message
& p
) {
799 DCHECK(p
.size() <= INT_MAX
);
800 int message_size
= static_cast<int>(p
.size());
801 m
->WriteInt(message_size
);
802 m
->WriteData(reinterpret_cast<const char*>(p
.data()), message_size
);
804 static bool Read(const Message
* m
, void** iter
, Message
* r
) {
806 if (!m
->ReadInt(iter
, &size
))
809 if (!m
->ReadData(iter
, &data
, &size
))
811 *r
= Message(data
, size
);
814 static void Log(const Message
& p
, std::string
* l
) {
815 l
->append("<IPC::Message>");
820 struct ParamTraits
<Tuple0
> {
821 typedef Tuple0 param_type
;
822 static void Write(Message
* m
, const param_type
& p
) {
824 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
827 static void Log(const param_type
& p
, std::string
* l
) {
832 struct ParamTraits
< Tuple1
<A
> > {
833 typedef Tuple1
<A
> param_type
;
834 static void Write(Message
* m
, const param_type
& p
) {
837 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
838 return ReadParam(m
, iter
, &r
->a
);
840 static void Log(const param_type
& p
, std::string
* l
) {
845 template <class A
, class B
>
846 struct ParamTraits
< Tuple2
<A
, B
> > {
847 typedef Tuple2
<A
, B
> param_type
;
848 static void Write(Message
* m
, const param_type
& p
) {
852 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
853 return (ReadParam(m
, iter
, &r
->a
) &&
854 ReadParam(m
, iter
, &r
->b
));
856 static void Log(const param_type
& p
, std::string
* l
) {
863 template <class A
, class B
, class C
>
864 struct ParamTraits
< Tuple3
<A
, B
, C
> > {
865 typedef Tuple3
<A
, B
, C
> param_type
;
866 static void Write(Message
* m
, const param_type
& p
) {
871 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
872 return (ReadParam(m
, iter
, &r
->a
) &&
873 ReadParam(m
, iter
, &r
->b
) &&
874 ReadParam(m
, iter
, &r
->c
));
876 static void Log(const param_type
& p
, std::string
* l
) {
885 template <class A
, class B
, class C
, class D
>
886 struct ParamTraits
< Tuple4
<A
, B
, C
, D
> > {
887 typedef Tuple4
<A
, B
, C
, D
> param_type
;
888 static void Write(Message
* m
, const param_type
& p
) {
894 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
895 return (ReadParam(m
, iter
, &r
->a
) &&
896 ReadParam(m
, iter
, &r
->b
) &&
897 ReadParam(m
, iter
, &r
->c
) &&
898 ReadParam(m
, iter
, &r
->d
));
900 static void Log(const param_type
& p
, std::string
* l
) {
911 template <class A
, class B
, class C
, class D
, class E
>
912 struct ParamTraits
< Tuple5
<A
, B
, C
, D
, E
> > {
913 typedef Tuple5
<A
, B
, C
, D
, E
> param_type
;
914 static void Write(Message
* m
, const param_type
& p
) {
921 static bool Read(const Message
* m
, void** iter
, param_type
* r
) {
922 return (ReadParam(m
, iter
, &r
->a
) &&
923 ReadParam(m
, iter
, &r
->b
) &&
924 ReadParam(m
, iter
, &r
->c
) &&
925 ReadParam(m
, iter
, &r
->d
) &&
926 ReadParam(m
, iter
, &r
->e
));
928 static void Log(const param_type
& p
, std::string
* l
) {
941 //-----------------------------------------------------------------------------
942 // Generic message subclasses
944 // Used for asynchronous messages.
945 template <class ParamType
>
946 class MessageWithTuple
: public Message
{
948 typedef ParamType Param
;
949 typedef typename TupleTypes
<ParamType
>::ParamTuple RefParam
;
951 // The constructor and the Read() method's templated implementations are in
952 // ipc_message_utils_impl.h. The subclass constructor and Log() methods call
953 // the templated versions of these and make sure there are instantiations in
954 // those translation units.
955 MessageWithTuple(int32 routing_id
, uint32 type
, const RefParam
& p
);
957 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
959 // Generic dispatcher. Should cover most cases.
960 template<class T
, class S
, class Method
>
961 static bool Dispatch(const Message
* msg
, T
* obj
, S
* sender
, Method func
) {
964 DispatchToMethod(obj
, func
, p
);
970 // The following dispatchers exist for the case where the callback function
971 // needs the message as well. They assume that "Param" is a type of Tuple
972 // (except the one arg case, as there is no Tuple1).
973 template<class T
, class S
, typename TA
>
974 static bool Dispatch(const Message
* msg
, T
* obj
, S
* sender
,
975 void (T::*func
)(const Message
&, TA
)) {
978 (obj
->*func
)(*msg
, p
.a
);
984 template<class T
, class S
, typename TA
, typename TB
>
985 static bool Dispatch(const Message
* msg
, T
* obj
, S
* sender
,
986 void (T::*func
)(const Message
&, TA
, TB
)) {
989 (obj
->*func
)(*msg
, p
.a
, p
.b
);
995 template<class T
, class S
, typename TA
, typename TB
, typename TC
>
996 static bool Dispatch(const Message
* msg
, T
* obj
, S
* sender
,
997 void (T::*func
)(const Message
&, TA
, TB
, TC
)) {
1000 (obj
->*func
)(*msg
, p
.a
, p
.b
, p
.c
);
1006 template<class T
, class S
, typename TA
, typename TB
, typename TC
, typename TD
>
1007 static bool Dispatch(const Message
* msg
, T
* obj
, S
* sender
,
1008 void (T::*func
)(const Message
&, TA
, TB
, TC
, TD
)) {
1010 if (Read(msg
, &p
)) {
1011 (obj
->*func
)(*msg
, p
.a
, p
.b
, p
.c
, p
.d
);
1017 template<class T
, class S
, typename TA
, typename TB
, typename TC
, typename TD
,
1019 static bool Dispatch(const Message
* msg
, T
* obj
, S
* sender
,
1020 void (T::*func
)(const Message
&, TA
, TB
, TC
, TD
, TE
)) {
1022 if (Read(msg
, &p
)) {
1023 (obj
->*func
)(*msg
, p
.a
, p
.b
, p
.c
, p
.d
, p
.e
);
1029 // Functions used to do manual unpacking. Only used by the automation code,
1030 // these should go away once that code uses SyncChannel.
1031 template<typename TA
, typename TB
>
1032 static bool Read(const IPC::Message
* msg
, TA
* a
, TB
* b
) {
1034 if (!Read(msg
, ¶ms
))
1041 template<typename TA
, typename TB
, typename TC
>
1042 static bool Read(const IPC::Message
* msg
, TA
* a
, TB
* b
, TC
* c
) {
1044 if (!Read(msg
, ¶ms
))
1052 template<typename TA
, typename TB
, typename TC
, typename TD
>
1053 static bool Read(const IPC::Message
* msg
, TA
* a
, TB
* b
, TC
* c
, TD
* d
) {
1055 if (!Read(msg
, ¶ms
))
1064 template<typename TA
, typename TB
, typename TC
, typename TD
, typename TE
>
1065 static bool Read(const IPC::Message
* msg
, TA
* a
, TB
* b
, TC
* c
, TD
* d
, TE
* e
) {
1067 if (!Read(msg
, ¶ms
))
1078 // defined in ipc_logging.cc
1079 void GenerateLogData(const std::string
& channel
, const Message
& message
,
1083 #if defined(IPC_MESSAGE_LOG_ENABLED)
1084 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
1085 const std::string
& output_params
= msg
->output_params();
1086 if (!l
->empty() && !output_params
.empty())
1089 l
->append(output_params
);
1092 template <class ReplyParamType
>
1093 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
1094 const Message
* msg
) {
1095 if (msg
->received_time() != 0) {
1096 std::string output_params
;
1097 LogParam(reply_params
, &output_params
);
1098 msg
->set_output_params(output_params
);
1102 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
1103 if (msg
->sent_time()) {
1104 // Don't log the sync message after dispatch, as we don't have the
1105 // output parameters at that point. Instead, save its data and log it
1106 // with the outgoing reply message when it's sent.
1107 LogData
* data
= new LogData
;
1108 GenerateLogData("", *msg
, data
);
1109 msg
->set_dont_log();
1110 reply
->set_sync_log_data(data
);
1114 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
1116 template <class ReplyParamType
>
1117 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
1118 const Message
* msg
) {}
1120 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
1123 // This class assumes that its template argument is a RefTuple (a Tuple with
1124 // reference elements). This would go into ipc_message_utils_impl.h, but it is
1125 // also used by chrome_frame.
1126 template <class RefTuple
>
1127 class ParamDeserializer
: public MessageReplyDeserializer
{
1129 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
1131 bool SerializeOutputParameters(const IPC::Message
& msg
, void* iter
) {
1132 return ReadParam(&msg
, &iter
, &out_
);
1138 // Used for synchronous messages.
1139 template <class SendParamType
, class ReplyParamType
>
1140 class MessageWithReply
: public SyncMessage
{
1142 typedef SendParamType SendParam
;
1143 typedef typename TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
1144 typedef ReplyParamType ReplyParam
;
1146 MessageWithReply(int32 routing_id
, uint32 type
,
1147 const RefSendParam
& send
, const ReplyParam
& reply
);
1148 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
1149 static bool ReadReplyParam(
1151 typename TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
1153 template<class T
, class S
, class Method
>
1154 static bool Dispatch(const Message
* msg
, T
* obj
, S
* sender
, Method func
) {
1155 SendParam send_params
;
1156 Message
* reply
= GenerateReply(msg
);
1158 if (ReadSendParam(msg
, &send_params
)) {
1159 typename TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
1160 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
1161 WriteParam(reply
, reply_params
);
1163 LogReplyParamsToMessage(reply_params
, msg
);
1165 NOTREACHED() << "Error deserializing message " << msg
->type();
1166 reply
->set_reply_error();
1170 sender
->Send(reply
);
1174 template<class T
, class Method
>
1175 static bool DispatchDelayReply(const Message
* msg
, T
* obj
, Method func
) {
1176 SendParam send_params
;
1177 Message
* reply
= GenerateReply(msg
);
1179 if (ReadSendParam(msg
, &send_params
)) {
1180 Tuple1
<Message
&> t
= MakeRefTuple(*reply
);
1181 ConnectMessageAndReply(msg
, reply
);
1182 DispatchToMethod(obj
, func
, send_params
, &t
);
1185 NOTREACHED() << "Error deserializing message " << msg
->type();
1186 reply
->set_reply_error();
1193 template<typename TA
>
1194 static void WriteReplyParams(Message
* reply
, TA a
) {
1196 WriteParam(reply
, p
);
1199 template<typename TA
, typename TB
>
1200 static void WriteReplyParams(Message
* reply
, TA a
, TB b
) {
1202 WriteParam(reply
, p
);
1205 template<typename TA
, typename TB
, typename TC
>
1206 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
) {
1207 ReplyParam
p(a
, b
, c
);
1208 WriteParam(reply
, p
);
1211 template<typename TA
, typename TB
, typename TC
, typename TD
>
1212 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
, TD d
) {
1213 ReplyParam
p(a
, b
, c
, d
);
1214 WriteParam(reply
, p
);
1217 template<typename TA
, typename TB
, typename TC
, typename TD
, typename TE
>
1218 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
, TD d
, TE e
) {
1219 ReplyParam
p(a
, b
, c
, d
, e
);
1220 WriteParam(reply
, p
);
1224 //-----------------------------------------------------------------------------
1228 #endif // IPC_IPC_MESSAGE_UTILS_H_