- add sources.
[platform/framework/web/crosswalk.git] / src / ipc / ipc_message_utils.h
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.
4
5 #ifndef IPC_IPC_MESSAGE_UTILS_H_
6 #define IPC_IPC_MESSAGE_UTILS_H_
7
8 #include <algorithm>
9 #include <map>
10 #include <set>
11 #include <string>
12 #include <vector>
13
14 #include "base/format_macros.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/platform_file.h"
17 #include "base/strings/string16.h"
18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.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"
24
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
47
48 namespace base {
49 class DictionaryValue;
50 class FilePath;
51 class ListValue;
52 class NullableString16;
53 class Time;
54 class TimeDelta;
55 class TimeTicks;
56 struct FileDescriptor;
57 }
58
59 namespace IPC {
60
61 struct ChannelHandle;
62
63 // -----------------------------------------------------------------------------
64 // How we send IPC message logs across channels.
65 struct IPC_EXPORT LogData {
66   LogData();
67   ~LogData();
68
69   std::string channel;
70   int32 routing_id;
71   uint32 type;  // "User-defined" message type, from ipc_message.h.
72   std::string flags;
73   int64 sent;  // Time that the message was sent (i.e. at Send()).
74   int64 receive;  // Time before it was dispatched (i.e. before calling
75                   // OnMessageReceived).
76   int64 dispatch;  // Time after it was dispatched (i.e. after calling
77                    // OnMessageReceived).
78   std::string message_name;
79   std::string params;
80 };
81
82 //-----------------------------------------------------------------------------
83
84 // A dummy struct to place first just to allow leading commas for all
85 // members in the macro-generated constructor initializer lists.
86 struct NoParams {
87 };
88
89 template <class P>
90 static inline void WriteParam(Message* m, const P& p) {
91   typedef typename SimilarTypeTraits<P>::Type Type;
92   ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
93 }
94
95 template <class P>
96 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m,
97                                                 PickleIterator* iter,
98                                                 P* p) {
99   typedef typename SimilarTypeTraits<P>::Type Type;
100   return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
101 }
102
103 template <class P>
104 static inline void LogParam(const P& p, std::string* l) {
105   typedef typename SimilarTypeTraits<P>::Type Type;
106   ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
107 }
108
109 // Primitive ParamTraits -------------------------------------------------------
110
111 template <>
112 struct ParamTraits<bool> {
113   typedef bool param_type;
114   static void Write(Message* m, const param_type& p) {
115     m->WriteBool(p);
116   }
117   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
118     return m->ReadBool(iter, r);
119   }
120   IPC_EXPORT static void Log(const param_type& p, std::string* l);
121 };
122
123 template <>
124 struct IPC_EXPORT ParamTraits<unsigned char> {
125   typedef unsigned char param_type;
126   static void Write(Message* m, const param_type& p);
127   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
128   static void Log(const param_type& p, std::string* l);
129 };
130
131 template <>
132 struct IPC_EXPORT ParamTraits<unsigned short> {
133   typedef unsigned short param_type;
134   static void Write(Message* m, const param_type& p);
135   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
136   static void Log(const param_type& p, std::string* l);
137 };
138
139 template <>
140 struct ParamTraits<int> {
141   typedef int param_type;
142   static void Write(Message* m, const param_type& p) {
143     m->WriteInt(p);
144   }
145   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
146     return m->ReadInt(iter, r);
147   }
148   IPC_EXPORT static void Log(const param_type& p, std::string* l);
149 };
150
151 template <>
152 struct ParamTraits<unsigned int> {
153   typedef unsigned int param_type;
154   static void Write(Message* m, const param_type& p) {
155     m->WriteInt(p);
156   }
157   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
158     return m->ReadInt(iter, reinterpret_cast<int*>(r));
159   }
160   IPC_EXPORT static void Log(const param_type& p, std::string* l);
161 };
162
163 template <>
164 struct ParamTraits<long> {
165   typedef long param_type;
166   static void Write(Message* m, const param_type& p) {
167     m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
168   }
169   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
170     return m->ReadLong(iter, r);
171   }
172   IPC_EXPORT static void Log(const param_type& p, std::string* l);
173 };
174
175 template <>
176 struct ParamTraits<unsigned long> {
177   typedef unsigned long param_type;
178   static void Write(Message* m, const param_type& p) {
179     m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
180   }
181   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
182     return m->ReadLong(iter, reinterpret_cast<long*>(r));
183   }
184   IPC_EXPORT static void Log(const param_type& p, std::string* l);
185 };
186
187 template <>
188 struct ParamTraits<long long> {
189   typedef long long param_type;
190   static void Write(Message* m, const param_type& p) {
191     m->WriteInt64(static_cast<int64>(p));
192   }
193   static bool Read(const Message* m, PickleIterator* iter,
194                    param_type* r) {
195     return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
196   }
197   IPC_EXPORT static void Log(const param_type& p, std::string* l);
198 };
199
200 template <>
201 struct ParamTraits<unsigned long long> {
202   typedef unsigned long long param_type;
203   static void Write(Message* m, const param_type& p) {
204     m->WriteInt64(p);
205   }
206   static bool Read(const Message* m, PickleIterator* iter,
207                    param_type* r) {
208     return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
209   }
210   IPC_EXPORT static void Log(const param_type& p, std::string* l);
211 };
212
213 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values.  Clients
214 // should be sure to check the sanity of these values after receiving them over
215 // IPC.
216 template <>
217 struct IPC_EXPORT ParamTraits<float> {
218   typedef float param_type;
219   static void Write(Message* m, const param_type& p) {
220     m->WriteFloat(p);
221   }
222   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
223     return m->ReadFloat(iter, r);
224   }
225   static void Log(const param_type& p, std::string* l);
226 };
227
228 template <>
229 struct IPC_EXPORT ParamTraits<double> {
230   typedef double param_type;
231   static void Write(Message* m, const param_type& p);
232   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
233   static void Log(const param_type& p, std::string* l);
234 };
235
236 // STL ParamTraits -------------------------------------------------------------
237
238 template <>
239 struct ParamTraits<std::string> {
240   typedef std::string param_type;
241   static void Write(Message* m, const param_type& p) {
242     m->WriteString(p);
243   }
244   static bool Read(const Message* m, PickleIterator* iter,
245                    param_type* r) {
246     return m->ReadString(iter, r);
247   }
248   IPC_EXPORT static void Log(const param_type& p, std::string* l);
249 };
250
251 template <>
252 struct ParamTraits<std::wstring> {
253   typedef std::wstring param_type;
254   static void Write(Message* m, const param_type& p) {
255     m->WriteWString(p);
256   }
257   static bool Read(const Message* m, PickleIterator* iter,
258                    param_type* r) {
259     return m->ReadWString(iter, r);
260   }
261   IPC_EXPORT static void Log(const param_type& p, std::string* l);
262 };
263
264 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
265 // need this trait.
266 #if !defined(WCHAR_T_IS_UTF16)
267 template <>
268 struct ParamTraits<string16> {
269   typedef string16 param_type;
270   static void Write(Message* m, const param_type& p) {
271     m->WriteString16(p);
272   }
273   static bool Read(const Message* m, PickleIterator* iter,
274                    param_type* r) {
275     return m->ReadString16(iter, r);
276   }
277   IPC_EXPORT static void Log(const param_type& p, std::string* l);
278 };
279 #endif
280
281 template <>
282 struct IPC_EXPORT ParamTraits<std::vector<char> > {
283   typedef std::vector<char> param_type;
284   static void Write(Message* m, const param_type& p);
285   static bool Read(const Message*, PickleIterator* iter, param_type* r);
286   static void Log(const param_type& p, std::string* l);
287 };
288
289 template <>
290 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
291   typedef std::vector<unsigned char> param_type;
292   static void Write(Message* m, const param_type& p);
293   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
294   static void Log(const param_type& p, std::string* l);
295 };
296
297 template <>
298 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
299   typedef std::vector<bool> param_type;
300   static void Write(Message* m, const param_type& p);
301   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
302   static void Log(const param_type& p, std::string* l);
303 };
304
305 template <class P>
306 struct ParamTraits<std::vector<P> > {
307   typedef std::vector<P> param_type;
308   static void Write(Message* m, const param_type& p) {
309     WriteParam(m, static_cast<int>(p.size()));
310     for (size_t i = 0; i < p.size(); i++)
311       WriteParam(m, p[i]);
312   }
313   static bool Read(const Message* m, PickleIterator* iter,
314                    param_type* r) {
315     int size;
316     // ReadLength() checks for < 0 itself.
317     if (!m->ReadLength(iter, &size))
318       return false;
319     // Resizing beforehand is not safe, see BUG 1006367 for details.
320     if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
321       return false;
322     r->resize(size);
323     for (int i = 0; i < size; i++) {
324       if (!ReadParam(m, iter, &(*r)[i]))
325         return false;
326     }
327     return true;
328   }
329   static void Log(const param_type& p, std::string* l) {
330     for (size_t i = 0; i < p.size(); ++i) {
331       if (i != 0)
332         l->append(" ");
333       LogParam((p[i]), l);
334     }
335   }
336 };
337
338 template <class P>
339 struct ParamTraits<std::set<P> > {
340   typedef std::set<P> param_type;
341   static void Write(Message* m, const param_type& p) {
342     WriteParam(m, static_cast<int>(p.size()));
343     typename param_type::const_iterator iter;
344     for (iter = p.begin(); iter != p.end(); ++iter)
345       WriteParam(m, *iter);
346   }
347   static bool Read(const Message* m, PickleIterator* iter,
348                    param_type* r) {
349     int size;
350     if (!m->ReadLength(iter, &size))
351       return false;
352     for (int i = 0; i < size; ++i) {
353       P item;
354       if (!ReadParam(m, iter, &item))
355         return false;
356       r->insert(item);
357     }
358     return true;
359   }
360   static void Log(const param_type& p, std::string* l) {
361     l->append("<std::set>");
362   }
363 };
364
365 template <class K, class V>
366 struct ParamTraits<std::map<K, V> > {
367   typedef std::map<K, V> param_type;
368   static void Write(Message* m, const param_type& p) {
369     WriteParam(m, static_cast<int>(p.size()));
370     typename param_type::const_iterator iter;
371     for (iter = p.begin(); iter != p.end(); ++iter) {
372       WriteParam(m, iter->first);
373       WriteParam(m, iter->second);
374     }
375   }
376   static bool Read(const Message* m, PickleIterator* iter,
377                    param_type* r) {
378     int size;
379     if (!ReadParam(m, iter, &size) || size < 0)
380       return false;
381     for (int i = 0; i < size; ++i) {
382       K k;
383       if (!ReadParam(m, iter, &k))
384         return false;
385       V& value = (*r)[k];
386       if (!ReadParam(m, iter, &value))
387         return false;
388     }
389     return true;
390   }
391   static void Log(const param_type& p, std::string* l) {
392     l->append("<std::map>");
393   }
394 };
395
396 template <class A, class B>
397 struct ParamTraits<std::pair<A, B> > {
398   typedef std::pair<A, B> param_type;
399   static void Write(Message* m, const param_type& p) {
400     WriteParam(m, p.first);
401     WriteParam(m, p.second);
402   }
403   static bool Read(const Message* m, PickleIterator* iter,
404                    param_type* r) {
405     return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
406   }
407   static void Log(const param_type& p, std::string* l) {
408     l->append("(");
409     LogParam(p.first, l);
410     l->append(", ");
411     LogParam(p.second, l);
412     l->append(")");
413   }
414 };
415
416 // Base ParamTraits ------------------------------------------------------------
417
418 template <>
419 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
420   typedef base::DictionaryValue param_type;
421   static void Write(Message* m, const param_type& p);
422   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
423   static void Log(const param_type& p, std::string* l);
424 };
425
426 #if defined(OS_POSIX)
427 // FileDescriptors may be serialised over IPC channels on POSIX. On the
428 // receiving side, the FileDescriptor is a valid duplicate of the file
429 // descriptor which was transmitted: *it is not just a copy of the integer like
430 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
431 // this case, the receiving end will see a value of -1. *Zero is a valid file
432 // descriptor*.
433 //
434 // The received file descriptor will have the |auto_close| flag set to true. The
435 // code which handles the message is responsible for taking ownership of it.
436 // File descriptors are OS resources and must be closed when no longer needed.
437 //
438 // When sending a file descriptor, the file descriptor must be valid at the time
439 // of transmission. Since transmission is not synchronous, one should consider
440 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
441 // flag, which causes the file descriptor to be closed after writing.
442 template<>
443 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
444   typedef base::FileDescriptor param_type;
445   static void Write(Message* m, const param_type& p);
446   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
447   static void Log(const param_type& p, std::string* l);
448 };
449 #endif  // defined(OS_POSIX)
450
451 template <>
452 struct IPC_EXPORT ParamTraits<base::FilePath> {
453   typedef base::FilePath param_type;
454   static void Write(Message* m, const param_type& p);
455   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
456   static void Log(const param_type& p, std::string* l);
457 };
458
459 template <>
460 struct IPC_EXPORT ParamTraits<base::ListValue> {
461   typedef base::ListValue param_type;
462   static void Write(Message* m, const param_type& p);
463   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
464   static void Log(const param_type& p, std::string* l);
465 };
466
467 template <>
468 struct IPC_EXPORT ParamTraits<base::NullableString16> {
469   typedef base::NullableString16 param_type;
470   static void Write(Message* m, const param_type& p);
471   static bool Read(const Message* m, PickleIterator* iter,
472                    param_type* r);
473   static void Log(const param_type& p, std::string* l);
474 };
475
476 template <>
477 struct IPC_EXPORT ParamTraits<base::PlatformFileInfo> {
478   typedef base::PlatformFileInfo param_type;
479   static void Write(Message* m, const param_type& p);
480   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
481   static void Log(const param_type& p, std::string* l);
482 };
483
484 template <>
485 struct SimilarTypeTraits<base::PlatformFileError> {
486   typedef int Type;
487 };
488
489 #if defined(OS_WIN)
490 template <>
491 struct SimilarTypeTraits<HWND> {
492   typedef HANDLE Type;
493 };
494 #endif  // defined(OS_WIN)
495
496 template <>
497 struct IPC_EXPORT ParamTraits<base::Time> {
498   typedef base::Time param_type;
499   static void Write(Message* m, const param_type& p);
500   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
501   static void Log(const param_type& p, std::string* l);
502 };
503
504 template <>
505 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
506   typedef base::TimeDelta param_type;
507   static void Write(Message* m, const param_type& p);
508   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
509   static void Log(const param_type& p, std::string* l);
510 };
511
512 template <>
513 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
514   typedef base::TimeTicks param_type;
515   static void Write(Message* m, const param_type& p);
516   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
517   static void Log(const param_type& p, std::string* l);
518 };
519
520 template <>
521 struct ParamTraits<Tuple0> {
522   typedef Tuple0 param_type;
523   static void Write(Message* m, const param_type& p) {
524   }
525   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
526     return true;
527   }
528   static void Log(const param_type& p, std::string* l) {
529   }
530 };
531
532 template <class A>
533 struct ParamTraits< Tuple1<A> > {
534   typedef Tuple1<A> param_type;
535   static void Write(Message* m, const param_type& p) {
536     WriteParam(m, p.a);
537   }
538   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
539     return ReadParam(m, iter, &r->a);
540   }
541   static void Log(const param_type& p, std::string* l) {
542     LogParam(p.a, l);
543   }
544 };
545
546 template <class A, class B>
547 struct ParamTraits< Tuple2<A, B> > {
548   typedef Tuple2<A, B> param_type;
549   static void Write(Message* m, const param_type& p) {
550     WriteParam(m, p.a);
551     WriteParam(m, p.b);
552   }
553   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
554     return (ReadParam(m, iter, &r->a) &&
555             ReadParam(m, iter, &r->b));
556   }
557   static void Log(const param_type& p, std::string* l) {
558     LogParam(p.a, l);
559     l->append(", ");
560     LogParam(p.b, l);
561   }
562 };
563
564 template <class A, class B, class C>
565 struct ParamTraits< Tuple3<A, B, C> > {
566   typedef Tuple3<A, B, C> param_type;
567   static void Write(Message* m, const param_type& p) {
568     WriteParam(m, p.a);
569     WriteParam(m, p.b);
570     WriteParam(m, p.c);
571   }
572   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
573     return (ReadParam(m, iter, &r->a) &&
574             ReadParam(m, iter, &r->b) &&
575             ReadParam(m, iter, &r->c));
576   }
577   static void Log(const param_type& p, std::string* l) {
578     LogParam(p.a, l);
579     l->append(", ");
580     LogParam(p.b, l);
581     l->append(", ");
582     LogParam(p.c, l);
583   }
584 };
585
586 template <class A, class B, class C, class D>
587 struct ParamTraits< Tuple4<A, B, C, D> > {
588   typedef Tuple4<A, B, C, D> param_type;
589   static void Write(Message* m, const param_type& p) {
590     WriteParam(m, p.a);
591     WriteParam(m, p.b);
592     WriteParam(m, p.c);
593     WriteParam(m, p.d);
594   }
595   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
596     return (ReadParam(m, iter, &r->a) &&
597             ReadParam(m, iter, &r->b) &&
598             ReadParam(m, iter, &r->c) &&
599             ReadParam(m, iter, &r->d));
600   }
601   static void Log(const param_type& p, std::string* l) {
602     LogParam(p.a, l);
603     l->append(", ");
604     LogParam(p.b, l);
605     l->append(", ");
606     LogParam(p.c, l);
607     l->append(", ");
608     LogParam(p.d, l);
609   }
610 };
611
612 template <class A, class B, class C, class D, class E>
613 struct ParamTraits< Tuple5<A, B, C, D, E> > {
614   typedef Tuple5<A, B, C, D, E> param_type;
615   static void Write(Message* m, const param_type& p) {
616     WriteParam(m, p.a);
617     WriteParam(m, p.b);
618     WriteParam(m, p.c);
619     WriteParam(m, p.d);
620     WriteParam(m, p.e);
621   }
622   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
623     return (ReadParam(m, iter, &r->a) &&
624             ReadParam(m, iter, &r->b) &&
625             ReadParam(m, iter, &r->c) &&
626             ReadParam(m, iter, &r->d) &&
627             ReadParam(m, iter, &r->e));
628   }
629   static void Log(const param_type& p, std::string* l) {
630     LogParam(p.a, l);
631     l->append(", ");
632     LogParam(p.b, l);
633     l->append(", ");
634     LogParam(p.c, l);
635     l->append(", ");
636     LogParam(p.d, l);
637     l->append(", ");
638     LogParam(p.e, l);
639   }
640 };
641
642 template<class P>
643 struct ParamTraits<ScopedVector<P> > {
644   typedef ScopedVector<P> param_type;
645   static void Write(Message* m, const param_type& p) {
646     WriteParam(m, static_cast<int>(p.size()));
647     for (size_t i = 0; i < p.size(); i++)
648       WriteParam(m, *p[i]);
649   }
650   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
651     int size = 0;
652     if (!m->ReadLength(iter, &size))
653       return false;
654     if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
655       return false;
656     r->resize(size);
657     for (int i = 0; i < size; i++) {
658       (*r)[i] = new P();
659       if (!ReadParam(m, iter, (*r)[i]))
660         return false;
661     }
662     return true;
663   }
664   static void Log(const param_type& p, std::string* l) {
665     for (size_t i = 0; i < p.size(); ++i) {
666       if (i != 0)
667         l->append(" ");
668       LogParam(*p[i], l);
669     }
670   }
671 };
672
673 // IPC types ParamTraits -------------------------------------------------------
674
675 // A ChannelHandle is basically a platform-inspecific wrapper around the
676 // fact that IPC endpoints are handled specially on POSIX.  See above comments
677 // on FileDescriptor for more background.
678 template<>
679 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
680   typedef ChannelHandle param_type;
681   static void Write(Message* m, const param_type& p);
682   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
683   static void Log(const param_type& p, std::string* l);
684 };
685
686 template <>
687 struct IPC_EXPORT ParamTraits<LogData> {
688   typedef LogData 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);
692 };
693
694 template <>
695 struct IPC_EXPORT ParamTraits<Message> {
696   static void Write(Message* m, const Message& p);
697   static bool Read(const Message* m, PickleIterator* iter, Message* r);
698   static void Log(const Message& p, std::string* l);
699 };
700
701 // Windows ParamTraits ---------------------------------------------------------
702
703 #if defined(OS_WIN)
704 template <>
705 struct IPC_EXPORT ParamTraits<HANDLE> {
706   typedef HANDLE param_type;
707   static void Write(Message* m, const param_type& p);
708   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
709   static void Log(const param_type& p, std::string* l);
710 };
711
712 template <>
713 struct IPC_EXPORT ParamTraits<LOGFONT> {
714   typedef LOGFONT param_type;
715   static void Write(Message* m, const param_type& p);
716   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
717   static void Log(const param_type& p, std::string* l);
718 };
719
720 template <>
721 struct IPC_EXPORT ParamTraits<MSG> {
722   typedef MSG param_type;
723   static void Write(Message* m, const param_type& p);
724   static bool Read(const Message* m, PickleIterator* iter, param_type* r);
725   static void Log(const param_type& p, std::string* l);
726 };
727 #endif  // defined(OS_WIN)
728
729 //-----------------------------------------------------------------------------
730 // Generic message subclasses
731
732 // Used for asynchronous messages.
733 template <class ParamType>
734 class MessageSchema {
735  public:
736   typedef ParamType Param;
737   typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
738
739   static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
740   static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
741 };
742
743 // defined in ipc_logging.cc
744 IPC_EXPORT void GenerateLogData(const std::string& channel,
745                                 const Message& message,
746                                 LogData* data, bool get_params);
747
748
749 #if defined(IPC_MESSAGE_LOG_ENABLED)
750 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
751   const std::string& output_params = msg->output_params();
752   if (!l->empty() && !output_params.empty())
753     l->append(", ");
754
755   l->append(output_params);
756 }
757
758 template <class ReplyParamType>
759 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
760                                     const Message* msg) {
761   if (msg->received_time() != 0) {
762     std::string output_params;
763     LogParam(reply_params, &output_params);
764     msg->set_output_params(output_params);
765   }
766 }
767
768 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
769   if (msg->sent_time()) {
770     // Don't log the sync message after dispatch, as we don't have the
771     // output parameters at that point.  Instead, save its data and log it
772     // with the outgoing reply message when it's sent.
773     LogData* data = new LogData;
774     GenerateLogData("", *msg, data, true);
775     msg->set_dont_log();
776     reply->set_sync_log_data(data);
777   }
778 }
779 #else
780 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
781
782 template <class ReplyParamType>
783 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
784                                     const Message* msg) {}
785
786 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
787 #endif
788
789 // This class assumes that its template argument is a RefTuple (a Tuple with
790 // reference elements). This would go into ipc_message_utils_impl.h, but it is
791 // also used by chrome_frame.
792 template <class RefTuple>
793 class ParamDeserializer : public MessageReplyDeserializer {
794  public:
795   explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
796
797   bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
798     return ReadParam(&msg, &iter, &out_);
799   }
800
801   RefTuple out_;
802 };
803
804 // Used for synchronous messages.
805 template <class SendParamType, class ReplyParamType>
806 class SyncMessageSchema {
807  public:
808   typedef SendParamType SendParam;
809   typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
810   typedef ReplyParamType ReplyParam;
811
812   static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
813   static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
814   static bool ReadReplyParam(
815       const Message* msg,
816       typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
817
818   template<class T, class S, class Method>
819   static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
820                                      const Message* msg, T* obj, S* sender,
821                                      Method func) {
822     Message* reply = SyncMessage::GenerateReply(msg);
823     if (ok) {
824       typename TupleTypes<ReplyParam>::ValueTuple reply_params;
825       DispatchToMethod(obj, func, send_params, &reply_params);
826       WriteParam(reply, reply_params);
827       LogReplyParamsToMessage(reply_params, msg);
828     } else {
829       NOTREACHED() << "Error deserializing message " << msg->type();
830       reply->set_reply_error();
831     }
832     sender->Send(reply);
833     return ok;
834   }
835
836   template<class T, class Method>
837   static bool DispatchDelayReplyWithSendParams(bool ok,
838                                                const SendParam& send_params,
839                                                const Message* msg, T* obj,
840                                                Method func) {
841     Message* reply = SyncMessage::GenerateReply(msg);
842     if (ok) {
843       Tuple1<Message&> t = MakeRefTuple(*reply);
844       ConnectMessageAndReply(msg, reply);
845       DispatchToMethod(obj, func, send_params, &t);
846     } else {
847       NOTREACHED() << "Error deserializing message " << msg->type();
848       reply->set_reply_error();
849       obj->Send(reply);
850     }
851     return ok;
852   }
853
854   template<typename TA>
855   static void WriteReplyParams(Message* reply, TA a) {
856     ReplyParam p(a);
857     WriteParam(reply, p);
858   }
859
860   template<typename TA, typename TB>
861   static void WriteReplyParams(Message* reply, TA a, TB b) {
862     ReplyParam p(a, b);
863     WriteParam(reply, p);
864   }
865
866   template<typename TA, typename TB, typename TC>
867   static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
868     ReplyParam p(a, b, c);
869     WriteParam(reply, p);
870   }
871
872   template<typename TA, typename TB, typename TC, typename TD>
873   static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
874     ReplyParam p(a, b, c, d);
875     WriteParam(reply, p);
876   }
877
878   template<typename TA, typename TB, typename TC, typename TD, typename TE>
879   static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
880     ReplyParam p(a, b, c, d, e);
881     WriteParam(reply, p);
882   }
883 };
884
885 }  // namespace IPC
886
887 #endif  // IPC_IPC_MESSAGE_UTILS_H_