Blink roll 171798:171837
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blob102992d45ec6e003bf1a516bdc9b39e002b494f8
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/containers/small_map.h"
15 #include "base/files/file.h"
16 #include "base/format_macros.h"
17 #include "base/memory/scoped_vector.h"
18 #include "base/strings/string16.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/tuple.h"
22 #include "ipc/ipc_message_start.h"
23 #include "ipc/ipc_param_traits.h"
24 #include "ipc/ipc_sync_message.h"
26 #if defined(COMPILER_GCC)
27 // GCC "helpfully" tries to inline template methods in release mode. Except we
28 // want the majority of the template junk being expanded once in the
29 // implementation file (and only provide the definitions in
30 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
31 // at every call site. Special note: GCC happily accepts the attribute before
32 // the method declaration, but only acts on it if it is after.
33 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
34 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
35 // the introduced noclone attribute, which will create specialized versions of
36 // functions/methods when certain types are constant.
37 // www.gnu.org/software/gcc/gcc-4.5/changes.html
38 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
39 #else
40 #define IPC_MSG_NOINLINE __attribute__((noinline));
41 #endif
42 #elif defined(COMPILER_MSVC)
43 // MSVC++ doesn't do this.
44 #define IPC_MSG_NOINLINE
45 #else
46 #error "Please add the noinline property for your new compiler here."
47 #endif
49 namespace base {
50 class DictionaryValue;
51 class FilePath;
52 class ListValue;
53 class NullableString16;
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 IPC_EXPORT ParamTraits<unsigned char> {
126 typedef unsigned char param_type;
127 static void Write(Message* m, const param_type& p);
128 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
129 static void Log(const param_type& p, std::string* l);
132 template <>
133 struct IPC_EXPORT ParamTraits<unsigned short> {
134 typedef unsigned short param_type;
135 static void Write(Message* m, const param_type& p);
136 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
137 static void Log(const param_type& p, std::string* l);
140 template <>
141 struct ParamTraits<int> {
142 typedef int param_type;
143 static void Write(Message* m, const param_type& p) {
144 m->WriteInt(p);
146 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
147 return m->ReadInt(iter, r);
149 IPC_EXPORT static void Log(const param_type& p, std::string* l);
152 template <>
153 struct ParamTraits<unsigned int> {
154 typedef unsigned int param_type;
155 static void Write(Message* m, const param_type& p) {
156 m->WriteInt(p);
158 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
159 return m->ReadInt(iter, reinterpret_cast<int*>(r));
161 IPC_EXPORT static void Log(const param_type& p, std::string* l);
164 template <>
165 struct ParamTraits<long> {
166 typedef long param_type;
167 static void Write(Message* m, const param_type& p) {
168 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
170 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
171 return m->ReadLong(iter, r);
173 IPC_EXPORT static void Log(const param_type& p, std::string* l);
176 template <>
177 struct ParamTraits<unsigned long> {
178 typedef unsigned long param_type;
179 static void Write(Message* m, const param_type& p) {
180 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
182 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
183 return m->ReadLong(iter, reinterpret_cast<long*>(r));
185 IPC_EXPORT static void Log(const param_type& p, std::string* l);
188 template <>
189 struct ParamTraits<long long> {
190 typedef long long param_type;
191 static void Write(Message* m, const param_type& p) {
192 m->WriteInt64(static_cast<int64>(p));
194 static bool Read(const Message* m, PickleIterator* iter,
195 param_type* r) {
196 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
198 IPC_EXPORT static void Log(const param_type& p, std::string* l);
201 template <>
202 struct ParamTraits<unsigned long long> {
203 typedef unsigned long long param_type;
204 static void Write(Message* m, const param_type& p) {
205 m->WriteInt64(p);
207 static bool Read(const Message* m, PickleIterator* iter,
208 param_type* r) {
209 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
211 IPC_EXPORT static void Log(const param_type& p, std::string* l);
214 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
215 // should be sure to check the sanity of these values after receiving them over
216 // IPC.
217 template <>
218 struct IPC_EXPORT ParamTraits<float> {
219 typedef float param_type;
220 static void Write(Message* m, const param_type& p) {
221 m->WriteFloat(p);
223 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
224 return m->ReadFloat(iter, r);
226 static void Log(const param_type& p, std::string* l);
229 template <>
230 struct IPC_EXPORT ParamTraits<double> {
231 typedef double param_type;
232 static void Write(Message* m, const param_type& p);
233 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
234 static void Log(const param_type& p, std::string* l);
237 // STL ParamTraits -------------------------------------------------------------
239 template <>
240 struct ParamTraits<std::string> {
241 typedef std::string param_type;
242 static void Write(Message* m, const param_type& p) {
243 m->WriteString(p);
245 static bool Read(const Message* m, PickleIterator* iter,
246 param_type* r) {
247 return m->ReadString(iter, r);
249 IPC_EXPORT static void Log(const param_type& p, std::string* l);
252 template <>
253 struct ParamTraits<std::wstring> {
254 typedef std::wstring param_type;
255 static void Write(Message* m, const param_type& p) {
256 m->WriteWString(p);
258 static bool Read(const Message* m, PickleIterator* iter,
259 param_type* r) {
260 return m->ReadWString(iter, r);
262 IPC_EXPORT static void Log(const param_type& p, std::string* l);
265 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
266 // need this trait.
267 #if !defined(WCHAR_T_IS_UTF16)
268 template <>
269 struct ParamTraits<base::string16> {
270 typedef base::string16 param_type;
271 static void Write(Message* m, const param_type& p) {
272 m->WriteString16(p);
274 static bool Read(const Message* m, PickleIterator* iter,
275 param_type* r) {
276 return m->ReadString16(iter, r);
278 IPC_EXPORT static void Log(const param_type& p, std::string* l);
280 #endif
282 template <>
283 struct IPC_EXPORT ParamTraits<std::vector<char> > {
284 typedef std::vector<char> param_type;
285 static void Write(Message* m, const param_type& p);
286 static bool Read(const Message*, PickleIterator* iter, param_type* r);
287 static void Log(const param_type& p, std::string* l);
290 template <>
291 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
292 typedef std::vector<unsigned char> param_type;
293 static void Write(Message* m, const param_type& p);
294 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
295 static void Log(const param_type& p, std::string* l);
298 template <>
299 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
300 typedef std::vector<bool> param_type;
301 static void Write(Message* m, const param_type& p);
302 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
303 static void Log(const param_type& p, std::string* l);
306 template <class P>
307 struct ParamTraits<std::vector<P> > {
308 typedef std::vector<P> param_type;
309 static void Write(Message* m, const param_type& p) {
310 WriteParam(m, static_cast<int>(p.size()));
311 for (size_t i = 0; i < p.size(); i++)
312 WriteParam(m, p[i]);
314 static bool Read(const Message* m, PickleIterator* iter,
315 param_type* r) {
316 int size;
317 // ReadLength() checks for < 0 itself.
318 if (!m->ReadLength(iter, &size))
319 return false;
320 // Resizing beforehand is not safe, see BUG 1006367 for details.
321 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
322 return false;
323 r->resize(size);
324 for (int i = 0; i < size; i++) {
325 if (!ReadParam(m, iter, &(*r)[i]))
326 return false;
328 return true;
330 static void Log(const param_type& p, std::string* l) {
331 for (size_t i = 0; i < p.size(); ++i) {
332 if (i != 0)
333 l->append(" ");
334 LogParam((p[i]), l);
339 template <class P>
340 struct ParamTraits<std::set<P> > {
341 typedef std::set<P> param_type;
342 static void Write(Message* m, const param_type& p) {
343 WriteParam(m, static_cast<int>(p.size()));
344 typename param_type::const_iterator iter;
345 for (iter = p.begin(); iter != p.end(); ++iter)
346 WriteParam(m, *iter);
348 static bool Read(const Message* m, PickleIterator* iter,
349 param_type* r) {
350 int size;
351 if (!m->ReadLength(iter, &size))
352 return false;
353 for (int i = 0; i < size; ++i) {
354 P item;
355 if (!ReadParam(m, iter, &item))
356 return false;
357 r->insert(item);
359 return true;
361 static void Log(const param_type& p, std::string* l) {
362 l->append("<std::set>");
366 template <class K, class V>
367 struct ParamTraits<std::map<K, V> > {
368 typedef std::map<K, V> param_type;
369 static void Write(Message* m, const param_type& p) {
370 WriteParam(m, static_cast<int>(p.size()));
371 typename param_type::const_iterator iter;
372 for (iter = p.begin(); iter != p.end(); ++iter) {
373 WriteParam(m, iter->first);
374 WriteParam(m, iter->second);
377 static bool Read(const Message* m, PickleIterator* iter,
378 param_type* r) {
379 int size;
380 if (!ReadParam(m, iter, &size) || size < 0)
381 return false;
382 for (int i = 0; i < size; ++i) {
383 K k;
384 if (!ReadParam(m, iter, &k))
385 return false;
386 V& value = (*r)[k];
387 if (!ReadParam(m, iter, &value))
388 return false;
390 return true;
392 static void Log(const param_type& p, std::string* l) {
393 l->append("<std::map>");
397 template <class A, class B>
398 struct ParamTraits<std::pair<A, B> > {
399 typedef std::pair<A, B> param_type;
400 static void Write(Message* m, const param_type& p) {
401 WriteParam(m, p.first);
402 WriteParam(m, p.second);
404 static bool Read(const Message* m, PickleIterator* iter,
405 param_type* r) {
406 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
408 static void Log(const param_type& p, std::string* l) {
409 l->append("(");
410 LogParam(p.first, l);
411 l->append(", ");
412 LogParam(p.second, l);
413 l->append(")");
417 // Base ParamTraits ------------------------------------------------------------
419 template <>
420 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
421 typedef base::DictionaryValue param_type;
422 static void Write(Message* m, const param_type& p);
423 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
424 static void Log(const param_type& p, std::string* l);
427 #if defined(OS_POSIX)
428 // FileDescriptors may be serialised over IPC channels on POSIX. On the
429 // receiving side, the FileDescriptor is a valid duplicate of the file
430 // descriptor which was transmitted: *it is not just a copy of the integer like
431 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
432 // this case, the receiving end will see a value of -1. *Zero is a valid file
433 // descriptor*.
435 // The received file descriptor will have the |auto_close| flag set to true. The
436 // code which handles the message is responsible for taking ownership of it.
437 // File descriptors are OS resources and must be closed when no longer needed.
439 // When sending a file descriptor, the file descriptor must be valid at the time
440 // of transmission. Since transmission is not synchronous, one should consider
441 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
442 // flag, which causes the file descriptor to be closed after writing.
443 template<>
444 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
445 typedef base::FileDescriptor param_type;
446 static void Write(Message* m, const param_type& p);
447 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
448 static void Log(const param_type& p, std::string* l);
450 #endif // defined(OS_POSIX)
452 template <>
453 struct IPC_EXPORT ParamTraits<base::FilePath> {
454 typedef base::FilePath param_type;
455 static void Write(Message* m, const param_type& p);
456 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
457 static void Log(const param_type& p, std::string* l);
460 template <>
461 struct IPC_EXPORT ParamTraits<base::ListValue> {
462 typedef base::ListValue param_type;
463 static void Write(Message* m, const param_type& p);
464 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
465 static void Log(const param_type& p, std::string* l);
468 template <>
469 struct IPC_EXPORT ParamTraits<base::NullableString16> {
470 typedef base::NullableString16 param_type;
471 static void Write(Message* m, const param_type& p);
472 static bool Read(const Message* m, PickleIterator* iter,
473 param_type* r);
474 static void Log(const param_type& p, std::string* l);
477 template <>
478 struct IPC_EXPORT ParamTraits<base::File::Info> {
479 typedef base::File::Info param_type;
480 static void Write(Message* m, const param_type& p);
481 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
482 static void Log(const param_type& p, std::string* l);
485 template <>
486 struct SimilarTypeTraits<base::File::Error> {
487 typedef int Type;
490 #if defined(OS_WIN)
491 template <>
492 struct SimilarTypeTraits<HWND> {
493 typedef HANDLE Type;
495 #endif // defined(OS_WIN)
497 template <>
498 struct IPC_EXPORT ParamTraits<base::Time> {
499 typedef base::Time param_type;
500 static void Write(Message* m, const param_type& p);
501 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
502 static void Log(const param_type& p, std::string* l);
505 template <>
506 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
507 typedef base::TimeDelta param_type;
508 static void Write(Message* m, const param_type& p);
509 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
510 static void Log(const param_type& p, std::string* l);
513 template <>
514 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
515 typedef base::TimeTicks param_type;
516 static void Write(Message* m, const param_type& p);
517 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
518 static void Log(const param_type& p, std::string* l);
521 template <>
522 struct ParamTraits<Tuple0> {
523 typedef Tuple0 param_type;
524 static void Write(Message* m, const param_type& p) {
526 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
527 return true;
529 static void Log(const param_type& p, std::string* l) {
533 template <class A>
534 struct ParamTraits< Tuple1<A> > {
535 typedef Tuple1<A> param_type;
536 static void Write(Message* m, const param_type& p) {
537 WriteParam(m, p.a);
539 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
540 return ReadParam(m, iter, &r->a);
542 static void Log(const param_type& p, std::string* l) {
543 LogParam(p.a, l);
547 template <class A, class B>
548 struct ParamTraits< Tuple2<A, B> > {
549 typedef Tuple2<A, B> param_type;
550 static void Write(Message* m, const param_type& p) {
551 WriteParam(m, p.a);
552 WriteParam(m, p.b);
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));
558 static void Log(const param_type& p, std::string* l) {
559 LogParam(p.a, l);
560 l->append(", ");
561 LogParam(p.b, l);
565 template <class A, class B, class C>
566 struct ParamTraits< Tuple3<A, B, C> > {
567 typedef Tuple3<A, B, C> param_type;
568 static void Write(Message* m, const param_type& p) {
569 WriteParam(m, p.a);
570 WriteParam(m, p.b);
571 WriteParam(m, p.c);
573 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
574 return (ReadParam(m, iter, &r->a) &&
575 ReadParam(m, iter, &r->b) &&
576 ReadParam(m, iter, &r->c));
578 static void Log(const param_type& p, std::string* l) {
579 LogParam(p.a, l);
580 l->append(", ");
581 LogParam(p.b, l);
582 l->append(", ");
583 LogParam(p.c, l);
587 template <class A, class B, class C, class D>
588 struct ParamTraits< Tuple4<A, B, C, D> > {
589 typedef Tuple4<A, B, C, D> param_type;
590 static void Write(Message* m, const param_type& p) {
591 WriteParam(m, p.a);
592 WriteParam(m, p.b);
593 WriteParam(m, p.c);
594 WriteParam(m, p.d);
596 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
597 return (ReadParam(m, iter, &r->a) &&
598 ReadParam(m, iter, &r->b) &&
599 ReadParam(m, iter, &r->c) &&
600 ReadParam(m, iter, &r->d));
602 static void Log(const param_type& p, std::string* l) {
603 LogParam(p.a, l);
604 l->append(", ");
605 LogParam(p.b, l);
606 l->append(", ");
607 LogParam(p.c, l);
608 l->append(", ");
609 LogParam(p.d, l);
613 template <class A, class B, class C, class D, class E>
614 struct ParamTraits< Tuple5<A, B, C, D, E> > {
615 typedef Tuple5<A, B, C, D, E> param_type;
616 static void Write(Message* m, const param_type& p) {
617 WriteParam(m, p.a);
618 WriteParam(m, p.b);
619 WriteParam(m, p.c);
620 WriteParam(m, p.d);
621 WriteParam(m, p.e);
623 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
624 return (ReadParam(m, iter, &r->a) &&
625 ReadParam(m, iter, &r->b) &&
626 ReadParam(m, iter, &r->c) &&
627 ReadParam(m, iter, &r->d) &&
628 ReadParam(m, iter, &r->e));
630 static void Log(const param_type& p, std::string* l) {
631 LogParam(p.a, l);
632 l->append(", ");
633 LogParam(p.b, l);
634 l->append(", ");
635 LogParam(p.c, l);
636 l->append(", ");
637 LogParam(p.d, l);
638 l->append(", ");
639 LogParam(p.e, l);
643 template<class P>
644 struct ParamTraits<ScopedVector<P> > {
645 typedef ScopedVector<P> param_type;
646 static void Write(Message* m, const param_type& p) {
647 WriteParam(m, static_cast<int>(p.size()));
648 for (size_t i = 0; i < p.size(); i++)
649 WriteParam(m, *p[i]);
651 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
652 int size = 0;
653 if (!m->ReadLength(iter, &size))
654 return false;
655 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
656 return false;
657 r->resize(size);
658 for (int i = 0; i < size; i++) {
659 (*r)[i] = new P();
660 if (!ReadParam(m, iter, (*r)[i]))
661 return false;
663 return true;
665 static void Log(const param_type& p, std::string* l) {
666 for (size_t i = 0; i < p.size(); ++i) {
667 if (i != 0)
668 l->append(" ");
669 LogParam(*p[i], l);
674 template <typename NormalMap,
675 int kArraySize,
676 typename EqualKey,
677 typename MapInit>
678 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
679 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
680 typedef typename param_type::key_type K;
681 typedef typename param_type::data_type V;
682 static void Write(Message* m, const param_type& p) {
683 WriteParam(m, static_cast<int>(p.size()));
684 typename param_type::const_iterator iter;
685 for (iter = p.begin(); iter != p.end(); ++iter) {
686 WriteParam(m, iter->first);
687 WriteParam(m, iter->second);
690 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
691 int size;
692 if (!m->ReadLength(iter, &size))
693 return false;
694 for (int i = 0; i < size; ++i) {
695 K key;
696 if (!ReadParam(m, iter, &key))
697 return false;
698 V& value = (*r)[key];
699 if (!ReadParam(m, iter, &value))
700 return false;
702 return true;
704 static void Log(const param_type& p, std::string* l) {
705 l->append("<base::SmallMap>");
709 // IPC types ParamTraits -------------------------------------------------------
711 // A ChannelHandle is basically a platform-inspecific wrapper around the
712 // fact that IPC endpoints are handled specially on POSIX. See above comments
713 // on FileDescriptor for more background.
714 template<>
715 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
716 typedef ChannelHandle param_type;
717 static void Write(Message* m, const param_type& p);
718 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
719 static void Log(const param_type& p, std::string* l);
722 template <>
723 struct IPC_EXPORT ParamTraits<LogData> {
724 typedef LogData param_type;
725 static void Write(Message* m, const param_type& p);
726 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
727 static void Log(const param_type& p, std::string* l);
730 template <>
731 struct IPC_EXPORT ParamTraits<Message> {
732 static void Write(Message* m, const Message& p);
733 static bool Read(const Message* m, PickleIterator* iter, Message* r);
734 static void Log(const Message& p, std::string* l);
737 // Windows ParamTraits ---------------------------------------------------------
739 #if defined(OS_WIN)
740 template <>
741 struct IPC_EXPORT ParamTraits<HANDLE> {
742 typedef HANDLE param_type;
743 static void Write(Message* m, const param_type& p);
744 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
745 static void Log(const param_type& p, std::string* l);
748 template <>
749 struct IPC_EXPORT ParamTraits<LOGFONT> {
750 typedef LOGFONT param_type;
751 static void Write(Message* m, const param_type& p);
752 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
753 static void Log(const param_type& p, std::string* l);
756 template <>
757 struct IPC_EXPORT ParamTraits<MSG> {
758 typedef MSG param_type;
759 static void Write(Message* m, const param_type& p);
760 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
761 static void Log(const param_type& p, std::string* l);
763 #endif // defined(OS_WIN)
765 //-----------------------------------------------------------------------------
766 // Generic message subclasses
768 // Used for asynchronous messages.
769 template <class ParamType>
770 class MessageSchema {
771 public:
772 typedef ParamType Param;
773 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
775 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
776 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
779 // defined in ipc_logging.cc
780 IPC_EXPORT void GenerateLogData(const std::string& channel,
781 const Message& message,
782 LogData* data, bool get_params);
785 #if defined(IPC_MESSAGE_LOG_ENABLED)
786 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
787 const std::string& output_params = msg->output_params();
788 if (!l->empty() && !output_params.empty())
789 l->append(", ");
791 l->append(output_params);
794 template <class ReplyParamType>
795 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
796 const Message* msg) {
797 if (msg->received_time() != 0) {
798 std::string output_params;
799 LogParam(reply_params, &output_params);
800 msg->set_output_params(output_params);
804 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
805 if (msg->sent_time()) {
806 // Don't log the sync message after dispatch, as we don't have the
807 // output parameters at that point. Instead, save its data and log it
808 // with the outgoing reply message when it's sent.
809 LogData* data = new LogData;
810 GenerateLogData("", *msg, data, true);
811 msg->set_dont_log();
812 reply->set_sync_log_data(data);
815 #else
816 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
818 template <class ReplyParamType>
819 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
820 const Message* msg) {}
822 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
823 #endif
825 // This class assumes that its template argument is a RefTuple (a Tuple with
826 // reference elements). This would go into ipc_message_utils_impl.h, but it is
827 // also used by chrome_frame.
828 template <class RefTuple>
829 class ParamDeserializer : public MessageReplyDeserializer {
830 public:
831 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
833 bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
834 return ReadParam(&msg, &iter, &out_);
837 RefTuple out_;
840 // Used for synchronous messages.
841 template <class SendParamType, class ReplyParamType>
842 class SyncMessageSchema {
843 public:
844 typedef SendParamType SendParam;
845 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
846 typedef ReplyParamType ReplyParam;
848 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
849 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
850 static bool ReadReplyParam(
851 const Message* msg,
852 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
854 template<class T, class S, class Method>
855 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
856 const Message* msg, T* obj, S* sender,
857 Method func) {
858 Message* reply = SyncMessage::GenerateReply(msg);
859 if (ok) {
860 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
861 DispatchToMethod(obj, func, send_params, &reply_params);
862 WriteParam(reply, reply_params);
863 LogReplyParamsToMessage(reply_params, msg);
864 } else {
865 NOTREACHED() << "Error deserializing message " << msg->type();
866 reply->set_reply_error();
868 sender->Send(reply);
869 return ok;
872 template<class T, class Method>
873 static bool DispatchDelayReplyWithSendParams(bool ok,
874 const SendParam& send_params,
875 const Message* msg, T* obj,
876 Method func) {
877 Message* reply = SyncMessage::GenerateReply(msg);
878 if (ok) {
879 Tuple1<Message&> t = MakeRefTuple(*reply);
880 ConnectMessageAndReply(msg, reply);
881 DispatchToMethod(obj, func, send_params, &t);
882 } else {
883 NOTREACHED() << "Error deserializing message " << msg->type();
884 reply->set_reply_error();
885 obj->Send(reply);
887 return ok;
890 template<typename TA>
891 static void WriteReplyParams(Message* reply, TA a) {
892 ReplyParam p(a);
893 WriteParam(reply, p);
896 template<typename TA, typename TB>
897 static void WriteReplyParams(Message* reply, TA a, TB b) {
898 ReplyParam p(a, b);
899 WriteParam(reply, p);
902 template<typename TA, typename TB, typename TC>
903 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
904 ReplyParam p(a, b, c);
905 WriteParam(reply, p);
908 template<typename TA, typename TB, typename TC, typename TD>
909 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
910 ReplyParam p(a, b, c, d);
911 WriteParam(reply, p);
914 template<typename TA, typename TB, typename TC, typename TD, typename TE>
915 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
916 ReplyParam p(a, b, c, d, e);
917 WriteParam(reply, p);
921 } // namespace IPC
923 #endif // IPC_IPC_MESSAGE_UTILS_H_