Don't switch browser locale on secondary user login
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blob7121c19e304fcea3dad3d765695f7b0a113e07d2
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef IPC_IPC_MESSAGE_UTILS_H_
6 #define IPC_IPC_MESSAGE_UTILS_H_
8 #include <algorithm>
9 #include <map>
10 #include <set>
11 #include <string>
12 #include <vector>
14 #include "base/format_macros.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/platform_file.h"
17 #include "base/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 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
221 static void Log(const param_type& p, std::string* l);
224 template <>
225 struct IPC_EXPORT ParamTraits<double> {
226 typedef double param_type;
227 static void Write(Message* m, const param_type& p);
228 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
229 static void Log(const param_type& p, std::string* l);
232 // STL ParamTraits -------------------------------------------------------------
234 template <>
235 struct ParamTraits<std::string> {
236 typedef std::string param_type;
237 static void Write(Message* m, const param_type& p) {
238 m->WriteString(p);
240 static bool Read(const Message* m, PickleIterator* iter,
241 param_type* r) {
242 return m->ReadString(iter, r);
244 IPC_EXPORT static void Log(const param_type& p, std::string* l);
247 template <>
248 struct ParamTraits<std::wstring> {
249 typedef std::wstring param_type;
250 static void Write(Message* m, const param_type& p) {
251 m->WriteWString(p);
253 static bool Read(const Message* m, PickleIterator* iter,
254 param_type* r) {
255 return m->ReadWString(iter, r);
257 IPC_EXPORT static void Log(const param_type& p, std::string* l);
260 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
261 // need this trait.
262 #if !defined(WCHAR_T_IS_UTF16)
263 template <>
264 struct ParamTraits<string16> {
265 typedef string16 param_type;
266 static void Write(Message* m, const param_type& p) {
267 m->WriteString16(p);
269 static bool Read(const Message* m, PickleIterator* iter,
270 param_type* r) {
271 return m->ReadString16(iter, r);
273 IPC_EXPORT static void Log(const param_type& p, std::string* l);
275 #endif
277 template <>
278 struct IPC_EXPORT ParamTraits<std::vector<char> > {
279 typedef std::vector<char> param_type;
280 static void Write(Message* m, const param_type& p);
281 static bool Read(const Message*, PickleIterator* iter, param_type* r);
282 static void Log(const param_type& p, std::string* l);
285 template <>
286 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
287 typedef std::vector<unsigned char> param_type;
288 static void Write(Message* m, const param_type& p);
289 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
290 static void Log(const param_type& p, std::string* l);
293 template <>
294 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
295 typedef std::vector<bool> param_type;
296 static void Write(Message* m, const param_type& p);
297 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
298 static void Log(const param_type& p, std::string* l);
301 template <class P>
302 struct ParamTraits<std::vector<P> > {
303 typedef std::vector<P> param_type;
304 static void Write(Message* m, const param_type& p) {
305 WriteParam(m, static_cast<int>(p.size()));
306 for (size_t i = 0; i < p.size(); i++)
307 WriteParam(m, p[i]);
309 static bool Read(const Message* m, PickleIterator* iter,
310 param_type* r) {
311 int size;
312 // ReadLength() checks for < 0 itself.
313 if (!m->ReadLength(iter, &size))
314 return false;
315 // Resizing beforehand is not safe, see BUG 1006367 for details.
316 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
317 return false;
318 r->resize(size);
319 for (int i = 0; i < size; i++) {
320 if (!ReadParam(m, iter, &(*r)[i]))
321 return false;
323 return true;
325 static void Log(const param_type& p, std::string* l) {
326 for (size_t i = 0; i < p.size(); ++i) {
327 if (i != 0)
328 l->append(" ");
329 LogParam((p[i]), l);
334 template <class P>
335 struct ParamTraits<std::set<P> > {
336 typedef std::set<P> param_type;
337 static void Write(Message* m, const param_type& p) {
338 WriteParam(m, static_cast<int>(p.size()));
339 typename param_type::const_iterator iter;
340 for (iter = p.begin(); iter != p.end(); ++iter)
341 WriteParam(m, *iter);
343 static bool Read(const Message* m, PickleIterator* iter,
344 param_type* r) {
345 int size;
346 if (!m->ReadLength(iter, &size))
347 return false;
348 for (int i = 0; i < size; ++i) {
349 P item;
350 if (!ReadParam(m, iter, &item))
351 return false;
352 r->insert(item);
354 return true;
356 static void Log(const param_type& p, std::string* l) {
357 l->append("<std::set>");
361 template <class K, class V>
362 struct ParamTraits<std::map<K, V> > {
363 typedef std::map<K, V> param_type;
364 static void Write(Message* m, const param_type& p) {
365 WriteParam(m, static_cast<int>(p.size()));
366 typename param_type::const_iterator iter;
367 for (iter = p.begin(); iter != p.end(); ++iter) {
368 WriteParam(m, iter->first);
369 WriteParam(m, iter->second);
372 static bool Read(const Message* m, PickleIterator* iter,
373 param_type* r) {
374 int size;
375 if (!ReadParam(m, iter, &size) || size < 0)
376 return false;
377 for (int i = 0; i < size; ++i) {
378 K k;
379 if (!ReadParam(m, iter, &k))
380 return false;
381 V& value = (*r)[k];
382 if (!ReadParam(m, iter, &value))
383 return false;
385 return true;
387 static void Log(const param_type& p, std::string* l) {
388 l->append("<std::map>");
392 template <class A, class B>
393 struct ParamTraits<std::pair<A, B> > {
394 typedef std::pair<A, B> param_type;
395 static void Write(Message* m, const param_type& p) {
396 WriteParam(m, p.first);
397 WriteParam(m, p.second);
399 static bool Read(const Message* m, PickleIterator* iter,
400 param_type* r) {
401 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
403 static void Log(const param_type& p, std::string* l) {
404 l->append("(");
405 LogParam(p.first, l);
406 l->append(", ");
407 LogParam(p.second, l);
408 l->append(")");
412 // Base ParamTraits ------------------------------------------------------------
414 template <>
415 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
416 typedef base::DictionaryValue param_type;
417 static void Write(Message* m, const param_type& p);
418 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
419 static void Log(const param_type& p, std::string* l);
422 #if defined(OS_POSIX)
423 // FileDescriptors may be serialised over IPC channels on POSIX. On the
424 // receiving side, the FileDescriptor is a valid duplicate of the file
425 // descriptor which was transmitted: *it is not just a copy of the integer like
426 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
427 // this case, the receiving end will see a value of -1. *Zero is a valid file
428 // descriptor*.
430 // The received file descriptor will have the |auto_close| flag set to true. The
431 // code which handles the message is responsible for taking ownership of it.
432 // File descriptors are OS resources and must be closed when no longer needed.
434 // When sending a file descriptor, the file descriptor must be valid at the time
435 // of transmission. Since transmission is not synchronous, one should consider
436 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
437 // flag, which causes the file descriptor to be closed after writing.
438 template<>
439 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
440 typedef base::FileDescriptor param_type;
441 static void Write(Message* m, const param_type& p);
442 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
443 static void Log(const param_type& p, std::string* l);
445 #endif // defined(OS_POSIX)
447 template <>
448 struct IPC_EXPORT ParamTraits<base::FilePath> {
449 typedef base::FilePath param_type;
450 static void Write(Message* m, const param_type& p);
451 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
452 static void Log(const param_type& p, std::string* l);
455 template <>
456 struct IPC_EXPORT ParamTraits<base::ListValue> {
457 typedef base::ListValue param_type;
458 static void Write(Message* m, const param_type& p);
459 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
460 static void Log(const param_type& p, std::string* l);
463 template <>
464 struct IPC_EXPORT ParamTraits<base::NullableString16> {
465 typedef base::NullableString16 param_type;
466 static void Write(Message* m, const param_type& p);
467 static bool Read(const Message* m, PickleIterator* iter,
468 param_type* r);
469 static void Log(const param_type& p, std::string* l);
472 template <>
473 struct IPC_EXPORT ParamTraits<base::PlatformFileInfo> {
474 typedef base::PlatformFileInfo param_type;
475 static void Write(Message* m, const param_type& p);
476 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
477 static void Log(const param_type& p, std::string* l);
480 template <>
481 struct SimilarTypeTraits<base::PlatformFileError> {
482 typedef int Type;
485 #if defined(OS_WIN)
486 template <>
487 struct SimilarTypeTraits<HWND> {
488 typedef HANDLE Type;
490 #endif // defined(OS_WIN)
492 template <>
493 struct IPC_EXPORT ParamTraits<base::Time> {
494 typedef base::Time param_type;
495 static void Write(Message* m, const param_type& p);
496 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
497 static void Log(const param_type& p, std::string* l);
500 template <>
501 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
502 typedef base::TimeDelta param_type;
503 static void Write(Message* m, const param_type& p);
504 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
505 static void Log(const param_type& p, std::string* l);
508 template <>
509 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
510 typedef base::TimeTicks param_type;
511 static void Write(Message* m, const param_type& p);
512 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
513 static void Log(const param_type& p, std::string* l);
516 template <>
517 struct ParamTraits<Tuple0> {
518 typedef Tuple0 param_type;
519 static void Write(Message* m, const param_type& p) {
521 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
522 return true;
524 static void Log(const param_type& p, std::string* l) {
528 template <class A>
529 struct ParamTraits< Tuple1<A> > {
530 typedef Tuple1<A> param_type;
531 static void Write(Message* m, const param_type& p) {
532 WriteParam(m, p.a);
534 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
535 return ReadParam(m, iter, &r->a);
537 static void Log(const param_type& p, std::string* l) {
538 LogParam(p.a, l);
542 template <class A, class B>
543 struct ParamTraits< Tuple2<A, B> > {
544 typedef Tuple2<A, B> param_type;
545 static void Write(Message* m, const param_type& p) {
546 WriteParam(m, p.a);
547 WriteParam(m, p.b);
549 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
550 return (ReadParam(m, iter, &r->a) &&
551 ReadParam(m, iter, &r->b));
553 static void Log(const param_type& p, std::string* l) {
554 LogParam(p.a, l);
555 l->append(", ");
556 LogParam(p.b, l);
560 template <class A, class B, class C>
561 struct ParamTraits< Tuple3<A, B, C> > {
562 typedef Tuple3<A, B, C> param_type;
563 static void Write(Message* m, const param_type& p) {
564 WriteParam(m, p.a);
565 WriteParam(m, p.b);
566 WriteParam(m, p.c);
568 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
569 return (ReadParam(m, iter, &r->a) &&
570 ReadParam(m, iter, &r->b) &&
571 ReadParam(m, iter, &r->c));
573 static void Log(const param_type& p, std::string* l) {
574 LogParam(p.a, l);
575 l->append(", ");
576 LogParam(p.b, l);
577 l->append(", ");
578 LogParam(p.c, l);
582 template <class A, class B, class C, class D>
583 struct ParamTraits< Tuple4<A, B, C, D> > {
584 typedef Tuple4<A, B, C, D> param_type;
585 static void Write(Message* m, const param_type& p) {
586 WriteParam(m, p.a);
587 WriteParam(m, p.b);
588 WriteParam(m, p.c);
589 WriteParam(m, p.d);
591 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
592 return (ReadParam(m, iter, &r->a) &&
593 ReadParam(m, iter, &r->b) &&
594 ReadParam(m, iter, &r->c) &&
595 ReadParam(m, iter, &r->d));
597 static void Log(const param_type& p, std::string* l) {
598 LogParam(p.a, l);
599 l->append(", ");
600 LogParam(p.b, l);
601 l->append(", ");
602 LogParam(p.c, l);
603 l->append(", ");
604 LogParam(p.d, l);
608 template <class A, class B, class C, class D, class E>
609 struct ParamTraits< Tuple5<A, B, C, D, E> > {
610 typedef Tuple5<A, B, C, D, E> param_type;
611 static void Write(Message* m, const param_type& p) {
612 WriteParam(m, p.a);
613 WriteParam(m, p.b);
614 WriteParam(m, p.c);
615 WriteParam(m, p.d);
616 WriteParam(m, p.e);
618 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
619 return (ReadParam(m, iter, &r->a) &&
620 ReadParam(m, iter, &r->b) &&
621 ReadParam(m, iter, &r->c) &&
622 ReadParam(m, iter, &r->d) &&
623 ReadParam(m, iter, &r->e));
625 static void Log(const param_type& p, std::string* l) {
626 LogParam(p.a, l);
627 l->append(", ");
628 LogParam(p.b, l);
629 l->append(", ");
630 LogParam(p.c, l);
631 l->append(", ");
632 LogParam(p.d, l);
633 l->append(", ");
634 LogParam(p.e, l);
638 template<class P>
639 struct ParamTraits<ScopedVector<P> > {
640 typedef ScopedVector<P> param_type;
641 static void Write(Message* m, const param_type& p) {
642 WriteParam(m, static_cast<int>(p.size()));
643 for (size_t i = 0; i < p.size(); i++)
644 WriteParam(m, *p[i]);
646 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
647 int size = 0;
648 if (!m->ReadLength(iter, &size))
649 return false;
650 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
651 return false;
652 r->resize(size);
653 for (int i = 0; i < size; i++) {
654 (*r)[i] = new P();
655 if (!ReadParam(m, iter, (*r)[i]))
656 return false;
658 return true;
660 static void Log(const param_type& p, std::string* l) {
661 for (size_t i = 0; i < p.size(); ++i) {
662 if (i != 0)
663 l->append(" ");
664 LogParam(*p[i], l);
669 // IPC types ParamTraits -------------------------------------------------------
671 // A ChannelHandle is basically a platform-inspecific wrapper around the
672 // fact that IPC endpoints are handled specially on POSIX. See above comments
673 // on FileDescriptor for more background.
674 template<>
675 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
676 typedef ChannelHandle param_type;
677 static void Write(Message* m, const param_type& p);
678 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
679 static void Log(const param_type& p, std::string* l);
682 template <>
683 struct IPC_EXPORT ParamTraits<LogData> {
684 typedef LogData param_type;
685 static void Write(Message* m, const param_type& p);
686 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
687 static void Log(const param_type& p, std::string* l);
690 template <>
691 struct IPC_EXPORT ParamTraits<Message> {
692 static void Write(Message* m, const Message& p);
693 static bool Read(const Message* m, PickleIterator* iter, Message* r);
694 static void Log(const Message& p, std::string* l);
697 // Windows ParamTraits ---------------------------------------------------------
699 #if defined(OS_WIN)
700 template <>
701 struct IPC_EXPORT ParamTraits<HANDLE> {
702 typedef HANDLE param_type;
703 static void Write(Message* m, const param_type& p);
704 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
705 static void Log(const param_type& p, std::string* l);
708 template <>
709 struct IPC_EXPORT ParamTraits<LOGFONT> {
710 typedef LOGFONT param_type;
711 static void Write(Message* m, const param_type& p);
712 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
713 static void Log(const param_type& p, std::string* l);
716 template <>
717 struct IPC_EXPORT ParamTraits<MSG> {
718 typedef MSG param_type;
719 static void Write(Message* m, const param_type& p);
720 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
721 static void Log(const param_type& p, std::string* l);
723 #endif // defined(OS_WIN)
725 //-----------------------------------------------------------------------------
726 // Generic message subclasses
728 // Used for asynchronous messages.
729 template <class ParamType>
730 class MessageSchema {
731 public:
732 typedef ParamType Param;
733 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
735 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
736 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
739 // defined in ipc_logging.cc
740 IPC_EXPORT void GenerateLogData(const std::string& channel,
741 const Message& message,
742 LogData* data, bool get_params);
745 #if defined(IPC_MESSAGE_LOG_ENABLED)
746 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
747 const std::string& output_params = msg->output_params();
748 if (!l->empty() && !output_params.empty())
749 l->append(", ");
751 l->append(output_params);
754 template <class ReplyParamType>
755 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
756 const Message* msg) {
757 if (msg->received_time() != 0) {
758 std::string output_params;
759 LogParam(reply_params, &output_params);
760 msg->set_output_params(output_params);
764 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
765 if (msg->sent_time()) {
766 // Don't log the sync message after dispatch, as we don't have the
767 // output parameters at that point. Instead, save its data and log it
768 // with the outgoing reply message when it's sent.
769 LogData* data = new LogData;
770 GenerateLogData("", *msg, data, true);
771 msg->set_dont_log();
772 reply->set_sync_log_data(data);
775 #else
776 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
778 template <class ReplyParamType>
779 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
780 const Message* msg) {}
782 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
783 #endif
785 // This class assumes that its template argument is a RefTuple (a Tuple with
786 // reference elements). This would go into ipc_message_utils_impl.h, but it is
787 // also used by chrome_frame.
788 template <class RefTuple>
789 class ParamDeserializer : public MessageReplyDeserializer {
790 public:
791 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
793 bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
794 return ReadParam(&msg, &iter, &out_);
797 RefTuple out_;
800 // Used for synchronous messages.
801 template <class SendParamType, class ReplyParamType>
802 class SyncMessageSchema {
803 public:
804 typedef SendParamType SendParam;
805 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
806 typedef ReplyParamType ReplyParam;
808 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
809 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
810 static bool ReadReplyParam(
811 const Message* msg,
812 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
814 template<class T, class S, class Method>
815 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
816 const Message* msg, T* obj, S* sender,
817 Method func) {
818 Message* reply = SyncMessage::GenerateReply(msg);
819 if (ok) {
820 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
821 DispatchToMethod(obj, func, send_params, &reply_params);
822 WriteParam(reply, reply_params);
823 LogReplyParamsToMessage(reply_params, msg);
824 } else {
825 NOTREACHED() << "Error deserializing message " << msg->type();
826 reply->set_reply_error();
828 sender->Send(reply);
829 return ok;
832 template<class T, class Method>
833 static bool DispatchDelayReplyWithSendParams(bool ok,
834 const SendParam& send_params,
835 const Message* msg, T* obj,
836 Method func) {
837 Message* reply = SyncMessage::GenerateReply(msg);
838 if (ok) {
839 Tuple1<Message&> t = MakeRefTuple(*reply);
840 ConnectMessageAndReply(msg, reply);
841 DispatchToMethod(obj, func, send_params, &t);
842 } else {
843 NOTREACHED() << "Error deserializing message " << msg->type();
844 reply->set_reply_error();
845 obj->Send(reply);
847 return ok;
850 template<typename TA>
851 static void WriteReplyParams(Message* reply, TA a) {
852 ReplyParam p(a);
853 WriteParam(reply, p);
856 template<typename TA, typename TB>
857 static void WriteReplyParams(Message* reply, TA a, TB b) {
858 ReplyParam p(a, b);
859 WriteParam(reply, p);
862 template<typename TA, typename TB, typename TC>
863 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
864 ReplyParam p(a, b, c);
865 WriteParam(reply, p);
868 template<typename TA, typename TB, typename TC, typename TD>
869 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
870 ReplyParam p(a, b, c, d);
871 WriteParam(reply, p);
874 template<typename TA, typename TB, typename TC, typename TD, typename TE>
875 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
876 ReplyParam p(a, b, c, d, e);
877 WriteParam(reply, p);
881 } // namespace IPC
883 #endif // IPC_IPC_MESSAGE_UTILS_H_