1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef IPC_IPC_MESSAGE_UTILS_H_
6 #define IPC_IPC_MESSAGE_UTILS_H_
14 #include "base/containers/small_map.h"
15 #include "base/files/file.h"
16 #include "base/format_macros.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/memory/scoped_vector.h"
19 #include "base/strings/string16.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/stringprintf.h"
22 #include "base/tuple.h"
23 #include "ipc/ipc_message_start.h"
24 #include "ipc/ipc_param_traits.h"
25 #include "ipc/ipc_sync_message.h"
27 #if defined(COMPILER_GCC)
28 // GCC "helpfully" tries to inline template methods in release mode. Except we
29 // want the majority of the template junk being expanded once in the
30 // implementation file (and only provide the definitions in
31 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
32 // at every call site. Special note: GCC happily accepts the attribute before
33 // the method declaration, but only acts on it if it is after.
34 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
35 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
36 // the introduced noclone attribute, which will create specialized versions of
37 // functions/methods when certain types are constant.
38 // www.gnu.org/software/gcc/gcc-4.5/changes.html
39 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
41 #define IPC_MSG_NOINLINE __attribute__((noinline));
43 #elif defined(COMPILER_MSVC)
44 // MSVC++ doesn't do this.
45 #define IPC_MSG_NOINLINE
47 #error "Please add the noinline property for your new compiler here."
51 class DictionaryValue;
54 class NullableString16;
58 struct FileDescriptor;
65 // -----------------------------------------------------------------------------
66 // How we send IPC message logs across channels.
67 struct IPC_EXPORT LogData {
73 uint32 type; // "User-defined" message type, from ipc_message.h.
75 int64 sent; // Time that the message was sent (i.e. at Send()).
76 int64 receive; // Time before it was dispatched (i.e. before calling
77 // OnMessageReceived).
78 int64 dispatch; // Time after it was dispatched (i.e. after calling
79 // OnMessageReceived).
80 std::string message_name;
84 //-----------------------------------------------------------------------------
86 // A dummy struct to place first just to allow leading commas for all
87 // members in the macro-generated constructor initializer lists.
92 static inline void WriteParam(Message* m, const P& p) {
93 typedef typename SimilarTypeTraits<P>::Type Type;
94 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
98 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m,
101 typedef typename SimilarTypeTraits<P>::Type Type;
102 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
106 static inline void LogParam(const P& p, std::string* l) {
107 typedef typename SimilarTypeTraits<P>::Type Type;
108 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
111 // Primitive ParamTraits -------------------------------------------------------
114 struct ParamTraits<bool> {
115 typedef bool param_type;
116 static void Write(Message* m, const param_type& p) {
119 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
120 return m->ReadBool(iter, r);
122 IPC_EXPORT static void Log(const param_type& p, std::string* l);
126 struct IPC_EXPORT ParamTraits<unsigned char> {
127 typedef unsigned char param_type;
128 static void Write(Message* m, const param_type& p);
129 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
130 static void Log(const param_type& p, std::string* l);
134 struct IPC_EXPORT ParamTraits<unsigned short> {
135 typedef unsigned short param_type;
136 static void Write(Message* m, const param_type& p);
137 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
138 static void Log(const param_type& p, std::string* l);
142 struct ParamTraits<int> {
143 typedef int param_type;
144 static void Write(Message* m, const param_type& p) {
147 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
148 return m->ReadInt(iter, r);
150 IPC_EXPORT static void Log(const param_type& p, std::string* l);
154 struct ParamTraits<unsigned int> {
155 typedef unsigned int param_type;
156 static void Write(Message* m, const param_type& p) {
159 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
160 return m->ReadInt(iter, reinterpret_cast<int*>(r));
162 IPC_EXPORT static void Log(const param_type& p, std::string* l);
166 struct ParamTraits<long> {
167 typedef long param_type;
168 static void Write(Message* m, const param_type& p) {
169 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
171 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
172 return m->ReadLong(iter, r);
174 IPC_EXPORT static void Log(const param_type& p, std::string* l);
178 struct ParamTraits<unsigned long> {
179 typedef unsigned long param_type;
180 static void Write(Message* m, const param_type& p) {
181 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
183 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
184 return m->ReadLong(iter, reinterpret_cast<long*>(r));
186 IPC_EXPORT static void Log(const param_type& p, std::string* l);
190 struct ParamTraits<long long> {
191 typedef long long param_type;
192 static void Write(Message* m, const param_type& p) {
193 m->WriteInt64(static_cast<int64>(p));
195 static bool Read(const Message* m, PickleIterator* iter,
197 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
199 IPC_EXPORT static void Log(const param_type& p, std::string* l);
203 struct ParamTraits<unsigned long long> {
204 typedef unsigned long long param_type;
205 static void Write(Message* m, const param_type& p) {
208 static bool Read(const Message* m, PickleIterator* iter,
210 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
212 IPC_EXPORT static void Log(const param_type& p, std::string* l);
215 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
216 // should be sure to check the sanity of these values after receiving them over
219 struct IPC_EXPORT ParamTraits<float> {
220 typedef float param_type;
221 static void Write(Message* m, const param_type& p) {
224 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
225 return m->ReadFloat(iter, r);
227 static void Log(const param_type& p, std::string* l);
231 struct IPC_EXPORT ParamTraits<double> {
232 typedef double param_type;
233 static void Write(Message* m, const param_type& p);
234 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
235 static void Log(const param_type& p, std::string* l);
238 // STL ParamTraits -------------------------------------------------------------
241 struct ParamTraits<std::string> {
242 typedef std::string param_type;
243 static void Write(Message* m, const param_type& p) {
246 static bool Read(const Message* m, PickleIterator* iter,
248 return m->ReadString(iter, r);
250 IPC_EXPORT static void Log(const param_type& p, std::string* l);
254 struct ParamTraits<std::wstring> {
255 typedef std::wstring param_type;
256 static void Write(Message* m, const param_type& p) {
259 static bool Read(const Message* m, PickleIterator* iter,
261 return m->ReadWString(iter, r);
263 IPC_EXPORT static void Log(const param_type& p, std::string* l);
266 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
268 #if !defined(WCHAR_T_IS_UTF16)
270 struct ParamTraits<base::string16> {
271 typedef base::string16 param_type;
272 static void Write(Message* m, const param_type& p) {
275 static bool Read(const Message* m, PickleIterator* iter,
277 return m->ReadString16(iter, r);
279 IPC_EXPORT static void Log(const param_type& p, std::string* l);
284 struct IPC_EXPORT ParamTraits<std::vector<char> > {
285 typedef std::vector<char> param_type;
286 static void Write(Message* m, const param_type& p);
287 static bool Read(const Message*, PickleIterator* iter, param_type* r);
288 static void Log(const param_type& p, std::string* l);
292 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
293 typedef std::vector<unsigned char> param_type;
294 static void Write(Message* m, const param_type& p);
295 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
296 static void Log(const param_type& p, std::string* l);
300 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
301 typedef std::vector<bool> param_type;
302 static void Write(Message* m, const param_type& p);
303 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
304 static void Log(const param_type& p, std::string* l);
308 struct ParamTraits<std::vector<P> > {
309 typedef std::vector<P> param_type;
310 static void Write(Message* m, const param_type& p) {
311 WriteParam(m, static_cast<int>(p.size()));
312 for (size_t i = 0; i < p.size(); i++)
315 static bool Read(const Message* m, PickleIterator* iter,
318 // ReadLength() checks for < 0 itself.
319 if (!m->ReadLength(iter, &size))
321 // Resizing beforehand is not safe, see BUG 1006367 for details.
322 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
325 for (int i = 0; i < size; i++) {
326 if (!ReadParam(m, iter, &(*r)[i]))
331 static void Log(const param_type& p, std::string* l) {
332 for (size_t i = 0; i < p.size(); ++i) {
341 struct ParamTraits<std::set<P> > {
342 typedef std::set<P> param_type;
343 static void Write(Message* m, const param_type& p) {
344 WriteParam(m, static_cast<int>(p.size()));
345 typename param_type::const_iterator iter;
346 for (iter = p.begin(); iter != p.end(); ++iter)
347 WriteParam(m, *iter);
349 static bool Read(const Message* m, PickleIterator* iter,
352 if (!m->ReadLength(iter, &size))
354 for (int i = 0; i < size; ++i) {
356 if (!ReadParam(m, iter, &item))
362 static void Log(const param_type& p, std::string* l) {
363 l->append("<std::set>");
367 template <class K, class V, class C, class A>
368 struct ParamTraits<std::map<K, V, C, A> > {
369 typedef std::map<K, V, C, A> param_type;
370 static void Write(Message* m, const param_type& p) {
371 WriteParam(m, static_cast<int>(p.size()));
372 typename param_type::const_iterator iter;
373 for (iter = p.begin(); iter != p.end(); ++iter) {
374 WriteParam(m, iter->first);
375 WriteParam(m, iter->second);
378 static bool Read(const Message* m, PickleIterator* iter,
381 if (!ReadParam(m, iter, &size) || size < 0)
383 for (int i = 0; i < size; ++i) {
385 if (!ReadParam(m, iter, &k))
388 if (!ReadParam(m, iter, &value))
393 static void Log(const param_type& p, std::string* l) {
394 l->append("<std::map>");
398 template <class A, class B>
399 struct ParamTraits<std::pair<A, B> > {
400 typedef std::pair<A, B> param_type;
401 static void Write(Message* m, const param_type& p) {
402 WriteParam(m, p.first);
403 WriteParam(m, p.second);
405 static bool Read(const Message* m, PickleIterator* iter,
407 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
409 static void Log(const param_type& p, std::string* l) {
411 LogParam(p.first, l);
413 LogParam(p.second, l);
418 // Base ParamTraits ------------------------------------------------------------
421 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
422 typedef base::DictionaryValue 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);
428 #if defined(OS_POSIX)
429 // FileDescriptors may be serialised over IPC channels on POSIX. On the
430 // receiving side, the FileDescriptor is a valid duplicate of the file
431 // descriptor which was transmitted: *it is not just a copy of the integer like
432 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
433 // this case, the receiving end will see a value of -1. *Zero is a valid file
436 // The received file descriptor will have the |auto_close| flag set to true. The
437 // code which handles the message is responsible for taking ownership of it.
438 // File descriptors are OS resources and must be closed when no longer needed.
440 // When sending a file descriptor, the file descriptor must be valid at the time
441 // of transmission. Since transmission is not synchronous, one should consider
442 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
443 // flag, which causes the file descriptor to be closed after writing.
445 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
446 typedef base::FileDescriptor param_type;
447 static void Write(Message* m, const param_type& p);
448 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
449 static void Log(const param_type& p, std::string* l);
451 #endif // defined(OS_POSIX)
454 struct IPC_EXPORT ParamTraits<base::FilePath> {
455 typedef base::FilePath param_type;
456 static void Write(Message* m, const param_type& p);
457 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
458 static void Log(const param_type& p, std::string* l);
462 struct IPC_EXPORT ParamTraits<base::ListValue> {
463 typedef base::ListValue param_type;
464 static void Write(Message* m, const param_type& p);
465 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
466 static void Log(const param_type& p, std::string* l);
470 struct IPC_EXPORT ParamTraits<base::NullableString16> {
471 typedef base::NullableString16 param_type;
472 static void Write(Message* m, const param_type& p);
473 static bool Read(const Message* m, PickleIterator* iter,
475 static void Log(const param_type& p, std::string* l);
479 struct IPC_EXPORT ParamTraits<base::File::Info> {
480 typedef base::File::Info param_type;
481 static void Write(Message* m, const param_type& p);
482 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
483 static void Log(const param_type& p, std::string* l);
487 struct SimilarTypeTraits<base::File::Error> {
493 struct SimilarTypeTraits<HWND> {
496 #endif // defined(OS_WIN)
499 struct IPC_EXPORT ParamTraits<base::Time> {
500 typedef base::Time param_type;
501 static void Write(Message* m, const param_type& p);
502 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
503 static void Log(const param_type& p, std::string* l);
507 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
508 typedef base::TimeDelta param_type;
509 static void Write(Message* m, const param_type& p);
510 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
511 static void Log(const param_type& p, std::string* l);
515 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
516 typedef base::TimeTicks param_type;
517 static void Write(Message* m, const param_type& p);
518 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
519 static void Log(const param_type& p, std::string* l);
523 struct ParamTraits<Tuple0> {
524 typedef Tuple0 param_type;
525 static void Write(Message* m, const param_type& p) {
527 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
530 static void Log(const param_type& p, std::string* l) {
535 struct ParamTraits< Tuple1<A> > {
536 typedef Tuple1<A> param_type;
537 static void Write(Message* m, const param_type& p) {
540 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
541 return ReadParam(m, iter, &r->a);
543 static void Log(const param_type& p, std::string* l) {
548 template <class A, class B>
549 struct ParamTraits< Tuple2<A, B> > {
550 typedef Tuple2<A, B> param_type;
551 static void Write(Message* m, const param_type& p) {
555 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
556 return (ReadParam(m, iter, &r->a) &&
557 ReadParam(m, iter, &r->b));
559 static void Log(const param_type& p, std::string* l) {
566 template <class A, class B, class C>
567 struct ParamTraits< Tuple3<A, B, C> > {
568 typedef Tuple3<A, B, C> param_type;
569 static void Write(Message* m, const param_type& p) {
574 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
575 return (ReadParam(m, iter, &r->a) &&
576 ReadParam(m, iter, &r->b) &&
577 ReadParam(m, iter, &r->c));
579 static void Log(const param_type& p, std::string* l) {
588 template <class A, class B, class C, class D>
589 struct ParamTraits< Tuple4<A, B, C, D> > {
590 typedef Tuple4<A, B, C, D> param_type;
591 static void Write(Message* m, const param_type& p) {
597 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
598 return (ReadParam(m, iter, &r->a) &&
599 ReadParam(m, iter, &r->b) &&
600 ReadParam(m, iter, &r->c) &&
601 ReadParam(m, iter, &r->d));
603 static void Log(const param_type& p, std::string* l) {
614 template <class A, class B, class C, class D, class E>
615 struct ParamTraits< Tuple5<A, B, C, D, E> > {
616 typedef Tuple5<A, B, C, D, E> param_type;
617 static void Write(Message* m, const param_type& p) {
624 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
625 return (ReadParam(m, iter, &r->a) &&
626 ReadParam(m, iter, &r->b) &&
627 ReadParam(m, iter, &r->c) &&
628 ReadParam(m, iter, &r->d) &&
629 ReadParam(m, iter, &r->e));
631 static void Log(const param_type& p, std::string* l) {
645 struct ParamTraits<ScopedVector<P> > {
646 typedef ScopedVector<P> param_type;
647 static void Write(Message* m, const param_type& p) {
648 WriteParam(m, static_cast<int>(p.size()));
649 for (size_t i = 0; i < p.size(); i++)
650 WriteParam(m, *p[i]);
652 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
654 if (!m->ReadLength(iter, &size))
656 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
659 for (int i = 0; i < size; i++) {
661 if (!ReadParam(m, iter, (*r)[i]))
666 static void Log(const param_type& p, std::string* l) {
667 for (size_t i = 0; i < p.size(); ++i) {
675 template <typename NormalMap,
679 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
680 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
681 typedef typename param_type::key_type K;
682 typedef typename param_type::data_type V;
683 static void Write(Message* m, const param_type& p) {
684 WriteParam(m, static_cast<int>(p.size()));
685 typename param_type::const_iterator iter;
686 for (iter = p.begin(); iter != p.end(); ++iter) {
687 WriteParam(m, iter->first);
688 WriteParam(m, iter->second);
691 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
693 if (!m->ReadLength(iter, &size))
695 for (int i = 0; i < size; ++i) {
697 if (!ReadParam(m, iter, &key))
699 V& value = (*r)[key];
700 if (!ReadParam(m, iter, &value))
705 static void Log(const param_type& p, std::string* l) {
706 l->append("<base::SmallMap>");
711 struct ParamTraits<scoped_ptr<P> > {
712 typedef scoped_ptr<P> param_type;
713 static void Write(Message* m, const param_type& p) {
715 WriteParam(m, valid);
719 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
721 if (!ReadParam(m, iter, &valid))
729 param_type temp(new P());
730 if (!ReadParam(m, iter, temp.get()))
736 static void Log(const param_type& p, std::string* l) {
744 // IPC types ParamTraits -------------------------------------------------------
746 // A ChannelHandle is basically a platform-inspecific wrapper around the
747 // fact that IPC endpoints are handled specially on POSIX. See above comments
748 // on FileDescriptor for more background.
750 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
751 typedef ChannelHandle param_type;
752 static void Write(Message* m, const param_type& p);
753 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
754 static void Log(const param_type& p, std::string* l);
758 struct IPC_EXPORT ParamTraits<LogData> {
759 typedef LogData param_type;
760 static void Write(Message* m, const param_type& p);
761 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
762 static void Log(const param_type& p, std::string* l);
766 struct IPC_EXPORT ParamTraits<Message> {
767 static void Write(Message* m, const Message& p);
768 static bool Read(const Message* m, PickleIterator* iter, Message* r);
769 static void Log(const Message& p, std::string* l);
772 // Windows ParamTraits ---------------------------------------------------------
776 struct IPC_EXPORT ParamTraits<HANDLE> {
777 typedef HANDLE 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);
784 struct IPC_EXPORT ParamTraits<LOGFONT> {
785 typedef LOGFONT param_type;
786 static void Write(Message* m, const param_type& p);
787 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
788 static void Log(const param_type& p, std::string* l);
792 struct IPC_EXPORT ParamTraits<MSG> {
793 typedef MSG param_type;
794 static void Write(Message* m, const param_type& p);
795 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
796 static void Log(const param_type& p, std::string* l);
798 #endif // defined(OS_WIN)
800 //-----------------------------------------------------------------------------
801 // Generic message subclasses
803 // Used for asynchronous messages.
804 template <class ParamType>
805 class MessageSchema {
807 typedef ParamType Param;
808 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
810 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
811 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
814 // defined in ipc_logging.cc
815 IPC_EXPORT void GenerateLogData(const std::string& channel,
816 const Message& message,
817 LogData* data, bool get_params);
820 #if defined(IPC_MESSAGE_LOG_ENABLED)
821 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
822 const std::string& output_params = msg->output_params();
823 if (!l->empty() && !output_params.empty())
826 l->append(output_params);
829 template <class ReplyParamType>
830 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
831 const Message* msg) {
832 if (msg->received_time() != 0) {
833 std::string output_params;
834 LogParam(reply_params, &output_params);
835 msg->set_output_params(output_params);
839 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
840 if (msg->sent_time()) {
841 // Don't log the sync message after dispatch, as we don't have the
842 // output parameters at that point. Instead, save its data and log it
843 // with the outgoing reply message when it's sent.
844 LogData* data = new LogData;
845 GenerateLogData("", *msg, data, true);
847 reply->set_sync_log_data(data);
851 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
853 template <class ReplyParamType>
854 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
855 const Message* msg) {}
857 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
860 // This class assumes that its template argument is a RefTuple (a Tuple with
861 // reference elements). This would go into ipc_message_utils_impl.h, but it is
862 // also used by chrome_frame.
863 template <class RefTuple>
864 class ParamDeserializer : public MessageReplyDeserializer {
866 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
868 bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
869 return ReadParam(&msg, &iter, &out_);
875 // Used for synchronous messages.
876 template <class SendParamType, class ReplyParamType>
877 class SyncMessageSchema {
879 typedef SendParamType SendParam;
880 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
881 typedef ReplyParamType ReplyParam;
883 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
884 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
885 static bool ReadReplyParam(
887 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
889 template<class T, class S, class Method>
890 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
891 const Message* msg, T* obj, S* sender,
893 Message* reply = SyncMessage::GenerateReply(msg);
895 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
896 DispatchToMethod(obj, func, send_params, &reply_params);
897 WriteParam(reply, reply_params);
898 LogReplyParamsToMessage(reply_params, msg);
900 NOTREACHED() << "Error deserializing message " << msg->type();
901 reply->set_reply_error();
907 template<class T, class Method>
908 static bool DispatchDelayReplyWithSendParams(bool ok,
909 const SendParam& send_params,
910 const Message* msg, T* obj,
912 Message* reply = SyncMessage::GenerateReply(msg);
914 Tuple1<Message&> t = MakeRefTuple(*reply);
915 ConnectMessageAndReply(msg, reply);
916 DispatchToMethod(obj, func, send_params, &t);
918 NOTREACHED() << "Error deserializing message " << msg->type();
919 reply->set_reply_error();
925 template<typename TA>
926 static void WriteReplyParams(Message* reply, TA a) {
928 WriteParam(reply, p);
931 template<typename TA, typename TB>
932 static void WriteReplyParams(Message* reply, TA a, TB b) {
934 WriteParam(reply, p);
937 template<typename TA, typename TB, typename TC>
938 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
939 ReplyParam p(a, b, c);
940 WriteParam(reply, p);
943 template<typename TA, typename TB, typename TC, typename TD>
944 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
945 ReplyParam p(a, b, c, d);
946 WriteParam(reply, p);
949 template<typename TA, typename TB, typename TC, typename TD, typename TE>
950 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
951 ReplyParam p(a, b, c, d, e);
952 WriteParam(reply, p);
958 #endif // IPC_IPC_MESSAGE_UTILS_H_