Memory leak in module png_codec.cc on encoder error.
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blob73006598617b7c666df960aeefc894c20c73c125
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 FilePath;
49 class NullableString16;
51 namespace base {
52 class DictionaryValue;
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<FilePath> {
442 typedef 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 template <>
479 struct IPC_EXPORT ParamTraits<base::Time> {
480 typedef base::Time 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);
486 template <>
487 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
488 typedef base::TimeDelta param_type;
489 static void Write(Message* m, const param_type& p);
490 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
491 static void Log(const param_type& p, std::string* l);
494 template <>
495 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
496 typedef base::TimeTicks param_type;
497 static void Write(Message* m, const param_type& p);
498 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
499 static void Log(const param_type& p, std::string* l);
502 template <>
503 struct ParamTraits<Tuple0> {
504 typedef Tuple0 param_type;
505 static void Write(Message* m, const param_type& p) {
507 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
508 return true;
510 static void Log(const param_type& p, std::string* l) {
514 template <class A>
515 struct ParamTraits< Tuple1<A> > {
516 typedef Tuple1<A> param_type;
517 static void Write(Message* m, const param_type& p) {
518 WriteParam(m, p.a);
520 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
521 return ReadParam(m, iter, &r->a);
523 static void Log(const param_type& p, std::string* l) {
524 LogParam(p.a, l);
528 template <class A, class B>
529 struct ParamTraits< Tuple2<A, B> > {
530 typedef Tuple2<A, B> param_type;
531 static void Write(Message* m, const param_type& p) {
532 WriteParam(m, p.a);
533 WriteParam(m, p.b);
535 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
536 return (ReadParam(m, iter, &r->a) &&
537 ReadParam(m, iter, &r->b));
539 static void Log(const param_type& p, std::string* l) {
540 LogParam(p.a, l);
541 l->append(", ");
542 LogParam(p.b, l);
546 template <class A, class B, class C>
547 struct ParamTraits< Tuple3<A, B, C> > {
548 typedef Tuple3<A, B, C> param_type;
549 static void Write(Message* m, const param_type& p) {
550 WriteParam(m, p.a);
551 WriteParam(m, p.b);
552 WriteParam(m, p.c);
554 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
555 return (ReadParam(m, iter, &r->a) &&
556 ReadParam(m, iter, &r->b) &&
557 ReadParam(m, iter, &r->c));
559 static void Log(const param_type& p, std::string* l) {
560 LogParam(p.a, l);
561 l->append(", ");
562 LogParam(p.b, l);
563 l->append(", ");
564 LogParam(p.c, l);
568 template <class A, class B, class C, class D>
569 struct ParamTraits< Tuple4<A, B, C, D> > {
570 typedef Tuple4<A, B, C, D> param_type;
571 static void Write(Message* m, const param_type& p) {
572 WriteParam(m, p.a);
573 WriteParam(m, p.b);
574 WriteParam(m, p.c);
575 WriteParam(m, p.d);
577 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
578 return (ReadParam(m, iter, &r->a) &&
579 ReadParam(m, iter, &r->b) &&
580 ReadParam(m, iter, &r->c) &&
581 ReadParam(m, iter, &r->d));
583 static void Log(const param_type& p, std::string* l) {
584 LogParam(p.a, l);
585 l->append(", ");
586 LogParam(p.b, l);
587 l->append(", ");
588 LogParam(p.c, l);
589 l->append(", ");
590 LogParam(p.d, l);
594 template <class A, class B, class C, class D, class E>
595 struct ParamTraits< Tuple5<A, B, C, D, E> > {
596 typedef Tuple5<A, B, C, D, E> param_type;
597 static void Write(Message* m, const param_type& p) {
598 WriteParam(m, p.a);
599 WriteParam(m, p.b);
600 WriteParam(m, p.c);
601 WriteParam(m, p.d);
602 WriteParam(m, p.e);
604 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
605 return (ReadParam(m, iter, &r->a) &&
606 ReadParam(m, iter, &r->b) &&
607 ReadParam(m, iter, &r->c) &&
608 ReadParam(m, iter, &r->d) &&
609 ReadParam(m, iter, &r->e));
611 static void Log(const param_type& p, std::string* l) {
612 LogParam(p.a, l);
613 l->append(", ");
614 LogParam(p.b, l);
615 l->append(", ");
616 LogParam(p.c, l);
617 l->append(", ");
618 LogParam(p.d, l);
619 l->append(", ");
620 LogParam(p.e, l);
624 template<class P>
625 struct ParamTraits<ScopedVector<P> > {
626 typedef ScopedVector<P> param_type;
627 static void Write(Message* m, const param_type& p) {
628 WriteParam(m, static_cast<int>(p.size()));
629 for (size_t i = 0; i < p.size(); i++)
630 WriteParam(m, *p[i]);
632 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
633 int size = 0;
634 if (!m->ReadLength(iter, &size))
635 return false;
636 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
637 return false;
638 r->resize(size);
639 for (int i = 0; i < size; i++) {
640 (*r)[i] = new P();
641 if (!ReadParam(m, iter, (*r)[i]))
642 return false;
644 return true;
646 static void Log(const param_type& p, std::string* l) {
647 for (size_t i = 0; i < p.size(); ++i) {
648 if (i != 0)
649 l->append(" ");
650 LogParam(*p[i], l);
655 // IPC types ParamTraits -------------------------------------------------------
657 // A ChannelHandle is basically a platform-inspecific wrapper around the
658 // fact that IPC endpoints are handled specially on POSIX. See above comments
659 // on FileDescriptor for more background.
660 template<>
661 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
662 typedef ChannelHandle param_type;
663 static void Write(Message* m, const param_type& p);
664 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
665 static void Log(const param_type& p, std::string* l);
668 template <>
669 struct IPC_EXPORT ParamTraits<LogData> {
670 typedef LogData param_type;
671 static void Write(Message* m, const param_type& p);
672 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
673 static void Log(const param_type& p, std::string* l);
676 template <>
677 struct IPC_EXPORT ParamTraits<Message> {
678 static void Write(Message* m, const Message& p);
679 static bool Read(const Message* m, PickleIterator* iter, Message* r);
680 static void Log(const Message& p, std::string* l);
683 // Windows ParamTraits ---------------------------------------------------------
685 #if defined(OS_WIN)
686 template <>
687 struct IPC_EXPORT ParamTraits<HANDLE> {
688 typedef HANDLE param_type;
689 static void Write(Message* m, const param_type& p);
690 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
691 static void Log(const param_type& p, std::string* l);
694 template <>
695 struct IPC_EXPORT ParamTraits<LOGFONT> {
696 typedef LOGFONT param_type;
697 static void Write(Message* m, const param_type& p);
698 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
699 static void Log(const param_type& p, std::string* l);
702 template <>
703 struct IPC_EXPORT ParamTraits<MSG> {
704 typedef MSG param_type;
705 static void Write(Message* m, const param_type& p);
706 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
707 static void Log(const param_type& p, std::string* l);
709 #endif // defined(OS_WIN)
711 //-----------------------------------------------------------------------------
712 // Generic message subclasses
714 // Used for asynchronous messages.
715 template <class ParamType>
716 class MessageSchema {
717 public:
718 typedef ParamType Param;
719 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
721 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
722 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
725 // defined in ipc_logging.cc
726 IPC_EXPORT void GenerateLogData(const std::string& channel,
727 const Message& message,
728 LogData* data, bool get_params);
731 #if defined(IPC_MESSAGE_LOG_ENABLED)
732 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
733 const std::string& output_params = msg->output_params();
734 if (!l->empty() && !output_params.empty())
735 l->append(", ");
737 l->append(output_params);
740 template <class ReplyParamType>
741 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
742 const Message* msg) {
743 if (msg->received_time() != 0) {
744 std::string output_params;
745 LogParam(reply_params, &output_params);
746 msg->set_output_params(output_params);
750 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
751 if (msg->sent_time()) {
752 // Don't log the sync message after dispatch, as we don't have the
753 // output parameters at that point. Instead, save its data and log it
754 // with the outgoing reply message when it's sent.
755 LogData* data = new LogData;
756 GenerateLogData("", *msg, data, true);
757 msg->set_dont_log();
758 reply->set_sync_log_data(data);
761 #else
762 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
764 template <class ReplyParamType>
765 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
766 const Message* msg) {}
768 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
769 #endif
771 // This class assumes that its template argument is a RefTuple (a Tuple with
772 // reference elements). This would go into ipc_message_utils_impl.h, but it is
773 // also used by chrome_frame.
774 template <class RefTuple>
775 class ParamDeserializer : public MessageReplyDeserializer {
776 public:
777 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
779 bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
780 return ReadParam(&msg, &iter, &out_);
783 RefTuple out_;
786 // Used for synchronous messages.
787 template <class SendParamType, class ReplyParamType>
788 class SyncMessageSchema {
789 public:
790 typedef SendParamType SendParam;
791 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
792 typedef ReplyParamType ReplyParam;
794 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
795 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
796 static bool ReadReplyParam(
797 const Message* msg,
798 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
800 template<class T, class S, class Method>
801 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
802 const Message* msg, T* obj, S* sender,
803 Method func) {
804 Message* reply = SyncMessage::GenerateReply(msg);
805 if (ok) {
806 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
807 DispatchToMethod(obj, func, send_params, &reply_params);
808 WriteParam(reply, reply_params);
809 LogReplyParamsToMessage(reply_params, msg);
810 } else {
811 NOTREACHED() << "Error deserializing message " << msg->type();
812 reply->set_reply_error();
814 sender->Send(reply);
815 return ok;
818 template<class T, class Method>
819 static bool DispatchDelayReplyWithSendParams(bool ok,
820 const SendParam& send_params,
821 const Message* msg, T* obj,
822 Method func) {
823 Message* reply = SyncMessage::GenerateReply(msg);
824 if (ok) {
825 Tuple1<Message&> t = MakeRefTuple(*reply);
826 ConnectMessageAndReply(msg, reply);
827 DispatchToMethod(obj, func, send_params, &t);
828 } else {
829 NOTREACHED() << "Error deserializing message " << msg->type();
830 reply->set_reply_error();
831 obj->Send(reply);
833 return ok;
836 template<typename TA>
837 static void WriteReplyParams(Message* reply, TA a) {
838 ReplyParam p(a);
839 WriteParam(reply, p);
842 template<typename TA, typename TB>
843 static void WriteReplyParams(Message* reply, TA a, TB b) {
844 ReplyParam p(a, b);
845 WriteParam(reply, p);
848 template<typename TA, typename TB, typename TC>
849 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
850 ReplyParam p(a, b, c);
851 WriteParam(reply, p);
854 template<typename TA, typename TB, typename TC, typename TD>
855 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
856 ReplyParam p(a, b, c, d);
857 WriteParam(reply, p);
860 template<typename TA, typename TB, typename TC, typename TD, typename TE>
861 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
862 ReplyParam p(a, b, c, d, e);
863 WriteParam(reply, p);
867 } // namespace IPC
869 #endif // IPC_IPC_MESSAGE_UTILS_H_