Telemetry: Fix bots after r200641 and r200596.
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blobc775d8da00ebf29f08b8b96d0da84dafccc151be
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_
8 #include <algorithm>
9 #include <map>
10 #include <set>
11 #include <string>
12 #include <vector>
14 #include "base/format_macros.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/platform_file.h"
17 #include "base/string16.h"
18 #include "base/stringprintf.h"
19 #include "base/string_util.h"
20 #include "base/tuple.h"
21 #include "ipc/ipc_message_start.h"
22 #include "ipc/ipc_param_traits.h"
23 #include "ipc/ipc_sync_message.h"
25 #if defined(COMPILER_GCC)
26 // GCC "helpfully" tries to inline template methods in release mode. Except we
27 // want the majority of the template junk being expanded once in the
28 // implementation file (and only provide the definitions in
29 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
30 // at every call site. Special note: GCC happily accepts the attribute before
31 // the method declaration, but only acts on it if it is after.
32 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
33 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
34 // the introduced noclone attribute, which will create specialized versions of
35 // functions/methods when certain types are constant.
36 // www.gnu.org/software/gcc/gcc-4.5/changes.html
37 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
38 #else
39 #define IPC_MSG_NOINLINE __attribute__((noinline));
40 #endif
41 #elif defined(COMPILER_MSVC)
42 // MSVC++ doesn't do this.
43 #define IPC_MSG_NOINLINE
44 #else
45 #error "Please add the noinline property for your new compiler here."
46 #endif
48 class NullableString16;
50 namespace base {
51 class DictionaryValue;
52 class FilePath;
53 class ListValue;
54 class Time;
55 class TimeDelta;
56 class TimeTicks;
57 struct FileDescriptor;
60 namespace IPC {
62 struct ChannelHandle;
64 // -----------------------------------------------------------------------------
65 // How we send IPC message logs across channels.
66 struct IPC_EXPORT LogData {
67 LogData();
68 ~LogData();
70 std::string channel;
71 int32 routing_id;
72 uint32 type; // "User-defined" message type, from ipc_message.h.
73 std::string flags;
74 int64 sent; // Time that the message was sent (i.e. at Send()).
75 int64 receive; // Time before it was dispatched (i.e. before calling
76 // OnMessageReceived).
77 int64 dispatch; // Time after it was dispatched (i.e. after calling
78 // OnMessageReceived).
79 std::string message_name;
80 std::string params;
83 //-----------------------------------------------------------------------------
85 // A dummy struct to place first just to allow leading commas for all
86 // members in the macro-generated constructor initializer lists.
87 struct NoParams {
90 template <class P>
91 static inline void WriteParam(Message* m, const P& p) {
92 typedef typename SimilarTypeTraits<P>::Type Type;
93 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
96 template <class P>
97 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m,
98 PickleIterator* iter,
99 P* p) {
100 typedef typename SimilarTypeTraits<P>::Type Type;
101 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
104 template <class P>
105 static inline void LogParam(const P& p, std::string* l) {
106 typedef typename SimilarTypeTraits<P>::Type Type;
107 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
110 // Primitive ParamTraits -------------------------------------------------------
112 template <>
113 struct ParamTraits<bool> {
114 typedef bool param_type;
115 static void Write(Message* m, const param_type& p) {
116 m->WriteBool(p);
118 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
119 return m->ReadBool(iter, r);
121 IPC_EXPORT static void Log(const param_type& p, std::string* l);
124 template <>
125 struct ParamTraits<int> {
126 typedef int param_type;
127 static void Write(Message* m, const param_type& p) {
128 m->WriteInt(p);
130 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
131 return m->ReadInt(iter, r);
133 IPC_EXPORT static void Log(const param_type& p, std::string* l);
136 template <>
137 struct ParamTraits<unsigned int> {
138 typedef unsigned int param_type;
139 static void Write(Message* m, const param_type& p) {
140 m->WriteInt(p);
142 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
143 return m->ReadInt(iter, reinterpret_cast<int*>(r));
145 IPC_EXPORT static void Log(const param_type& p, std::string* l);
148 template <>
149 struct ParamTraits<long> {
150 typedef long param_type;
151 static void Write(Message* m, const param_type& p) {
152 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
154 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
155 return m->ReadLong(iter, r);
157 IPC_EXPORT static void Log(const param_type& p, std::string* l);
160 template <>
161 struct ParamTraits<unsigned long> {
162 typedef unsigned long param_type;
163 static void Write(Message* m, const param_type& p) {
164 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
166 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
167 return m->ReadLong(iter, reinterpret_cast<long*>(r));
169 IPC_EXPORT static void Log(const param_type& p, std::string* l);
172 template <>
173 struct ParamTraits<long long> {
174 typedef long long param_type;
175 static void Write(Message* m, const param_type& p) {
176 m->WriteInt64(static_cast<int64>(p));
178 static bool Read(const Message* m, PickleIterator* iter,
179 param_type* r) {
180 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
182 IPC_EXPORT static void Log(const param_type& p, std::string* l);
185 template <>
186 struct ParamTraits<unsigned long long> {
187 typedef unsigned long long param_type;
188 static void Write(Message* m, const param_type& p) {
189 m->WriteInt64(p);
191 static bool Read(const Message* m, PickleIterator* iter,
192 param_type* r) {
193 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
195 IPC_EXPORT static void Log(const param_type& p, std::string* l);
198 template <>
199 struct IPC_EXPORT ParamTraits<unsigned short> {
200 typedef unsigned short param_type;
201 static void Write(Message* m, const param_type& p);
202 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
203 static void Log(const param_type& p, std::string* l);
206 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
207 // should be sure to check the sanity of these values after receiving them over
208 // IPC.
209 template <>
210 struct IPC_EXPORT ParamTraits<float> {
211 typedef float param_type;
212 static void Write(Message* m, const param_type& p);
213 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
214 static void Log(const param_type& p, std::string* l);
217 template <>
218 struct IPC_EXPORT ParamTraits<double> {
219 typedef double param_type;
220 static void Write(Message* m, const param_type& p);
221 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
222 static void Log(const param_type& p, std::string* l);
225 // STL ParamTraits -------------------------------------------------------------
227 template <>
228 struct ParamTraits<std::string> {
229 typedef std::string param_type;
230 static void Write(Message* m, const param_type& p) {
231 m->WriteString(p);
233 static bool Read(const Message* m, PickleIterator* iter,
234 param_type* r) {
235 return m->ReadString(iter, r);
237 IPC_EXPORT static void Log(const param_type& p, std::string* l);
240 template <>
241 struct ParamTraits<std::wstring> {
242 typedef std::wstring param_type;
243 static void Write(Message* m, const param_type& p) {
244 m->WriteWString(p);
246 static bool Read(const Message* m, PickleIterator* iter,
247 param_type* r) {
248 return m->ReadWString(iter, r);
250 IPC_EXPORT static void Log(const param_type& p, std::string* l);
253 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
254 // need this trait.
255 #if !defined(WCHAR_T_IS_UTF16)
256 template <>
257 struct ParamTraits<string16> {
258 typedef string16 param_type;
259 static void Write(Message* m, const param_type& p) {
260 m->WriteString16(p);
262 static bool Read(const Message* m, PickleIterator* iter,
263 param_type* r) {
264 return m->ReadString16(iter, r);
266 IPC_EXPORT static void Log(const param_type& p, std::string* l);
268 #endif
270 template <>
271 struct IPC_EXPORT ParamTraits<std::vector<char> > {
272 typedef std::vector<char> param_type;
273 static void Write(Message* m, const param_type& p);
274 static bool Read(const Message*, PickleIterator* iter, param_type* r);
275 static void Log(const param_type& p, std::string* l);
278 template <>
279 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
280 typedef std::vector<unsigned char> param_type;
281 static void Write(Message* m, const param_type& p);
282 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
283 static void Log(const param_type& p, std::string* l);
286 template <>
287 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
288 typedef std::vector<bool> param_type;
289 static void Write(Message* m, const param_type& p);
290 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
291 static void Log(const param_type& p, std::string* l);
294 template <class P>
295 struct ParamTraits<std::vector<P> > {
296 typedef std::vector<P> param_type;
297 static void Write(Message* m, const param_type& p) {
298 WriteParam(m, static_cast<int>(p.size()));
299 for (size_t i = 0; i < p.size(); i++)
300 WriteParam(m, p[i]);
302 static bool Read(const Message* m, PickleIterator* iter,
303 param_type* r) {
304 int size;
305 // ReadLength() checks for < 0 itself.
306 if (!m->ReadLength(iter, &size))
307 return false;
308 // Resizing beforehand is not safe, see BUG 1006367 for details.
309 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
310 return false;
311 r->resize(size);
312 for (int i = 0; i < size; i++) {
313 if (!ReadParam(m, iter, &(*r)[i]))
314 return false;
316 return true;
318 static void Log(const param_type& p, std::string* l) {
319 for (size_t i = 0; i < p.size(); ++i) {
320 if (i != 0)
321 l->append(" ");
322 LogParam((p[i]), l);
327 template <class P>
328 struct ParamTraits<std::set<P> > {
329 typedef std::set<P> param_type;
330 static void Write(Message* m, const param_type& p) {
331 WriteParam(m, static_cast<int>(p.size()));
332 typename param_type::const_iterator iter;
333 for (iter = p.begin(); iter != p.end(); ++iter)
334 WriteParam(m, *iter);
336 static bool Read(const Message* m, PickleIterator* iter,
337 param_type* r) {
338 int size;
339 if (!m->ReadLength(iter, &size))
340 return false;
341 for (int i = 0; i < size; ++i) {
342 P item;
343 if (!ReadParam(m, iter, &item))
344 return false;
345 r->insert(item);
347 return true;
349 static void Log(const param_type& p, std::string* l) {
350 l->append("<std::set>");
354 template <class K, class V>
355 struct ParamTraits<std::map<K, V> > {
356 typedef std::map<K, V> param_type;
357 static void Write(Message* m, const param_type& p) {
358 WriteParam(m, static_cast<int>(p.size()));
359 typename param_type::const_iterator iter;
360 for (iter = p.begin(); iter != p.end(); ++iter) {
361 WriteParam(m, iter->first);
362 WriteParam(m, iter->second);
365 static bool Read(const Message* m, PickleIterator* iter,
366 param_type* r) {
367 int size;
368 if (!ReadParam(m, iter, &size) || size < 0)
369 return false;
370 for (int i = 0; i < size; ++i) {
371 K k;
372 if (!ReadParam(m, iter, &k))
373 return false;
374 V& value = (*r)[k];
375 if (!ReadParam(m, iter, &value))
376 return false;
378 return true;
380 static void Log(const param_type& p, std::string* l) {
381 l->append("<std::map>");
385 template <class A, class B>
386 struct ParamTraits<std::pair<A, B> > {
387 typedef std::pair<A, B> param_type;
388 static void Write(Message* m, const param_type& p) {
389 WriteParam(m, p.first);
390 WriteParam(m, p.second);
392 static bool Read(const Message* m, PickleIterator* iter,
393 param_type* r) {
394 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
396 static void Log(const param_type& p, std::string* l) {
397 l->append("(");
398 LogParam(p.first, l);
399 l->append(", ");
400 LogParam(p.second, l);
401 l->append(")");
405 // Base ParamTraits ------------------------------------------------------------
407 template <>
408 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
409 typedef base::DictionaryValue param_type;
410 static void Write(Message* m, const param_type& p);
411 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
412 static void Log(const param_type& p, std::string* l);
415 #if defined(OS_POSIX)
416 // FileDescriptors may be serialised over IPC channels on POSIX. On the
417 // receiving side, the FileDescriptor is a valid duplicate of the file
418 // descriptor which was transmitted: *it is not just a copy of the integer like
419 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
420 // this case, the receiving end will see a value of -1. *Zero is a valid file
421 // descriptor*.
423 // The received file descriptor will have the |auto_close| flag set to true. The
424 // code which handles the message is responsible for taking ownership of it.
425 // File descriptors are OS resources and must be closed when no longer needed.
427 // When sending a file descriptor, the file descriptor must be valid at the time
428 // of transmission. Since transmission is not synchronous, one should consider
429 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
430 // flag, which causes the file descriptor to be closed after writing.
431 template<>
432 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
433 typedef base::FileDescriptor param_type;
434 static void Write(Message* m, const param_type& p);
435 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
436 static void Log(const param_type& p, std::string* l);
438 #endif // defined(OS_POSIX)
440 template <>
441 struct IPC_EXPORT ParamTraits<base::FilePath> {
442 typedef base::FilePath param_type;
443 static void Write(Message* m, const param_type& p);
444 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
445 static void Log(const param_type& p, std::string* l);
448 template <>
449 struct IPC_EXPORT ParamTraits<base::ListValue> {
450 typedef base::ListValue param_type;
451 static void Write(Message* m, const param_type& p);
452 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
453 static void Log(const param_type& p, std::string* l);
456 template <>
457 struct IPC_EXPORT ParamTraits<NullableString16> {
458 typedef NullableString16 param_type;
459 static void Write(Message* m, const param_type& p);
460 static bool Read(const Message* m, PickleIterator* iter,
461 param_type* r);
462 static void Log(const param_type& p, std::string* l);
465 template <>
466 struct IPC_EXPORT ParamTraits<base::PlatformFileInfo> {
467 typedef base::PlatformFileInfo param_type;
468 static void Write(Message* m, const param_type& p);
469 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
470 static void Log(const param_type& p, std::string* l);
473 template <>
474 struct SimilarTypeTraits<base::PlatformFileError> {
475 typedef int Type;
478 #if defined(OS_WIN)
479 template <>
480 struct SimilarTypeTraits<HWND> {
481 typedef HANDLE Type;
483 #endif // defined(OS_WIN)
485 template <>
486 struct IPC_EXPORT ParamTraits<base::Time> {
487 typedef base::Time param_type;
488 static void Write(Message* m, const param_type& p);
489 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
490 static void Log(const param_type& p, std::string* l);
493 template <>
494 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
495 typedef base::TimeDelta param_type;
496 static void Write(Message* m, const param_type& p);
497 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
498 static void Log(const param_type& p, std::string* l);
501 template <>
502 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
503 typedef base::TimeTicks param_type;
504 static void Write(Message* m, const param_type& p);
505 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
506 static void Log(const param_type& p, std::string* l);
509 template <>
510 struct ParamTraits<Tuple0> {
511 typedef Tuple0 param_type;
512 static void Write(Message* m, const param_type& p) {
514 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
515 return true;
517 static void Log(const param_type& p, std::string* l) {
521 template <class A>
522 struct ParamTraits< Tuple1<A> > {
523 typedef Tuple1<A> param_type;
524 static void Write(Message* m, const param_type& p) {
525 WriteParam(m, p.a);
527 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
528 return ReadParam(m, iter, &r->a);
530 static void Log(const param_type& p, std::string* l) {
531 LogParam(p.a, l);
535 template <class A, class B>
536 struct ParamTraits< Tuple2<A, B> > {
537 typedef Tuple2<A, B> param_type;
538 static void Write(Message* m, const param_type& p) {
539 WriteParam(m, p.a);
540 WriteParam(m, p.b);
542 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
543 return (ReadParam(m, iter, &r->a) &&
544 ReadParam(m, iter, &r->b));
546 static void Log(const param_type& p, std::string* l) {
547 LogParam(p.a, l);
548 l->append(", ");
549 LogParam(p.b, l);
553 template <class A, class B, class C>
554 struct ParamTraits< Tuple3<A, B, C> > {
555 typedef Tuple3<A, B, C> param_type;
556 static void Write(Message* m, const param_type& p) {
557 WriteParam(m, p.a);
558 WriteParam(m, p.b);
559 WriteParam(m, p.c);
561 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
562 return (ReadParam(m, iter, &r->a) &&
563 ReadParam(m, iter, &r->b) &&
564 ReadParam(m, iter, &r->c));
566 static void Log(const param_type& p, std::string* l) {
567 LogParam(p.a, l);
568 l->append(", ");
569 LogParam(p.b, l);
570 l->append(", ");
571 LogParam(p.c, l);
575 template <class A, class B, class C, class D>
576 struct ParamTraits< Tuple4<A, B, C, D> > {
577 typedef Tuple4<A, B, C, D> param_type;
578 static void Write(Message* m, const param_type& p) {
579 WriteParam(m, p.a);
580 WriteParam(m, p.b);
581 WriteParam(m, p.c);
582 WriteParam(m, p.d);
584 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
585 return (ReadParam(m, iter, &r->a) &&
586 ReadParam(m, iter, &r->b) &&
587 ReadParam(m, iter, &r->c) &&
588 ReadParam(m, iter, &r->d));
590 static void Log(const param_type& p, std::string* l) {
591 LogParam(p.a, l);
592 l->append(", ");
593 LogParam(p.b, l);
594 l->append(", ");
595 LogParam(p.c, l);
596 l->append(", ");
597 LogParam(p.d, l);
601 template <class A, class B, class C, class D, class E>
602 struct ParamTraits< Tuple5<A, B, C, D, E> > {
603 typedef Tuple5<A, B, C, D, E> param_type;
604 static void Write(Message* m, const param_type& p) {
605 WriteParam(m, p.a);
606 WriteParam(m, p.b);
607 WriteParam(m, p.c);
608 WriteParam(m, p.d);
609 WriteParam(m, p.e);
611 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
612 return (ReadParam(m, iter, &r->a) &&
613 ReadParam(m, iter, &r->b) &&
614 ReadParam(m, iter, &r->c) &&
615 ReadParam(m, iter, &r->d) &&
616 ReadParam(m, iter, &r->e));
618 static void Log(const param_type& p, std::string* l) {
619 LogParam(p.a, l);
620 l->append(", ");
621 LogParam(p.b, l);
622 l->append(", ");
623 LogParam(p.c, l);
624 l->append(", ");
625 LogParam(p.d, l);
626 l->append(", ");
627 LogParam(p.e, l);
631 template<class P>
632 struct ParamTraits<ScopedVector<P> > {
633 typedef ScopedVector<P> param_type;
634 static void Write(Message* m, const param_type& p) {
635 WriteParam(m, static_cast<int>(p.size()));
636 for (size_t i = 0; i < p.size(); i++)
637 WriteParam(m, *p[i]);
639 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
640 int size = 0;
641 if (!m->ReadLength(iter, &size))
642 return false;
643 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
644 return false;
645 r->resize(size);
646 for (int i = 0; i < size; i++) {
647 (*r)[i] = new P();
648 if (!ReadParam(m, iter, (*r)[i]))
649 return false;
651 return true;
653 static void Log(const param_type& p, std::string* l) {
654 for (size_t i = 0; i < p.size(); ++i) {
655 if (i != 0)
656 l->append(" ");
657 LogParam(*p[i], l);
662 // IPC types ParamTraits -------------------------------------------------------
664 // A ChannelHandle is basically a platform-inspecific wrapper around the
665 // fact that IPC endpoints are handled specially on POSIX. See above comments
666 // on FileDescriptor for more background.
667 template<>
668 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
669 typedef ChannelHandle param_type;
670 static void Write(Message* m, const param_type& p);
671 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
672 static void Log(const param_type& p, std::string* l);
675 template <>
676 struct IPC_EXPORT ParamTraits<LogData> {
677 typedef LogData param_type;
678 static void Write(Message* m, const param_type& p);
679 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
680 static void Log(const param_type& p, std::string* l);
683 template <>
684 struct IPC_EXPORT ParamTraits<Message> {
685 static void Write(Message* m, const Message& p);
686 static bool Read(const Message* m, PickleIterator* iter, Message* r);
687 static void Log(const Message& p, std::string* l);
690 // Windows ParamTraits ---------------------------------------------------------
692 #if defined(OS_WIN)
693 template <>
694 struct IPC_EXPORT ParamTraits<HANDLE> {
695 typedef HANDLE param_type;
696 static void Write(Message* m, const param_type& p);
697 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
698 static void Log(const param_type& p, std::string* l);
701 template <>
702 struct IPC_EXPORT ParamTraits<LOGFONT> {
703 typedef LOGFONT param_type;
704 static void Write(Message* m, const param_type& p);
705 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
706 static void Log(const param_type& p, std::string* l);
709 template <>
710 struct IPC_EXPORT ParamTraits<MSG> {
711 typedef MSG param_type;
712 static void Write(Message* m, const param_type& p);
713 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
714 static void Log(const param_type& p, std::string* l);
716 #endif // defined(OS_WIN)
718 //-----------------------------------------------------------------------------
719 // Generic message subclasses
721 // Used for asynchronous messages.
722 template <class ParamType>
723 class MessageSchema {
724 public:
725 typedef ParamType Param;
726 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
728 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
729 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
732 // defined in ipc_logging.cc
733 IPC_EXPORT void GenerateLogData(const std::string& channel,
734 const Message& message,
735 LogData* data, bool get_params);
738 #if defined(IPC_MESSAGE_LOG_ENABLED)
739 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
740 const std::string& output_params = msg->output_params();
741 if (!l->empty() && !output_params.empty())
742 l->append(", ");
744 l->append(output_params);
747 template <class ReplyParamType>
748 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
749 const Message* msg) {
750 if (msg->received_time() != 0) {
751 std::string output_params;
752 LogParam(reply_params, &output_params);
753 msg->set_output_params(output_params);
757 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
758 if (msg->sent_time()) {
759 // Don't log the sync message after dispatch, as we don't have the
760 // output parameters at that point. Instead, save its data and log it
761 // with the outgoing reply message when it's sent.
762 LogData* data = new LogData;
763 GenerateLogData("", *msg, data, true);
764 msg->set_dont_log();
765 reply->set_sync_log_data(data);
768 #else
769 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
771 template <class ReplyParamType>
772 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
773 const Message* msg) {}
775 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
776 #endif
778 // This class assumes that its template argument is a RefTuple (a Tuple with
779 // reference elements). This would go into ipc_message_utils_impl.h, but it is
780 // also used by chrome_frame.
781 template <class RefTuple>
782 class ParamDeserializer : public MessageReplyDeserializer {
783 public:
784 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
786 bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
787 return ReadParam(&msg, &iter, &out_);
790 RefTuple out_;
793 // Used for synchronous messages.
794 template <class SendParamType, class ReplyParamType>
795 class SyncMessageSchema {
796 public:
797 typedef SendParamType SendParam;
798 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
799 typedef ReplyParamType ReplyParam;
801 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
802 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
803 static bool ReadReplyParam(
804 const Message* msg,
805 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
807 template<class T, class S, class Method>
808 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
809 const Message* msg, T* obj, S* sender,
810 Method func) {
811 Message* reply = SyncMessage::GenerateReply(msg);
812 if (ok) {
813 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
814 DispatchToMethod(obj, func, send_params, &reply_params);
815 WriteParam(reply, reply_params);
816 LogReplyParamsToMessage(reply_params, msg);
817 } else {
818 NOTREACHED() << "Error deserializing message " << msg->type();
819 reply->set_reply_error();
821 sender->Send(reply);
822 return ok;
825 template<class T, class Method>
826 static bool DispatchDelayReplyWithSendParams(bool ok,
827 const SendParam& send_params,
828 const Message* msg, T* obj,
829 Method func) {
830 Message* reply = SyncMessage::GenerateReply(msg);
831 if (ok) {
832 Tuple1<Message&> t = MakeRefTuple(*reply);
833 ConnectMessageAndReply(msg, reply);
834 DispatchToMethod(obj, func, send_params, &t);
835 } else {
836 NOTREACHED() << "Error deserializing message " << msg->type();
837 reply->set_reply_error();
838 obj->Send(reply);
840 return ok;
843 template<typename TA>
844 static void WriteReplyParams(Message* reply, TA a) {
845 ReplyParam p(a);
846 WriteParam(reply, p);
849 template<typename TA, typename TB>
850 static void WriteReplyParams(Message* reply, TA a, TB b) {
851 ReplyParam p(a, b);
852 WriteParam(reply, p);
855 template<typename TA, typename TB, typename TC>
856 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
857 ReplyParam p(a, b, c);
858 WriteParam(reply, p);
861 template<typename TA, typename TB, typename TC, typename TD>
862 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
863 ReplyParam p(a, b, c, d);
864 WriteParam(reply, p);
867 template<typename TA, typename TB, typename TC, typename TD, typename TE>
868 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
869 ReplyParam p(a, b, c, d, e);
870 WriteParam(reply, p);
874 } // namespace IPC
876 #endif // IPC_IPC_MESSAGE_UTILS_H_