• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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"
26 
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));
40 #else
41 #define IPC_MSG_NOINLINE  __attribute__((noinline));
42 #endif
43 #elif defined(COMPILER_MSVC)
44 // MSVC++ doesn't do this.
45 #define IPC_MSG_NOINLINE
46 #else
47 #error "Please add the noinline property for your new compiler here."
48 #endif
49 
50 namespace base {
51 class DictionaryValue;
52 class FilePath;
53 class ListValue;
54 class NullableString16;
55 class Time;
56 class TimeDelta;
57 class TimeTicks;
58 struct FileDescriptor;
59 }
60 
61 namespace IPC {
62 
63 struct ChannelHandle;
64 
65 // -----------------------------------------------------------------------------
66 // How we send IPC message logs across channels.
67 struct IPC_EXPORT LogData {
68   LogData();
69   ~LogData();
70 
71   std::string channel;
72   int32 routing_id;
73   uint32 type;  // "User-defined" message type, from ipc_message.h.
74   std::string flags;
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;
81   std::string params;
82 };
83 
84 //-----------------------------------------------------------------------------
85 
86 // A dummy struct to place first just to allow leading commas for all
87 // members in the macro-generated constructor initializer lists.
88 struct NoParams {
89 };
90 
91 template <class P>
WriteParam(Message * m,const P & p)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));
95 }
96 
97 template <class P>
ReadParam(const Message * m,PickleIterator * iter,P * p)98 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m,
99                                                 PickleIterator* iter,
100                                                 P* p) {
101   typedef typename SimilarTypeTraits<P>::Type Type;
102   return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
103 }
104 
105 template <class P>
LogParam(const P & p,std::string * l)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);
109 }
110 
111 // Primitive ParamTraits -------------------------------------------------------
112 
113 template <>
114 struct ParamTraits<bool> {
115   typedef bool param_type;
116   static void Write(Message* m, const param_type& p) {
117     m->WriteBool(p);
118   }
119   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
120     return m->ReadBool(iter, r);
121   }
122   IPC_EXPORT static void Log(const param_type& p, std::string* l);
123 };
124 
125 template <>
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);
131 };
132 
133 template <>
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);
139 };
140 
141 template <>
142 struct ParamTraits<int> {
143   typedef int param_type;
144   static void Write(Message* m, const param_type& p) {
145     m->WriteInt(p);
146   }
147   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
148     return m->ReadInt(iter, r);
149   }
150   IPC_EXPORT static void Log(const param_type& p, std::string* l);
151 };
152 
153 template <>
154 struct ParamTraits<unsigned int> {
155   typedef unsigned int param_type;
156   static void Write(Message* m, const param_type& p) {
157     m->WriteInt(p);
158   }
159   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
160     return m->ReadInt(iter, reinterpret_cast<int*>(r));
161   }
162   IPC_EXPORT static void Log(const param_type& p, std::string* l);
163 };
164 
165 template <>
166 struct ParamTraits<long> {
167   typedef long param_type;
168   static void Write(Message* m, const param_type& p) {
169     m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
170   }
171   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
172     return m->ReadLong(iter, r);
173   }
174   IPC_EXPORT static void Log(const param_type& p, std::string* l);
175 };
176 
177 template <>
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);
182   }
183   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
184     return m->ReadLong(iter, reinterpret_cast<long*>(r));
185   }
186   IPC_EXPORT static void Log(const param_type& p, std::string* l);
187 };
188 
189 template <>
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));
194   }
195   static bool Read(const Message* m, PickleIterator* iter,
196                    param_type* r) {
197     return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
198   }
199   IPC_EXPORT static void Log(const param_type& p, std::string* l);
200 };
201 
202 template <>
203 struct ParamTraits<unsigned long long> {
204   typedef unsigned long long param_type;
205   static void Write(Message* m, const param_type& p) {
206     m->WriteInt64(p);
207   }
208   static bool Read(const Message* m, PickleIterator* iter,
209                    param_type* r) {
210     return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
211   }
212   IPC_EXPORT static void Log(const param_type& p, std::string* l);
213 };
214 
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
217 // IPC.
218 template <>
219 struct IPC_EXPORT ParamTraits<float> {
220   typedef float param_type;
221   static void Write(Message* m, const param_type& p) {
222     m->WriteFloat(p);
223   }
224   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
225     return m->ReadFloat(iter, r);
226   }
227   static void Log(const param_type& p, std::string* l);
228 };
229 
230 template <>
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);
236 };
237 
238 // STL ParamTraits -------------------------------------------------------------
239 
240 template <>
241 struct ParamTraits<std::string> {
242   typedef std::string param_type;
243   static void Write(Message* m, const param_type& p) {
244     m->WriteString(p);
245   }
246   static bool Read(const Message* m, PickleIterator* iter,
247                    param_type* r) {
248     return m->ReadString(iter, r);
249   }
250   IPC_EXPORT static void Log(const param_type& p, std::string* l);
251 };
252 
253 template <>
254 struct ParamTraits<std::wstring> {
255   typedef std::wstring param_type;
256   static void Write(Message* m, const param_type& p) {
257     m->WriteWString(p);
258   }
259   static bool Read(const Message* m, PickleIterator* iter,
260                    param_type* r) {
261     return m->ReadWString(iter, r);
262   }
263   IPC_EXPORT static void Log(const param_type& p, std::string* l);
264 };
265 
266 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
267 // need this trait.
268 #if !defined(WCHAR_T_IS_UTF16)
269 template <>
270 struct ParamTraits<base::string16> {
271   typedef base::string16 param_type;
272   static void Write(Message* m, const param_type& p) {
273     m->WriteString16(p);
274   }
275   static bool Read(const Message* m, PickleIterator* iter,
276                    param_type* r) {
277     return m->ReadString16(iter, r);
278   }
279   IPC_EXPORT static void Log(const param_type& p, std::string* l);
280 };
281 #endif
282 
283 template <>
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);
289 };
290 
291 template <>
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);
297 };
298 
299 template <>
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);
305 };
306 
307 template <class P>
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++)
313       WriteParam(m, p[i]);
314   }
315   static bool Read(const Message* m, PickleIterator* iter,
316                    param_type* r) {
317     int size;
318     // ReadLength() checks for < 0 itself.
319     if (!m->ReadLength(iter, &size))
320       return false;
321     // Resizing beforehand is not safe, see BUG 1006367 for details.
322     if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
323       return false;
324     r->resize(size);
325     for (int i = 0; i < size; i++) {
326       if (!ReadParam(m, iter, &(*r)[i]))
327         return false;
328     }
329     return true;
330   }
331   static void Log(const param_type& p, std::string* l) {
332     for (size_t i = 0; i < p.size(); ++i) {
333       if (i != 0)
334         l->append(" ");
335       LogParam((p[i]), l);
336     }
337   }
338 };
339 
340 template <class P>
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);
348   }
349   static bool Read(const Message* m, PickleIterator* iter,
350                    param_type* r) {
351     int size;
352     if (!m->ReadLength(iter, &size))
353       return false;
354     for (int i = 0; i < size; ++i) {
355       P item;
356       if (!ReadParam(m, iter, &item))
357         return false;
358       r->insert(item);
359     }
360     return true;
361   }
362   static void Log(const param_type& p, std::string* l) {
363     l->append("<std::set>");
364   }
365 };
366 
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);
376     }
377   }
378   static bool Read(const Message* m, PickleIterator* iter,
379                    param_type* r) {
380     int size;
381     if (!ReadParam(m, iter, &size) || size < 0)
382       return false;
383     for (int i = 0; i < size; ++i) {
384       K k;
385       if (!ReadParam(m, iter, &k))
386         return false;
387       V& value = (*r)[k];
388       if (!ReadParam(m, iter, &value))
389         return false;
390     }
391     return true;
392   }
393   static void Log(const param_type& p, std::string* l) {
394     l->append("<std::map>");
395   }
396 };
397 
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);
404   }
405   static bool Read(const Message* m, PickleIterator* iter,
406                    param_type* r) {
407     return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
408   }
409   static void Log(const param_type& p, std::string* l) {
410     l->append("(");
411     LogParam(p.first, l);
412     l->append(", ");
413     LogParam(p.second, l);
414     l->append(")");
415   }
416 };
417 
418 // Base ParamTraits ------------------------------------------------------------
419 
420 template <>
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);
426 };
427 
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
434 // descriptor*.
435 //
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.
439 //
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.
444 template<>
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);
450 };
451 #endif  // defined(OS_POSIX)
452 
453 template <>
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);
459 };
460 
461 template <>
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);
467 };
468 
469 template <>
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,
474                    param_type* r);
475   static void Log(const param_type& p, std::string* l);
476 };
477 
478 template <>
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);
484 };
485 
486 template <>
487 struct SimilarTypeTraits<base::File::Error> {
488   typedef int Type;
489 };
490 
491 #if defined(OS_WIN)
492 template <>
493 struct SimilarTypeTraits<HWND> {
494   typedef HANDLE Type;
495 };
496 #endif  // defined(OS_WIN)
497 
498 template <>
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);
504 };
505 
506 template <>
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);
512 };
513 
514 template <>
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);
520 };
521 
522 template <>
523 struct ParamTraits<Tuple0> {
524   typedef Tuple0 param_type;
525   static void Write(Message* m, const param_type& p) {
526   }
527   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
528     return true;
529   }
530   static void Log(const param_type& p, std::string* l) {
531   }
532 };
533 
534 template <class A>
535 struct ParamTraits< Tuple1<A> > {
536   typedef Tuple1<A> param_type;
537   static void Write(Message* m, const param_type& p) {
538     WriteParam(m, p.a);
539   }
540   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
541     return ReadParam(m, iter, &r->a);
542   }
543   static void Log(const param_type& p, std::string* l) {
544     LogParam(p.a, l);
545   }
546 };
547 
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) {
552     WriteParam(m, p.a);
553     WriteParam(m, p.b);
554   }
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));
558   }
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   }
564 };
565 
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) {
570     WriteParam(m, p.a);
571     WriteParam(m, p.b);
572     WriteParam(m, p.c);
573   }
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));
578   }
579   static void Log(const param_type& p, std::string* l) {
580     LogParam(p.a, l);
581     l->append(", ");
582     LogParam(p.b, l);
583     l->append(", ");
584     LogParam(p.c, l);
585   }
586 };
587 
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) {
592     WriteParam(m, p.a);
593     WriteParam(m, p.b);
594     WriteParam(m, p.c);
595     WriteParam(m, p.d);
596   }
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));
602   }
603   static void Log(const param_type& p, std::string* l) {
604     LogParam(p.a, l);
605     l->append(", ");
606     LogParam(p.b, l);
607     l->append(", ");
608     LogParam(p.c, l);
609     l->append(", ");
610     LogParam(p.d, l);
611   }
612 };
613 
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) {
618     WriteParam(m, p.a);
619     WriteParam(m, p.b);
620     WriteParam(m, p.c);
621     WriteParam(m, p.d);
622     WriteParam(m, p.e);
623   }
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));
630   }
631   static void Log(const param_type& p, std::string* l) {
632     LogParam(p.a, l);
633     l->append(", ");
634     LogParam(p.b, l);
635     l->append(", ");
636     LogParam(p.c, l);
637     l->append(", ");
638     LogParam(p.d, l);
639     l->append(", ");
640     LogParam(p.e, l);
641   }
642 };
643 
644 template<class P>
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]);
651   }
652   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
653     int size = 0;
654     if (!m->ReadLength(iter, &size))
655       return false;
656     if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
657       return false;
658     r->resize(size);
659     for (int i = 0; i < size; i++) {
660       (*r)[i] = new P();
661       if (!ReadParam(m, iter, (*r)[i]))
662         return false;
663     }
664     return true;
665   }
666   static void Log(const param_type& p, std::string* l) {
667     for (size_t i = 0; i < p.size(); ++i) {
668       if (i != 0)
669         l->append(" ");
670       LogParam(*p[i], l);
671     }
672   }
673 };
674 
675 template <typename NormalMap,
676           int kArraySize,
677           typename EqualKey,
678           typename MapInit>
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);
689     }
690   }
691   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
692     int size;
693     if (!m->ReadLength(iter, &size))
694       return false;
695     for (int i = 0; i < size; ++i) {
696       K key;
697       if (!ReadParam(m, iter, &key))
698         return false;
699       V& value = (*r)[key];
700       if (!ReadParam(m, iter, &value))
701         return false;
702     }
703     return true;
704   }
705   static void Log(const param_type& p, std::string* l) {
706     l->append("<base::SmallMap>");
707   }
708 };
709 
710 template <class P>
711 struct ParamTraits<scoped_ptr<P> > {
712   typedef scoped_ptr<P> param_type;
713   static void Write(Message* m, const param_type& p) {
714     bool valid = !!p;
715     WriteParam(m, valid);
716     if (valid)
717       WriteParam(m, *p);
718   }
719   static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
720     bool valid = false;
721     if (!ReadParam(m, iter, &valid))
722       return false;
723 
724     if (!valid) {
725       r->reset();
726       return true;
727     }
728 
729     param_type temp(new P());
730     if (!ReadParam(m, iter, temp.get()))
731       return false;
732 
733     r->swap(temp);
734     return true;
735   }
736   static void Log(const param_type& p, std::string* l) {
737     if (p)
738       LogParam(*p, l);
739     else
740       l->append("NULL");
741   }
742 };
743 
744 // IPC types ParamTraits -------------------------------------------------------
745 
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.
749 template<>
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);
755 };
756 
757 template <>
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);
763 };
764 
765 template <>
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);
770 };
771 
772 // Windows ParamTraits ---------------------------------------------------------
773 
774 #if defined(OS_WIN)
775 template <>
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);
781 };
782 
783 template <>
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);
789 };
790 
791 template <>
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);
797 };
798 #endif  // defined(OS_WIN)
799 
800 //-----------------------------------------------------------------------------
801 // Generic message subclasses
802 
803 // Used for asynchronous messages.
804 template <class ParamType>
805 class MessageSchema {
806  public:
807   typedef ParamType Param;
808   typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
809 
810   static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
811   static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
812 };
813 
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);
818 
819 
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())
824     l->append(", ");
825 
826   l->append(output_params);
827 }
828 
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);
836   }
837 }
838 
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);
846     msg->set_dont_log();
847     reply->set_sync_log_data(data);
848   }
849 }
850 #else
851 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
852 
853 template <class ReplyParamType>
854 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
855                                     const Message* msg) {}
856 
857 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
858 #endif
859 
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 {
865  public:
866   explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
867 
868   bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
869     return ReadParam(&msg, &iter, &out_);
870   }
871 
872   RefTuple out_;
873 };
874 
875 // Used for synchronous messages.
876 template <class SendParamType, class ReplyParamType>
877 class SyncMessageSchema {
878  public:
879   typedef SendParamType SendParam;
880   typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
881   typedef ReplyParamType ReplyParam;
882 
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(
886       const Message* msg,
887       typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
888 
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,
892                                      Method func) {
893     Message* reply = SyncMessage::GenerateReply(msg);
894     if (ok) {
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);
899     } else {
900       NOTREACHED() << "Error deserializing message " << msg->type();
901       reply->set_reply_error();
902     }
903     sender->Send(reply);
904     return ok;
905   }
906 
907   template<class T, class Method>
908   static bool DispatchDelayReplyWithSendParams(bool ok,
909                                                const SendParam& send_params,
910                                                const Message* msg, T* obj,
911                                                Method func) {
912     Message* reply = SyncMessage::GenerateReply(msg);
913     if (ok) {
914       Tuple1<Message&> t = MakeRefTuple(*reply);
915       ConnectMessageAndReply(msg, reply);
916       DispatchToMethod(obj, func, send_params, &t);
917     } else {
918       NOTREACHED() << "Error deserializing message " << msg->type();
919       reply->set_reply_error();
920       obj->Send(reply);
921     }
922     return ok;
923   }
924 
925   template<typename TA>
926   static void WriteReplyParams(Message* reply, TA a) {
927     ReplyParam p(a);
928     WriteParam(reply, p);
929   }
930 
931   template<typename TA, typename TB>
932   static void WriteReplyParams(Message* reply, TA a, TB b) {
933     ReplyParam p(a, b);
934     WriteParam(reply, p);
935   }
936 
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);
941   }
942 
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);
947   }
948 
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);
953   }
954 };
955 
956 }  // namespace IPC
957 
958 #endif  // IPC_IPC_MESSAGE_UTILS_H_
959