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_
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
,
69 SpeechRecognitionMsgStart
,
81 DeviceOrientationMsgStart
,
82 DesktopNotificationMsgStart
,
93 TextInputClientMsgStart
,
94 ChromeUtilityMsgStart
,
96 ChromeBenchmarkingMsgStart
,
101 AccessibilityMsgStart
,
104 LastIPCMsgStart
// Must come last.
108 class NullableString16
;
111 class DictionaryValue
;
116 struct FileDescriptor
;
121 struct ChannelHandle
;
123 //-----------------------------------------------------------------------------
124 // An iterator class for reading the fields contained within a Message.
126 class MessageIterator
{
128 explicit MessageIterator(const Message
& m
) : iter_(m
) {
130 int NextInt() const {
132 if (!iter_
.ReadInt(&val
))
136 const std::string
NextString() const {
138 if (!iter_
.ReadString(&val
))
142 const std::wstring
NextWString() const {
144 if (!iter_
.ReadWString(&val
))
148 void NextData(const char** data
, int* length
) const {
149 if (!iter_
.ReadData(data
, length
)) {
154 mutable PickleIterator iter_
;
157 //-----------------------------------------------------------------------------
158 // A dummy struct to place first just to allow leading commas for all
159 // members in the macro-generated constructor initializer lists.
163 //-----------------------------------------------------------------------------
164 // ParamTraits specializations, etc.
167 static inline void WriteParam(Message
* m
, const P
& p
) {
168 typedef typename SimilarTypeTraits
<P
>::Type Type
;
169 ParamTraits
<Type
>::Write(m
, static_cast<const Type
& >(p
));
173 static inline bool WARN_UNUSED_RESULT
ReadParam(const Message
* m
,
174 PickleIterator
* iter
,
176 typedef typename SimilarTypeTraits
<P
>::Type Type
;
177 return ParamTraits
<Type
>::Read(m
, iter
, reinterpret_cast<Type
* >(p
));
181 static inline void LogParam(const P
& p
, std::string
* l
) {
182 typedef typename SimilarTypeTraits
<P
>::Type Type
;
183 ParamTraits
<Type
>::Log(static_cast<const Type
& >(p
), l
);
187 struct ParamTraits
<bool> {
188 typedef bool param_type
;
189 static void Write(Message
* m
, const param_type
& p
) {
192 static bool Read(const Message
* m
, PickleIterator
* iter
,
194 return m
->ReadBool(iter
, r
);
196 static void Log(const param_type
& p
, std::string
* l
) {
197 l
->append(p
? "true" : "false");
202 struct ParamTraits
<int> {
203 typedef int param_type
;
204 static void Write(Message
* m
, const param_type
& p
) {
207 static bool Read(const Message
* m
, PickleIterator
* iter
,
209 return m
->ReadInt(iter
, r
);
211 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
215 struct ParamTraits
<unsigned int> {
216 typedef unsigned int param_type
;
217 static void Write(Message
* m
, const param_type
& p
) {
220 static bool Read(const Message
* m
, PickleIterator
* iter
,
222 return m
->ReadInt(iter
, reinterpret_cast<int*>(r
));
224 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
228 struct ParamTraits
<long> {
229 typedef long param_type
;
230 static void Write(Message
* m
, const param_type
& p
) {
231 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
233 static bool Read(const Message
* m
, PickleIterator
* iter
,
235 return m
->ReadLong(iter
, r
);
237 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
241 struct ParamTraits
<unsigned long> {
242 typedef unsigned long param_type
;
243 static void Write(Message
* m
, const param_type
& p
) {
244 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
246 static bool Read(const Message
* m
, PickleIterator
* iter
,
248 return m
->ReadLong(iter
, reinterpret_cast<long*>(r
));
250 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
254 struct ParamTraits
<long long> {
255 typedef long long param_type
;
256 static void Write(Message
* m
, const param_type
& p
) {
257 m
->WriteInt64(static_cast<int64
>(p
));
259 static bool Read(const Message
* m
, PickleIterator
* iter
,
261 return m
->ReadInt64(iter
, reinterpret_cast<int64
*>(r
));
263 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
267 struct ParamTraits
<unsigned long long> {
268 typedef unsigned long long param_type
;
269 static void Write(Message
* m
, const param_type
& p
) {
272 static bool Read(const Message
* m
, PickleIterator
* iter
,
274 return m
->ReadInt64(iter
, reinterpret_cast<int64
*>(r
));
276 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
280 struct IPC_EXPORT ParamTraits
<unsigned short> {
281 typedef unsigned short param_type
;
282 static void Write(Message
* m
, const param_type
& p
);
283 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
284 static void Log(const param_type
& p
, std::string
* l
);
287 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
288 // should be sure to check the sanity of these values after receiving them over
291 struct ParamTraits
<float> {
292 typedef float param_type
;
293 static void Write(Message
* m
, const param_type
& p
) {
294 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(param_type
));
296 static bool Read(const Message
* m
, PickleIterator
* iter
,
300 if (!m
->ReadData(iter
, &data
, &data_size
) ||
301 data_size
!= sizeof(param_type
)) {
305 memcpy(r
, data
, sizeof(param_type
));
308 static void Log(const param_type
& p
, std::string
* l
) {
309 l
->append(StringPrintf("%e", p
));
314 struct ParamTraits
<double> {
315 typedef double param_type
;
316 static void Write(Message
* m
, const param_type
& p
) {
317 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(param_type
));
319 static bool Read(const Message
* m
, PickleIterator
* iter
,
323 if (!m
->ReadData(iter
, &data
, &data_size
) ||
324 data_size
!= sizeof(param_type
)) {
328 memcpy(r
, data
, sizeof(param_type
));
331 static void Log(const param_type
& p
, std::string
* l
) {
332 l
->append(StringPrintf("%e", p
));
337 struct IPC_EXPORT ParamTraits
<base::Time
> {
338 typedef base::Time param_type
;
339 static void Write(Message
* m
, const param_type
& p
);
340 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
341 static void Log(const param_type
& p
, std::string
* l
);
345 struct IPC_EXPORT ParamTraits
<base::TimeDelta
> {
346 typedef base::TimeDelta param_type
;
347 static void Write(Message
* m
, const param_type
& p
);
348 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
349 static void Log(const param_type
& p
, std::string
* l
);
353 struct IPC_EXPORT ParamTraits
<base::TimeTicks
> {
354 typedef base::TimeTicks param_type
;
355 static void Write(Message
* m
, const param_type
& p
);
356 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
357 static void Log(const param_type
& p
, std::string
* l
);
362 struct ParamTraits
<LOGFONT
> {
363 typedef LOGFONT param_type
;
364 static void Write(Message
* m
, const param_type
& p
) {
365 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(LOGFONT
));
367 static bool Read(const Message
* m
, PickleIterator
* iter
,
371 bool result
= m
->ReadData(iter
, &data
, &data_size
);
372 if (result
&& data_size
== sizeof(LOGFONT
)) {
373 memcpy(r
, data
, sizeof(LOGFONT
));
381 static void Log(const param_type
& p
, std::string
* l
) {
382 l
->append(StringPrintf("<LOGFONT>"));
387 struct ParamTraits
<MSG
> {
388 typedef MSG param_type
;
389 static void Write(Message
* m
, const param_type
& p
) {
390 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(MSG
));
392 static bool Read(const Message
* m
, PickleIterator
* iter
,
396 bool result
= m
->ReadData(iter
, &data
, &data_size
);
397 if (result
&& data_size
== sizeof(MSG
)) {
398 memcpy(r
, data
, sizeof(MSG
));
406 static void Log(const param_type
& p
, std::string
* l
) {
410 #endif // defined(OS_WIN)
413 struct IPC_EXPORT ParamTraits
<base::DictionaryValue
> {
414 typedef base::DictionaryValue param_type
;
415 static void Write(Message
* m
, const param_type
& p
);
416 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
417 static void Log(const param_type
& p
, std::string
* l
);
421 struct IPC_EXPORT ParamTraits
<base::ListValue
> {
422 typedef base::ListValue param_type
;
423 static void Write(Message
* m
, const param_type
& p
);
424 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
425 static void Log(const param_type
& p
, std::string
* l
);
429 struct ParamTraits
<std::string
> {
430 typedef std::string param_type
;
431 static void Write(Message
* m
, const param_type
& p
) {
434 static bool Read(const Message
* m
, PickleIterator
* iter
,
436 return m
->ReadString(iter
, r
);
438 static void Log(const param_type
& p
, std::string
* l
) {
443 template<typename CharType
>
444 static void LogBytes(const std::vector
<CharType
>& data
, std::string
* out
) {
446 // Windows has a GUI for logging, which can handle arbitrary binary data.
447 for (size_t i
= 0; i
< data
.size(); ++i
)
448 out
->push_back(data
[i
]);
450 // On POSIX, we log to stdout, which we assume can display ASCII.
451 static const size_t kMaxBytesToLog
= 100;
452 for (size_t i
= 0; i
< std::min(data
.size(), kMaxBytesToLog
); ++i
) {
453 if (isprint(data
[i
]))
454 out
->push_back(data
[i
]);
456 out
->append(StringPrintf("[%02X]", static_cast<unsigned char>(data
[i
])));
458 if (data
.size() > kMaxBytesToLog
) {
460 StringPrintf(" and %u more bytes",
461 static_cast<unsigned>(data
.size() - kMaxBytesToLog
)));
467 struct ParamTraits
<std::vector
<unsigned char> > {
468 typedef std::vector
<unsigned char> param_type
;
469 static void Write(Message
* m
, const param_type
& p
) {
471 m
->WriteData(NULL
, 0);
473 m
->WriteData(reinterpret_cast<const char*>(&p
.front()),
474 static_cast<int>(p
.size()));
477 static bool Read(const Message
* m
, PickleIterator
* iter
,
481 if (!m
->ReadData(iter
, &data
, &data_size
) || data_size
< 0)
483 r
->resize(data_size
);
485 memcpy(&r
->front(), data
, data_size
);
488 static void Log(const param_type
& p
, std::string
* l
) {
494 struct ParamTraits
<std::vector
<char> > {
495 typedef std::vector
<char> param_type
;
496 static void Write(Message
* m
, const param_type
& p
) {
498 m
->WriteData(NULL
, 0);
500 m
->WriteData(&p
.front(), static_cast<int>(p
.size()));
503 static bool Read(const Message
* m
, PickleIterator
* iter
,
507 if (!m
->ReadData(iter
, &data
, &data_size
) || data_size
< 0)
509 r
->resize(data_size
);
511 memcpy(&r
->front(), data
, data_size
);
514 static void Log(const param_type
& p
, std::string
* l
) {
520 struct ParamTraits
<std::vector
<bool> > {
521 typedef std::vector
<bool> param_type
;
522 static void Write(Message
* m
, const param_type
& p
) {
523 WriteParam(m
, static_cast<int>(p
.size()));
524 for (size_t i
= 0; i
< p
.size(); i
++)
527 static bool Read(const Message
* m
, PickleIterator
* iter
,
530 // ReadLength() checks for < 0 itself.
531 if (!m
->ReadLength(iter
, &size
))
534 for (int i
= 0; i
< size
; i
++) {
536 if (!ReadParam(m
, iter
, &value
))
542 static void Log(const param_type
& p
, std::string
* l
) {
543 for (size_t i
= 0; i
< p
.size(); ++i
) {
552 struct ParamTraits
<std::vector
<P
> > {
553 typedef std::vector
<P
> param_type
;
554 static void Write(Message
* m
, const param_type
& p
) {
555 WriteParam(m
, static_cast<int>(p
.size()));
556 for (size_t i
= 0; i
< p
.size(); i
++)
559 static bool Read(const Message
* m
, PickleIterator
* iter
,
562 // ReadLength() checks for < 0 itself.
563 if (!m
->ReadLength(iter
, &size
))
565 // Resizing beforehand is not safe, see BUG 1006367 for details.
566 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
569 for (int i
= 0; i
< size
; i
++) {
570 if (!ReadParam(m
, iter
, &(*r
)[i
]))
575 static void Log(const param_type
& p
, std::string
* l
) {
576 for (size_t i
= 0; i
< p
.size(); ++i
) {
585 struct ParamTraits
<std::set
<P
> > {
586 typedef std::set
<P
> param_type
;
587 static void Write(Message
* m
, const param_type
& p
) {
588 WriteParam(m
, static_cast<int>(p
.size()));
589 typename
param_type::const_iterator iter
;
590 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
591 WriteParam(m
, *iter
);
593 static bool Read(const Message
* m
, PickleIterator
* iter
,
596 if (!m
->ReadLength(iter
, &size
))
598 for (int i
= 0; i
< size
; ++i
) {
600 if (!ReadParam(m
, iter
, &item
))
606 static void Log(const param_type
& p
, std::string
* l
) {
607 l
->append("<std::set>");
612 template <class K
, class V
>
613 struct ParamTraits
<std::map
<K
, V
> > {
614 typedef std::map
<K
, V
> param_type
;
615 static void Write(Message
* m
, const param_type
& p
) {
616 WriteParam(m
, static_cast<int>(p
.size()));
617 typename
param_type::const_iterator iter
;
618 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
619 WriteParam(m
, iter
->first
);
620 WriteParam(m
, iter
->second
);
623 static bool Read(const Message
* m
, PickleIterator
* iter
,
626 if (!ReadParam(m
, iter
, &size
) || size
< 0)
628 for (int i
= 0; i
< size
; ++i
) {
630 if (!ReadParam(m
, iter
, &k
))
633 if (!ReadParam(m
, iter
, &value
))
638 static void Log(const param_type
& p
, std::string
* l
) {
639 l
->append("<std::map>");
645 struct ParamTraits
<std::wstring
> {
646 typedef std::wstring param_type
;
647 static void Write(Message
* m
, const param_type
& p
) {
650 static bool Read(const Message
* m
, PickleIterator
* iter
,
652 return m
->ReadWString(iter
, r
);
654 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
657 template <class A
, class B
>
658 struct ParamTraits
<std::pair
<A
, B
> > {
659 typedef std::pair
<A
, B
> param_type
;
660 static void Write(Message
* m
, const param_type
& p
) {
661 WriteParam(m
, p
.first
);
662 WriteParam(m
, p
.second
);
664 static bool Read(const Message
* m
, PickleIterator
* iter
,
666 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
668 static void Log(const param_type
& p
, std::string
* l
) {
670 LogParam(p
.first
, l
);
672 LogParam(p
.second
, l
);
678 struct IPC_EXPORT ParamTraits
<NullableString16
> {
679 typedef NullableString16 param_type
;
680 static void Write(Message
* m
, const param_type
& p
);
681 static bool Read(const Message
* m
, PickleIterator
* iter
,
683 static void Log(const param_type
& p
, std::string
* l
);
686 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
688 #if !defined(WCHAR_T_IS_UTF16)
690 struct ParamTraits
<string16
> {
691 typedef string16 param_type
;
692 static void Write(Message
* m
, const param_type
& p
) {
695 static bool Read(const Message
* m
, PickleIterator
* iter
,
697 return m
->ReadString16(iter
, r
);
699 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
703 // and, a few more useful types...
706 struct ParamTraits
<HANDLE
> {
707 typedef HANDLE param_type
;
708 static void Write(Message
* m
, const param_type
& p
) {
709 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
711 m
->WriteUInt32(reinterpret_cast<uint32
>(p
));
713 static bool Read(const Message
* m
, PickleIterator
* iter
,
715 DCHECK_EQ(sizeof(param_type
), sizeof(uint32
));
716 return m
->ReadUInt32(iter
, reinterpret_cast<uint32
*>(r
));
718 static void Log(const param_type
& p
, std::string
* l
) {
719 l
->append(StringPrintf("0x%X", p
));
724 struct ParamTraits
<HCURSOR
> {
725 typedef HCURSOR param_type
;
726 static void Write(Message
* m
, const param_type
& p
) {
727 m
->WriteUInt32(reinterpret_cast<uint32
>(p
));
729 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
730 DCHECK_EQ(sizeof(param_type
), sizeof(uint32
));
731 return m
->ReadUInt32(iter
, reinterpret_cast<uint32
*>(r
));
733 static void Log(const param_type
& p
, std::string
* l
) {
734 l
->append(StringPrintf("0x%X", p
));
739 struct ParamTraits
<HACCEL
> {
740 typedef HACCEL param_type
;
741 static void Write(Message
* m
, const param_type
& p
) {
742 m
->WriteUInt32(reinterpret_cast<uint32
>(p
));
744 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
745 DCHECK_EQ(sizeof(param_type
), sizeof(uint32
));
746 return m
->ReadUInt32(iter
, reinterpret_cast<uint32
*>(r
));
751 struct ParamTraits
<POINT
> {
752 typedef POINT param_type
;
753 static void Write(Message
* m
, const param_type
& p
) {
757 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
759 if (!m
->ReadInt(iter
, &x
) || !m
->ReadInt(iter
, &y
))
765 static void Log(const param_type
& p
, std::string
* l
) {
766 l
->append(StringPrintf("(%d, %d)", p
.x
, p
.y
));
769 #endif // defined(OS_WIN)
772 struct IPC_EXPORT ParamTraits
<FilePath
> {
773 typedef FilePath param_type
;
774 static void Write(Message
* m
, const param_type
& p
);
775 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
776 static void Log(const param_type
& p
, std::string
* l
);
779 #if defined(OS_POSIX)
780 // FileDescriptors may be serialised over IPC channels on POSIX. On the
781 // receiving side, the FileDescriptor is a valid duplicate of the file
782 // descriptor which was transmitted: *it is not just a copy of the integer like
783 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
784 // this case, the receiving end will see a value of -1. *Zero is a valid file
787 // The received file descriptor will have the |auto_close| flag set to true. The
788 // code which handles the message is responsible for taking ownership of it.
789 // File descriptors are OS resources and must be closed when no longer needed.
791 // When sending a file descriptor, the file descriptor must be valid at the time
792 // of transmission. Since transmission is not synchronous, one should consider
793 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
794 // flag, which causes the file descriptor to be closed after writing.
796 struct IPC_EXPORT ParamTraits
<base::FileDescriptor
> {
797 typedef base::FileDescriptor param_type
;
798 static void Write(Message
* m
, const param_type
& p
);
799 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
800 static void Log(const param_type
& p
, std::string
* l
);
802 #endif // defined(OS_POSIX)
804 // A ChannelHandle is basically a platform-inspecific wrapper around the
805 // fact that IPC endpoints are handled specially on POSIX. See above comments
806 // on FileDescriptor for more background.
808 struct IPC_EXPORT ParamTraits
<IPC::ChannelHandle
> {
809 typedef ChannelHandle param_type
;
810 static void Write(Message
* m
, const param_type
& p
);
811 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
812 static void Log(const param_type
& p
, std::string
* l
);
817 struct ParamTraits
<XFORM
> {
818 typedef XFORM param_type
;
819 static void Write(Message
* m
, const param_type
& p
) {
820 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(XFORM
));
822 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
825 bool result
= m
->ReadData(iter
, &data
, &data_size
);
826 if (result
&& data_size
== sizeof(XFORM
)) {
827 memcpy(r
, data
, sizeof(XFORM
));
835 static void Log(const param_type
& p
, std::string
* l
) {
836 l
->append("<XFORM>");
839 #endif // defined(OS_WIN)
841 struct IPC_EXPORT LogData
{
847 uint32 type
; // "User-defined" message type, from ipc_message.h.
849 int64 sent
; // Time that the message was sent (i.e. at Send()).
850 int64 receive
; // Time before it was dispatched (i.e. before calling
851 // OnMessageReceived).
852 int64 dispatch
; // Time after it was dispatched (i.e. after calling
853 // OnMessageReceived).
854 std::string message_name
;
859 struct IPC_EXPORT ParamTraits
<LogData
> {
860 typedef LogData param_type
;
861 static void Write(Message
* m
, const param_type
& p
);
862 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
863 static void Log(const param_type
& p
, std::string
* l
) {
864 // Doesn't make sense to implement this!
869 struct ParamTraits
<Message
> {
870 static void Write(Message
* m
, const Message
& p
) {
871 DCHECK(p
.size() <= INT_MAX
);
872 int message_size
= static_cast<int>(p
.size());
873 m
->WriteInt(message_size
);
874 m
->WriteData(reinterpret_cast<const char*>(p
.data()), message_size
);
876 static bool Read(const Message
* m
, PickleIterator
* iter
, Message
* r
) {
878 if (!m
->ReadInt(iter
, &size
))
881 if (!m
->ReadData(iter
, &data
, &size
))
883 *r
= Message(data
, size
);
886 static void Log(const Message
& p
, std::string
* l
) {
887 l
->append("<IPC::Message>");
892 struct ParamTraits
<Tuple0
> {
893 typedef Tuple0 param_type
;
894 static void Write(Message
* m
, const param_type
& p
) {
896 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
899 static void Log(const param_type
& p
, std::string
* l
) {
904 struct ParamTraits
< Tuple1
<A
> > {
905 typedef Tuple1
<A
> param_type
;
906 static void Write(Message
* m
, const param_type
& p
) {
909 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
910 return ReadParam(m
, iter
, &r
->a
);
912 static void Log(const param_type
& p
, std::string
* l
) {
917 template <class A
, class B
>
918 struct ParamTraits
< Tuple2
<A
, B
> > {
919 typedef Tuple2
<A
, B
> param_type
;
920 static void Write(Message
* m
, const param_type
& p
) {
924 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
925 return (ReadParam(m
, iter
, &r
->a
) &&
926 ReadParam(m
, iter
, &r
->b
));
928 static void Log(const param_type
& p
, std::string
* l
) {
935 template <class A
, class B
, class C
>
936 struct ParamTraits
< Tuple3
<A
, B
, C
> > {
937 typedef Tuple3
<A
, B
, C
> param_type
;
938 static void Write(Message
* m
, const param_type
& p
) {
943 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
944 return (ReadParam(m
, iter
, &r
->a
) &&
945 ReadParam(m
, iter
, &r
->b
) &&
946 ReadParam(m
, iter
, &r
->c
));
948 static void Log(const param_type
& p
, std::string
* l
) {
957 template <class A
, class B
, class C
, class D
>
958 struct ParamTraits
< Tuple4
<A
, B
, C
, D
> > {
959 typedef Tuple4
<A
, B
, C
, D
> param_type
;
960 static void Write(Message
* m
, const param_type
& p
) {
966 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
967 return (ReadParam(m
, iter
, &r
->a
) &&
968 ReadParam(m
, iter
, &r
->b
) &&
969 ReadParam(m
, iter
, &r
->c
) &&
970 ReadParam(m
, iter
, &r
->d
));
972 static void Log(const param_type
& p
, std::string
* l
) {
983 template <class A
, class B
, class C
, class D
, class E
>
984 struct ParamTraits
< Tuple5
<A
, B
, C
, D
, E
> > {
985 typedef Tuple5
<A
, B
, C
, D
, E
> param_type
;
986 static void Write(Message
* m
, const param_type
& p
) {
993 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
994 return (ReadParam(m
, iter
, &r
->a
) &&
995 ReadParam(m
, iter
, &r
->b
) &&
996 ReadParam(m
, iter
, &r
->c
) &&
997 ReadParam(m
, iter
, &r
->d
) &&
998 ReadParam(m
, iter
, &r
->e
));
1000 static void Log(const param_type
& p
, std::string
* l
) {
1013 //-----------------------------------------------------------------------------
1014 // Generic message subclasses
1016 // Used for asynchronous messages.
1017 template <class ParamType
>
1018 class MessageSchema
{
1020 typedef ParamType Param
;
1021 typedef typename TupleTypes
<ParamType
>::ParamTuple RefParam
;
1023 static void Write(Message
* msg
, const RefParam
& p
) IPC_MSG_NOINLINE
;
1024 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
1027 // defined in ipc_logging.cc
1028 IPC_EXPORT
void GenerateLogData(const std::string
& channel
,
1029 const Message
& message
,
1030 LogData
* data
, bool get_params
);
1033 #if defined(IPC_MESSAGE_LOG_ENABLED)
1034 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
1035 const std::string
& output_params
= msg
->output_params();
1036 if (!l
->empty() && !output_params
.empty())
1039 l
->append(output_params
);
1042 template <class ReplyParamType
>
1043 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
1044 const Message
* msg
) {
1045 if (msg
->received_time() != 0) {
1046 std::string output_params
;
1047 LogParam(reply_params
, &output_params
);
1048 msg
->set_output_params(output_params
);
1052 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
1053 if (msg
->sent_time()) {
1054 // Don't log the sync message after dispatch, as we don't have the
1055 // output parameters at that point. Instead, save its data and log it
1056 // with the outgoing reply message when it's sent.
1057 LogData
* data
= new LogData
;
1058 GenerateLogData("", *msg
, data
, true);
1059 msg
->set_dont_log();
1060 reply
->set_sync_log_data(data
);
1064 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
1066 template <class ReplyParamType
>
1067 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
1068 const Message
* msg
) {}
1070 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
1073 // This class assumes that its template argument is a RefTuple (a Tuple with
1074 // reference elements). This would go into ipc_message_utils_impl.h, but it is
1075 // also used by chrome_frame.
1076 template <class RefTuple
>
1077 class ParamDeserializer
: public MessageReplyDeserializer
{
1079 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
1081 bool SerializeOutputParameters(const IPC::Message
& msg
, PickleIterator iter
) {
1082 return ReadParam(&msg
, &iter
, &out_
);
1088 // Used for synchronous messages.
1089 template <class SendParamType
, class ReplyParamType
>
1090 class SyncMessageSchema
{
1092 typedef SendParamType SendParam
;
1093 typedef typename TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
1094 typedef ReplyParamType ReplyParam
;
1096 static void Write(Message
* msg
, const RefSendParam
& send
) IPC_MSG_NOINLINE
;
1097 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
1098 static bool ReadReplyParam(
1100 typename TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
1102 template<class T
, class S
, class Method
>
1103 static bool DispatchWithSendParams(bool ok
, const SendParam
& send_params
,
1104 const Message
* msg
, T
* obj
, S
* sender
,
1106 Message
* reply
= SyncMessage::GenerateReply(msg
);
1108 typename TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
1109 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
1110 WriteParam(reply
, reply_params
);
1111 LogReplyParamsToMessage(reply_params
, msg
);
1113 NOTREACHED() << "Error deserializing message " << msg
->type();
1114 reply
->set_reply_error();
1116 sender
->Send(reply
);
1120 template<class T
, class Method
>
1121 static bool DispatchDelayReplyWithSendParams(bool ok
,
1122 const SendParam
& send_params
,
1123 const Message
* msg
, T
* obj
,
1125 Message
* reply
= SyncMessage::GenerateReply(msg
);
1127 Tuple1
<Message
&> t
= MakeRefTuple(*reply
);
1128 ConnectMessageAndReply(msg
, reply
);
1129 DispatchToMethod(obj
, func
, send_params
, &t
);
1131 NOTREACHED() << "Error deserializing message " << msg
->type();
1132 reply
->set_reply_error();
1138 template<typename TA
>
1139 static void WriteReplyParams(Message
* reply
, TA a
) {
1141 WriteParam(reply
, p
);
1144 template<typename TA
, typename TB
>
1145 static void WriteReplyParams(Message
* reply
, TA a
, TB b
) {
1147 WriteParam(reply
, p
);
1150 template<typename TA
, typename TB
, typename TC
>
1151 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
) {
1152 ReplyParam
p(a
, b
, c
);
1153 WriteParam(reply
, p
);
1156 template<typename TA
, typename TB
, typename TC
, typename TD
>
1157 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
, TD d
) {
1158 ReplyParam
p(a
, b
, c
, d
);
1159 WriteParam(reply
, p
);
1162 template<typename TA
, typename TB
, typename TC
, typename TD
, typename TE
>
1163 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
, TD d
, TE e
) {
1164 ReplyParam
p(a
, b
, c
, d
, e
);
1165 WriteParam(reply
, p
);
1169 //-----------------------------------------------------------------------------
1173 #endif // IPC_IPC_MESSAGE_UTILS_H_