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 BrowserPluginMsgStart
,
105 LastIPCMsgStart
// Must come last.
109 class NullableString16
;
112 class DictionaryValue
;
117 struct FileDescriptor
;
122 struct ChannelHandle
;
124 //-----------------------------------------------------------------------------
125 // An iterator class for reading the fields contained within a Message.
127 class MessageIterator
{
129 explicit MessageIterator(const Message
& m
) : iter_(m
) {
131 int NextInt() const {
133 if (!iter_
.ReadInt(&val
))
137 const std::string
NextString() const {
139 if (!iter_
.ReadString(&val
))
143 const std::wstring
NextWString() const {
145 if (!iter_
.ReadWString(&val
))
149 void NextData(const char** data
, int* length
) const {
150 if (!iter_
.ReadData(data
, length
)) {
155 mutable PickleIterator iter_
;
158 //-----------------------------------------------------------------------------
159 // A dummy struct to place first just to allow leading commas for all
160 // members in the macro-generated constructor initializer lists.
164 //-----------------------------------------------------------------------------
165 // ParamTraits specializations, etc.
168 static inline void WriteParam(Message
* m
, const P
& p
) {
169 typedef typename SimilarTypeTraits
<P
>::Type Type
;
170 ParamTraits
<Type
>::Write(m
, static_cast<const Type
& >(p
));
174 static inline bool WARN_UNUSED_RESULT
ReadParam(const Message
* m
,
175 PickleIterator
* iter
,
177 typedef typename SimilarTypeTraits
<P
>::Type Type
;
178 return ParamTraits
<Type
>::Read(m
, iter
, reinterpret_cast<Type
* >(p
));
182 static inline void LogParam(const P
& p
, std::string
* l
) {
183 typedef typename SimilarTypeTraits
<P
>::Type Type
;
184 ParamTraits
<Type
>::Log(static_cast<const Type
& >(p
), l
);
188 struct ParamTraits
<bool> {
189 typedef bool param_type
;
190 static void Write(Message
* m
, const param_type
& p
) {
193 static bool Read(const Message
* m
, PickleIterator
* iter
,
195 return m
->ReadBool(iter
, r
);
197 static void Log(const param_type
& p
, std::string
* l
) {
198 l
->append(p
? "true" : "false");
203 struct ParamTraits
<int> {
204 typedef int param_type
;
205 static void Write(Message
* m
, const param_type
& p
) {
208 static bool Read(const Message
* m
, PickleIterator
* iter
,
210 return m
->ReadInt(iter
, r
);
212 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
216 struct ParamTraits
<unsigned int> {
217 typedef unsigned int param_type
;
218 static void Write(Message
* m
, const param_type
& p
) {
221 static bool Read(const Message
* m
, PickleIterator
* iter
,
223 return m
->ReadInt(iter
, reinterpret_cast<int*>(r
));
225 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
229 struct ParamTraits
<long> {
230 typedef long param_type
;
231 static void Write(Message
* m
, const param_type
& p
) {
232 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
234 static bool Read(const Message
* m
, PickleIterator
* iter
,
236 return m
->ReadLong(iter
, r
);
238 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
242 struct ParamTraits
<unsigned long> {
243 typedef unsigned long param_type
;
244 static void Write(Message
* m
, const param_type
& p
) {
245 m
->WriteLongUsingDangerousNonPortableLessPersistableForm(p
);
247 static bool Read(const Message
* m
, PickleIterator
* iter
,
249 return m
->ReadLong(iter
, reinterpret_cast<long*>(r
));
251 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
255 struct ParamTraits
<long long> {
256 typedef long long param_type
;
257 static void Write(Message
* m
, const param_type
& p
) {
258 m
->WriteInt64(static_cast<int64
>(p
));
260 static bool Read(const Message
* m
, PickleIterator
* iter
,
262 return m
->ReadInt64(iter
, reinterpret_cast<int64
*>(r
));
264 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
268 struct ParamTraits
<unsigned long long> {
269 typedef unsigned long long param_type
;
270 static void Write(Message
* m
, const param_type
& p
) {
273 static bool Read(const Message
* m
, PickleIterator
* iter
,
275 return m
->ReadInt64(iter
, reinterpret_cast<int64
*>(r
));
277 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
281 struct IPC_EXPORT ParamTraits
<unsigned short> {
282 typedef unsigned short param_type
;
283 static void Write(Message
* m
, const param_type
& p
);
284 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
285 static void Log(const param_type
& p
, std::string
* l
);
288 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
289 // should be sure to check the sanity of these values after receiving them over
292 struct ParamTraits
<float> {
293 typedef float param_type
;
294 static void Write(Message
* m
, const param_type
& p
) {
295 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(param_type
));
297 static bool Read(const Message
* m
, PickleIterator
* iter
,
301 if (!m
->ReadData(iter
, &data
, &data_size
) ||
302 data_size
!= sizeof(param_type
)) {
306 memcpy(r
, data
, sizeof(param_type
));
309 static void Log(const param_type
& p
, std::string
* l
) {
310 l
->append(StringPrintf("%e", p
));
315 struct ParamTraits
<double> {
316 typedef double param_type
;
317 static void Write(Message
* m
, const param_type
& p
) {
318 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(param_type
));
320 static bool Read(const Message
* m
, PickleIterator
* iter
,
324 if (!m
->ReadData(iter
, &data
, &data_size
) ||
325 data_size
!= sizeof(param_type
)) {
329 memcpy(r
, data
, sizeof(param_type
));
332 static void Log(const param_type
& p
, std::string
* l
) {
333 l
->append(StringPrintf("%e", p
));
338 struct IPC_EXPORT ParamTraits
<base::Time
> {
339 typedef base::Time param_type
;
340 static void Write(Message
* m
, const param_type
& p
);
341 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
342 static void Log(const param_type
& p
, std::string
* l
);
346 struct IPC_EXPORT ParamTraits
<base::TimeDelta
> {
347 typedef base::TimeDelta param_type
;
348 static void Write(Message
* m
, const param_type
& p
);
349 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
350 static void Log(const param_type
& p
, std::string
* l
);
354 struct IPC_EXPORT ParamTraits
<base::TimeTicks
> {
355 typedef base::TimeTicks param_type
;
356 static void Write(Message
* m
, const param_type
& p
);
357 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
358 static void Log(const param_type
& p
, std::string
* l
);
363 struct ParamTraits
<LOGFONT
> {
364 typedef LOGFONT param_type
;
365 static void Write(Message
* m
, const param_type
& p
) {
366 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(LOGFONT
));
368 static bool Read(const Message
* m
, PickleIterator
* iter
,
372 bool result
= m
->ReadData(iter
, &data
, &data_size
);
373 if (result
&& data_size
== sizeof(LOGFONT
)) {
374 memcpy(r
, data
, sizeof(LOGFONT
));
382 static void Log(const param_type
& p
, std::string
* l
) {
383 l
->append(StringPrintf("<LOGFONT>"));
388 struct ParamTraits
<MSG
> {
389 typedef MSG param_type
;
390 static void Write(Message
* m
, const param_type
& p
) {
391 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(MSG
));
393 static bool Read(const Message
* m
, PickleIterator
* iter
,
397 bool result
= m
->ReadData(iter
, &data
, &data_size
);
398 if (result
&& data_size
== sizeof(MSG
)) {
399 memcpy(r
, data
, sizeof(MSG
));
407 static void Log(const param_type
& p
, std::string
* l
) {
411 #endif // defined(OS_WIN)
414 struct IPC_EXPORT ParamTraits
<base::DictionaryValue
> {
415 typedef base::DictionaryValue param_type
;
416 static void Write(Message
* m
, const param_type
& p
);
417 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
418 static void Log(const param_type
& p
, std::string
* l
);
422 struct IPC_EXPORT ParamTraits
<base::ListValue
> {
423 typedef base::ListValue param_type
;
424 static void Write(Message
* m
, const param_type
& p
);
425 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
426 static void Log(const param_type
& p
, std::string
* l
);
430 struct ParamTraits
<std::string
> {
431 typedef std::string param_type
;
432 static void Write(Message
* m
, const param_type
& p
) {
435 static bool Read(const Message
* m
, PickleIterator
* iter
,
437 return m
->ReadString(iter
, r
);
439 static void Log(const param_type
& p
, std::string
* l
) {
444 template<typename CharType
>
445 static void LogBytes(const std::vector
<CharType
>& data
, std::string
* out
) {
447 // Windows has a GUI for logging, which can handle arbitrary binary data.
448 for (size_t i
= 0; i
< data
.size(); ++i
)
449 out
->push_back(data
[i
]);
451 // On POSIX, we log to stdout, which we assume can display ASCII.
452 static const size_t kMaxBytesToLog
= 100;
453 for (size_t i
= 0; i
< std::min(data
.size(), kMaxBytesToLog
); ++i
) {
454 if (isprint(data
[i
]))
455 out
->push_back(data
[i
]);
457 out
->append(StringPrintf("[%02X]", static_cast<unsigned char>(data
[i
])));
459 if (data
.size() > kMaxBytesToLog
) {
461 StringPrintf(" and %u more bytes",
462 static_cast<unsigned>(data
.size() - kMaxBytesToLog
)));
468 struct ParamTraits
<std::vector
<unsigned char> > {
469 typedef std::vector
<unsigned char> param_type
;
470 static void Write(Message
* m
, const param_type
& p
) {
472 m
->WriteData(NULL
, 0);
474 m
->WriteData(reinterpret_cast<const char*>(&p
.front()),
475 static_cast<int>(p
.size()));
478 static bool Read(const Message
* m
, PickleIterator
* iter
,
482 if (!m
->ReadData(iter
, &data
, &data_size
) || data_size
< 0)
484 r
->resize(data_size
);
486 memcpy(&r
->front(), data
, data_size
);
489 static void Log(const param_type
& p
, std::string
* l
) {
495 struct ParamTraits
<std::vector
<char> > {
496 typedef std::vector
<char> param_type
;
497 static void Write(Message
* m
, const param_type
& p
) {
499 m
->WriteData(NULL
, 0);
501 m
->WriteData(&p
.front(), static_cast<int>(p
.size()));
504 static bool Read(const Message
* m
, PickleIterator
* iter
,
508 if (!m
->ReadData(iter
, &data
, &data_size
) || data_size
< 0)
510 r
->resize(data_size
);
512 memcpy(&r
->front(), data
, data_size
);
515 static void Log(const param_type
& p
, std::string
* l
) {
521 struct ParamTraits
<std::vector
<bool> > {
522 typedef std::vector
<bool> param_type
;
523 static void Write(Message
* m
, const param_type
& p
) {
524 WriteParam(m
, static_cast<int>(p
.size()));
525 for (size_t i
= 0; i
< p
.size(); i
++)
528 static bool Read(const Message
* m
, PickleIterator
* iter
,
531 // ReadLength() checks for < 0 itself.
532 if (!m
->ReadLength(iter
, &size
))
535 for (int i
= 0; i
< size
; i
++) {
537 if (!ReadParam(m
, iter
, &value
))
543 static void Log(const param_type
& p
, std::string
* l
) {
544 for (size_t i
= 0; i
< p
.size(); ++i
) {
553 struct ParamTraits
<std::vector
<P
> > {
554 typedef std::vector
<P
> param_type
;
555 static void Write(Message
* m
, const param_type
& p
) {
556 WriteParam(m
, static_cast<int>(p
.size()));
557 for (size_t i
= 0; i
< p
.size(); i
++)
560 static bool Read(const Message
* m
, PickleIterator
* iter
,
563 // ReadLength() checks for < 0 itself.
564 if (!m
->ReadLength(iter
, &size
))
566 // Resizing beforehand is not safe, see BUG 1006367 for details.
567 if (INT_MAX
/ sizeof(P
) <= static_cast<size_t>(size
))
570 for (int i
= 0; i
< size
; i
++) {
571 if (!ReadParam(m
, iter
, &(*r
)[i
]))
576 static void Log(const param_type
& p
, std::string
* l
) {
577 for (size_t i
= 0; i
< p
.size(); ++i
) {
586 struct ParamTraits
<std::set
<P
> > {
587 typedef std::set
<P
> param_type
;
588 static void Write(Message
* m
, const param_type
& p
) {
589 WriteParam(m
, static_cast<int>(p
.size()));
590 typename
param_type::const_iterator iter
;
591 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
)
592 WriteParam(m
, *iter
);
594 static bool Read(const Message
* m
, PickleIterator
* iter
,
597 if (!m
->ReadLength(iter
, &size
))
599 for (int i
= 0; i
< size
; ++i
) {
601 if (!ReadParam(m
, iter
, &item
))
607 static void Log(const param_type
& p
, std::string
* l
) {
608 l
->append("<std::set>");
613 template <class K
, class V
>
614 struct ParamTraits
<std::map
<K
, V
> > {
615 typedef std::map
<K
, V
> param_type
;
616 static void Write(Message
* m
, const param_type
& p
) {
617 WriteParam(m
, static_cast<int>(p
.size()));
618 typename
param_type::const_iterator iter
;
619 for (iter
= p
.begin(); iter
!= p
.end(); ++iter
) {
620 WriteParam(m
, iter
->first
);
621 WriteParam(m
, iter
->second
);
624 static bool Read(const Message
* m
, PickleIterator
* iter
,
627 if (!ReadParam(m
, iter
, &size
) || size
< 0)
629 for (int i
= 0; i
< size
; ++i
) {
631 if (!ReadParam(m
, iter
, &k
))
634 if (!ReadParam(m
, iter
, &value
))
639 static void Log(const param_type
& p
, std::string
* l
) {
640 l
->append("<std::map>");
646 struct ParamTraits
<std::wstring
> {
647 typedef std::wstring param_type
;
648 static void Write(Message
* m
, const param_type
& p
) {
651 static bool Read(const Message
* m
, PickleIterator
* iter
,
653 return m
->ReadWString(iter
, r
);
655 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
658 template <class A
, class B
>
659 struct ParamTraits
<std::pair
<A
, B
> > {
660 typedef std::pair
<A
, B
> param_type
;
661 static void Write(Message
* m
, const param_type
& p
) {
662 WriteParam(m
, p
.first
);
663 WriteParam(m
, p
.second
);
665 static bool Read(const Message
* m
, PickleIterator
* iter
,
667 return ReadParam(m
, iter
, &r
->first
) && ReadParam(m
, iter
, &r
->second
);
669 static void Log(const param_type
& p
, std::string
* l
) {
671 LogParam(p
.first
, l
);
673 LogParam(p
.second
, l
);
679 struct IPC_EXPORT ParamTraits
<NullableString16
> {
680 typedef NullableString16 param_type
;
681 static void Write(Message
* m
, const param_type
& p
);
682 static bool Read(const Message
* m
, PickleIterator
* iter
,
684 static void Log(const param_type
& p
, std::string
* l
);
687 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
689 #if !defined(WCHAR_T_IS_UTF16)
691 struct ParamTraits
<string16
> {
692 typedef string16 param_type
;
693 static void Write(Message
* m
, const param_type
& p
) {
696 static bool Read(const Message
* m
, PickleIterator
* iter
,
698 return m
->ReadString16(iter
, r
);
700 IPC_EXPORT
static void Log(const param_type
& p
, std::string
* l
);
704 // and, a few more useful types...
707 struct ParamTraits
<HANDLE
> {
708 typedef HANDLE param_type
;
709 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
711 static void Write(Message
* m
, const param_type
& p
) {
712 m
->WriteUInt32(reinterpret_cast<uint32
>(p
));
714 static bool Read(const Message
* m
, PickleIterator
* iter
,
717 if (!m
->ReadUInt32(iter
, &temp
))
719 *r
= reinterpret_cast<HANDLE
>(temp
);
722 static void Log(const param_type
& p
, std::string
* l
) {
723 l
->append(StringPrintf("0x%X", p
));
728 struct ParamTraits
<HCURSOR
> {
729 typedef HCURSOR param_type
;
730 static void Write(Message
* m
, const param_type
& p
) {
731 m
->WriteUInt32(reinterpret_cast<uint32
>(p
));
733 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
734 DCHECK_EQ(sizeof(param_type
), sizeof(uint32
));
735 return m
->ReadUInt32(iter
, reinterpret_cast<uint32
*>(r
));
737 static void Log(const param_type
& p
, std::string
* l
) {
738 l
->append(StringPrintf("0x%X", p
));
743 struct ParamTraits
<HACCEL
> {
744 typedef HACCEL param_type
;
745 static void Write(Message
* m
, const param_type
& p
) {
746 m
->WriteUInt32(reinterpret_cast<uint32
>(p
));
748 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
749 DCHECK_EQ(sizeof(param_type
), sizeof(uint32
));
750 return m
->ReadUInt32(iter
, reinterpret_cast<uint32
*>(r
));
755 struct ParamTraits
<POINT
> {
756 typedef POINT param_type
;
757 static void Write(Message
* m
, const param_type
& p
) {
761 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
763 if (!m
->ReadInt(iter
, &x
) || !m
->ReadInt(iter
, &y
))
769 static void Log(const param_type
& p
, std::string
* l
) {
770 l
->append(StringPrintf("(%d, %d)", p
.x
, p
.y
));
773 #endif // defined(OS_WIN)
776 struct IPC_EXPORT ParamTraits
<FilePath
> {
777 typedef FilePath param_type
;
778 static void Write(Message
* m
, const param_type
& p
);
779 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
780 static void Log(const param_type
& p
, std::string
* l
);
783 #if defined(OS_POSIX)
784 // FileDescriptors may be serialised over IPC channels on POSIX. On the
785 // receiving side, the FileDescriptor is a valid duplicate of the file
786 // descriptor which was transmitted: *it is not just a copy of the integer like
787 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
788 // this case, the receiving end will see a value of -1. *Zero is a valid file
791 // The received file descriptor will have the |auto_close| flag set to true. The
792 // code which handles the message is responsible for taking ownership of it.
793 // File descriptors are OS resources and must be closed when no longer needed.
795 // When sending a file descriptor, the file descriptor must be valid at the time
796 // of transmission. Since transmission is not synchronous, one should consider
797 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
798 // flag, which causes the file descriptor to be closed after writing.
800 struct IPC_EXPORT ParamTraits
<base::FileDescriptor
> {
801 typedef base::FileDescriptor param_type
;
802 static void Write(Message
* m
, const param_type
& p
);
803 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
804 static void Log(const param_type
& p
, std::string
* l
);
806 #endif // defined(OS_POSIX)
808 // A ChannelHandle is basically a platform-inspecific wrapper around the
809 // fact that IPC endpoints are handled specially on POSIX. See above comments
810 // on FileDescriptor for more background.
812 struct IPC_EXPORT ParamTraits
<IPC::ChannelHandle
> {
813 typedef ChannelHandle param_type
;
814 static void Write(Message
* m
, const param_type
& p
);
815 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
816 static void Log(const param_type
& p
, std::string
* l
);
821 struct ParamTraits
<XFORM
> {
822 typedef XFORM param_type
;
823 static void Write(Message
* m
, const param_type
& p
) {
824 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(XFORM
));
826 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
829 bool result
= m
->ReadData(iter
, &data
, &data_size
);
830 if (result
&& data_size
== sizeof(XFORM
)) {
831 memcpy(r
, data
, sizeof(XFORM
));
839 static void Log(const param_type
& p
, std::string
* l
) {
840 l
->append("<XFORM>");
843 #endif // defined(OS_WIN)
845 struct IPC_EXPORT LogData
{
851 uint32 type
; // "User-defined" message type, from ipc_message.h.
853 int64 sent
; // Time that the message was sent (i.e. at Send()).
854 int64 receive
; // Time before it was dispatched (i.e. before calling
855 // OnMessageReceived).
856 int64 dispatch
; // Time after it was dispatched (i.e. after calling
857 // OnMessageReceived).
858 std::string message_name
;
863 struct IPC_EXPORT ParamTraits
<LogData
> {
864 typedef LogData param_type
;
865 static void Write(Message
* m
, const param_type
& p
);
866 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
);
867 static void Log(const param_type
& p
, std::string
* l
) {
868 // Doesn't make sense to implement this!
873 struct ParamTraits
<Message
> {
874 static void Write(Message
* m
, const Message
& p
) {
875 DCHECK(p
.size() <= INT_MAX
);
876 int message_size
= static_cast<int>(p
.size());
877 m
->WriteInt(message_size
);
878 m
->WriteData(reinterpret_cast<const char*>(p
.data()), message_size
);
880 static bool Read(const Message
* m
, PickleIterator
* iter
, Message
* r
) {
882 if (!m
->ReadInt(iter
, &size
))
885 if (!m
->ReadData(iter
, &data
, &size
))
887 *r
= Message(data
, size
);
890 static void Log(const Message
& p
, std::string
* l
) {
891 l
->append("<IPC::Message>");
896 struct ParamTraits
<Tuple0
> {
897 typedef Tuple0 param_type
;
898 static void Write(Message
* m
, const param_type
& p
) {
900 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
903 static void Log(const param_type
& p
, std::string
* l
) {
908 struct ParamTraits
< Tuple1
<A
> > {
909 typedef Tuple1
<A
> param_type
;
910 static void Write(Message
* m
, const param_type
& p
) {
913 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
914 return ReadParam(m
, iter
, &r
->a
);
916 static void Log(const param_type
& p
, std::string
* l
) {
921 template <class A
, class B
>
922 struct ParamTraits
< Tuple2
<A
, B
> > {
923 typedef Tuple2
<A
, B
> param_type
;
924 static void Write(Message
* m
, const param_type
& p
) {
928 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
929 return (ReadParam(m
, iter
, &r
->a
) &&
930 ReadParam(m
, iter
, &r
->b
));
932 static void Log(const param_type
& p
, std::string
* l
) {
939 template <class A
, class B
, class C
>
940 struct ParamTraits
< Tuple3
<A
, B
, C
> > {
941 typedef Tuple3
<A
, B
, C
> param_type
;
942 static void Write(Message
* m
, const param_type
& p
) {
947 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
948 return (ReadParam(m
, iter
, &r
->a
) &&
949 ReadParam(m
, iter
, &r
->b
) &&
950 ReadParam(m
, iter
, &r
->c
));
952 static void Log(const param_type
& p
, std::string
* l
) {
961 template <class A
, class B
, class C
, class D
>
962 struct ParamTraits
< Tuple4
<A
, B
, C
, D
> > {
963 typedef Tuple4
<A
, B
, C
, D
> param_type
;
964 static void Write(Message
* m
, const param_type
& p
) {
970 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
971 return (ReadParam(m
, iter
, &r
->a
) &&
972 ReadParam(m
, iter
, &r
->b
) &&
973 ReadParam(m
, iter
, &r
->c
) &&
974 ReadParam(m
, iter
, &r
->d
));
976 static void Log(const param_type
& p
, std::string
* l
) {
987 template <class A
, class B
, class C
, class D
, class E
>
988 struct ParamTraits
< Tuple5
<A
, B
, C
, D
, E
> > {
989 typedef Tuple5
<A
, B
, C
, D
, E
> param_type
;
990 static void Write(Message
* m
, const param_type
& p
) {
997 static bool Read(const Message
* m
, PickleIterator
* iter
, param_type
* r
) {
998 return (ReadParam(m
, iter
, &r
->a
) &&
999 ReadParam(m
, iter
, &r
->b
) &&
1000 ReadParam(m
, iter
, &r
->c
) &&
1001 ReadParam(m
, iter
, &r
->d
) &&
1002 ReadParam(m
, iter
, &r
->e
));
1004 static void Log(const param_type
& p
, std::string
* l
) {
1017 //-----------------------------------------------------------------------------
1018 // Generic message subclasses
1020 // Used for asynchronous messages.
1021 template <class ParamType
>
1022 class MessageSchema
{
1024 typedef ParamType Param
;
1025 typedef typename TupleTypes
<ParamType
>::ParamTuple RefParam
;
1027 static void Write(Message
* msg
, const RefParam
& p
) IPC_MSG_NOINLINE
;
1028 static bool Read(const Message
* msg
, Param
* p
) IPC_MSG_NOINLINE
;
1031 // defined in ipc_logging.cc
1032 IPC_EXPORT
void GenerateLogData(const std::string
& channel
,
1033 const Message
& message
,
1034 LogData
* data
, bool get_params
);
1037 #if defined(IPC_MESSAGE_LOG_ENABLED)
1038 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {
1039 const std::string
& output_params
= msg
->output_params();
1040 if (!l
->empty() && !output_params
.empty())
1043 l
->append(output_params
);
1046 template <class ReplyParamType
>
1047 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
1048 const Message
* msg
) {
1049 if (msg
->received_time() != 0) {
1050 std::string output_params
;
1051 LogParam(reply_params
, &output_params
);
1052 msg
->set_output_params(output_params
);
1056 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {
1057 if (msg
->sent_time()) {
1058 // Don't log the sync message after dispatch, as we don't have the
1059 // output parameters at that point. Instead, save its data and log it
1060 // with the outgoing reply message when it's sent.
1061 LogData
* data
= new LogData
;
1062 GenerateLogData("", *msg
, data
, true);
1063 msg
->set_dont_log();
1064 reply
->set_sync_log_data(data
);
1068 inline void AddOutputParamsToLog(const Message
* msg
, std::string
* l
) {}
1070 template <class ReplyParamType
>
1071 inline void LogReplyParamsToMessage(const ReplyParamType
& reply_params
,
1072 const Message
* msg
) {}
1074 inline void ConnectMessageAndReply(const Message
* msg
, Message
* reply
) {}
1077 // This class assumes that its template argument is a RefTuple (a Tuple with
1078 // reference elements). This would go into ipc_message_utils_impl.h, but it is
1079 // also used by chrome_frame.
1080 template <class RefTuple
>
1081 class ParamDeserializer
: public MessageReplyDeserializer
{
1083 explicit ParamDeserializer(const RefTuple
& out
) : out_(out
) { }
1085 bool SerializeOutputParameters(const IPC::Message
& msg
, PickleIterator iter
) {
1086 return ReadParam(&msg
, &iter
, &out_
);
1092 // Used for synchronous messages.
1093 template <class SendParamType
, class ReplyParamType
>
1094 class SyncMessageSchema
{
1096 typedef SendParamType SendParam
;
1097 typedef typename TupleTypes
<SendParam
>::ParamTuple RefSendParam
;
1098 typedef ReplyParamType ReplyParam
;
1100 static void Write(Message
* msg
, const RefSendParam
& send
) IPC_MSG_NOINLINE
;
1101 static bool ReadSendParam(const Message
* msg
, SendParam
* p
) IPC_MSG_NOINLINE
;
1102 static bool ReadReplyParam(
1104 typename TupleTypes
<ReplyParam
>::ValueTuple
* p
) IPC_MSG_NOINLINE
;
1106 template<class T
, class S
, class Method
>
1107 static bool DispatchWithSendParams(bool ok
, const SendParam
& send_params
,
1108 const Message
* msg
, T
* obj
, S
* sender
,
1110 Message
* reply
= SyncMessage::GenerateReply(msg
);
1112 typename TupleTypes
<ReplyParam
>::ValueTuple reply_params
;
1113 DispatchToMethod(obj
, func
, send_params
, &reply_params
);
1114 WriteParam(reply
, reply_params
);
1115 LogReplyParamsToMessage(reply_params
, msg
);
1117 NOTREACHED() << "Error deserializing message " << msg
->type();
1118 reply
->set_reply_error();
1120 sender
->Send(reply
);
1124 template<class T
, class Method
>
1125 static bool DispatchDelayReplyWithSendParams(bool ok
,
1126 const SendParam
& send_params
,
1127 const Message
* msg
, T
* obj
,
1129 Message
* reply
= SyncMessage::GenerateReply(msg
);
1131 Tuple1
<Message
&> t
= MakeRefTuple(*reply
);
1132 ConnectMessageAndReply(msg
, reply
);
1133 DispatchToMethod(obj
, func
, send_params
, &t
);
1135 NOTREACHED() << "Error deserializing message " << msg
->type();
1136 reply
->set_reply_error();
1142 template<typename TA
>
1143 static void WriteReplyParams(Message
* reply
, TA a
) {
1145 WriteParam(reply
, p
);
1148 template<typename TA
, typename TB
>
1149 static void WriteReplyParams(Message
* reply
, TA a
, TB b
) {
1151 WriteParam(reply
, p
);
1154 template<typename TA
, typename TB
, typename TC
>
1155 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
) {
1156 ReplyParam
p(a
, b
, c
);
1157 WriteParam(reply
, p
);
1160 template<typename TA
, typename TB
, typename TC
, typename TD
>
1161 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
, TD d
) {
1162 ReplyParam
p(a
, b
, c
, d
);
1163 WriteParam(reply
, p
);
1166 template<typename TA
, typename TB
, typename TC
, typename TD
, typename TE
>
1167 static void WriteReplyParams(Message
* reply
, TA a
, TB b
, TC c
, TD d
, TE e
) {
1168 ReplyParam
p(a
, b
, c
, d
, e
);
1169 WriteParam(reply
, p
);
1173 //-----------------------------------------------------------------------------
1177 #endif // IPC_IPC_MESSAGE_UTILS_H_