Initial implementation of the chrome.automation API.
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blobb05f76dd17334c7a98385dc1114795e0bf384ec4
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/files/file.h"
15 #include "base/format_macros.h"
16 #include "base/memory/scoped_vector.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"
25 #if defined(COMPILER_GCC)
26 // GCC "helpfully" tries to inline template methods in release mode. Except we
27 // want the majority of the template junk being expanded once in the
28 // implementation file (and only provide the definitions in
29 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
30 // at every call site. Special note: GCC happily accepts the attribute before
31 // the method declaration, but only acts on it if it is after.
32 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
33 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
34 // the introduced noclone attribute, which will create specialized versions of
35 // functions/methods when certain types are constant.
36 // www.gnu.org/software/gcc/gcc-4.5/changes.html
37 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
38 #else
39 #define IPC_MSG_NOINLINE __attribute__((noinline));
40 #endif
41 #elif defined(COMPILER_MSVC)
42 // MSVC++ doesn't do this.
43 #define IPC_MSG_NOINLINE
44 #else
45 #error "Please add the noinline property for your new compiler here."
46 #endif
48 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;
59 namespace IPC {
61 struct ChannelHandle;
63 // -----------------------------------------------------------------------------
64 // How we send IPC message logs across channels.
65 struct IPC_EXPORT LogData {
66 LogData();
67 ~LogData();
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;
82 //-----------------------------------------------------------------------------
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 {
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));
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));
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);
109 // Primitive ParamTraits -------------------------------------------------------
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);
117 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
118 return m->ReadBool(iter, r);
120 IPC_EXPORT static void Log(const param_type& p, std::string* l);
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);
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);
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);
145 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
146 return m->ReadInt(iter, r);
148 IPC_EXPORT static void Log(const param_type& p, std::string* l);
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);
157 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
158 return m->ReadInt(iter, reinterpret_cast<int*>(r));
160 IPC_EXPORT static void Log(const param_type& p, std::string* l);
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);
169 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
170 return m->ReadLong(iter, r);
172 IPC_EXPORT static void Log(const param_type& p, std::string* l);
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);
181 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
182 return m->ReadLong(iter, reinterpret_cast<long*>(r));
184 IPC_EXPORT static void Log(const param_type& p, std::string* l);
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));
193 static bool Read(const Message* m, PickleIterator* iter,
194 param_type* r) {
195 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
197 IPC_EXPORT static void Log(const param_type& p, std::string* l);
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);
206 static bool Read(const Message* m, PickleIterator* iter,
207 param_type* r) {
208 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
210 IPC_EXPORT static void Log(const param_type& p, std::string* l);
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);
222 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
223 return m->ReadFloat(iter, r);
225 static void Log(const param_type& p, std::string* l);
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);
236 // STL ParamTraits -------------------------------------------------------------
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);
244 static bool Read(const Message* m, PickleIterator* iter,
245 param_type* r) {
246 return m->ReadString(iter, r);
248 IPC_EXPORT static void Log(const param_type& p, std::string* l);
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);
257 static bool Read(const Message* m, PickleIterator* iter,
258 param_type* r) {
259 return m->ReadWString(iter, r);
261 IPC_EXPORT static void Log(const param_type& p, std::string* l);
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<base::string16> {
269 typedef base::string16 param_type;
270 static void Write(Message* m, const param_type& p) {
271 m->WriteString16(p);
273 static bool Read(const Message* m, PickleIterator* iter,
274 param_type* r) {
275 return m->ReadString16(iter, r);
277 IPC_EXPORT static void Log(const param_type& p, std::string* l);
279 #endif
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);
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);
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);
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]);
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;
327 return true;
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);
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);
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);
358 return true;
360 static void Log(const param_type& p, std::string* l) {
361 l->append("<std::set>");
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);
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;
389 return true;
391 static void Log(const param_type& p, std::string* l) {
392 l->append("<std::map>");
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);
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);
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(")");
416 // Base ParamTraits ------------------------------------------------------------
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);
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*.
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.
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);
449 #endif // defined(OS_POSIX)
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);
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);
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);
476 template <>
477 struct IPC_EXPORT ParamTraits<base::File::Info> {
478 typedef base::File::Info 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);
484 template <>
485 struct SimilarTypeTraits<base::File::Error> {
486 typedef int Type;
489 #if defined(OS_WIN)
490 template <>
491 struct SimilarTypeTraits<HWND> {
492 typedef HANDLE Type;
494 #endif // defined(OS_WIN)
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);
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);
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);
520 template <>
521 struct ParamTraits<Tuple0> {
522 typedef Tuple0 param_type;
523 static void Write(Message* m, const param_type& p) {
525 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
526 return true;
528 static void Log(const param_type& p, std::string* l) {
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);
538 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
539 return ReadParam(m, iter, &r->a);
541 static void Log(const param_type& p, std::string* l) {
542 LogParam(p.a, l);
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);
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));
557 static void Log(const param_type& p, std::string* l) {
558 LogParam(p.a, l);
559 l->append(", ");
560 LogParam(p.b, l);
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);
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));
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);
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);
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));
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);
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);
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));
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);
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]);
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;
662 return true;
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);
673 // IPC types ParamTraits -------------------------------------------------------
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);
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);
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);
701 // Windows ParamTraits ---------------------------------------------------------
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);
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);
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);
727 #endif // defined(OS_WIN)
729 //-----------------------------------------------------------------------------
730 // Generic message subclasses
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;
739 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
740 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
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);
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(", ");
755 l->append(output_params);
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);
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);
779 #else
780 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
782 template <class ReplyParamType>
783 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
784 const Message* msg) {}
786 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
787 #endif
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) { }
797 bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
798 return ReadParam(&msg, &iter, &out_);
801 RefTuple out_;
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;
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;
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();
832 sender->Send(reply);
833 return ok;
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);
851 return ok;
854 template<typename TA>
855 static void WriteReplyParams(Message* reply, TA a) {
856 ReplyParam p(a);
857 WriteParam(reply, p);
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);
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);
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);
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);
885 } // namespace IPC
887 #endif // IPC_IPC_MESSAGE_UTILS_H_