Switch to using GregorianCalendar.
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blob96bb6895abb3f08c25dca3af78c7f8a26619ce38
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_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"
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
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 class TraceTicks;
59 struct FileDescriptor;
61 #if defined(OS_MACOSX) && !defined(OS_IOS)
62 class SharedMemoryHandle;
63 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
66 namespace IPC {
68 struct ChannelHandle;
70 // -----------------------------------------------------------------------------
71 // How we send IPC message logs across channels.
72 struct IPC_EXPORT LogData {
73 LogData();
74 ~LogData();
76 std::string channel;
77 int32 routing_id;
78 uint32 type; // "User-defined" message type, from ipc_message.h.
79 std::string flags;
80 int64 sent; // Time that the message was sent (i.e. at Send()).
81 int64 receive; // Time before it was dispatched (i.e. before calling
82 // OnMessageReceived).
83 int64 dispatch; // Time after it was dispatched (i.e. after calling
84 // OnMessageReceived).
85 std::string message_name;
86 std::string params;
89 //-----------------------------------------------------------------------------
91 // A dummy struct to place first just to allow leading commas for all
92 // members in the macro-generated constructor initializer lists.
93 struct NoParams {
96 template <class P>
97 static inline void WriteParam(Message* m, const P& p) {
98 typedef typename SimilarTypeTraits<P>::Type Type;
99 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
102 template <class P>
103 static inline bool WARN_UNUSED_RESULT
104 ReadParam(const Message* m, base::PickleIterator* iter, P* p) {
105 typedef typename SimilarTypeTraits<P>::Type Type;
106 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
109 template <class P>
110 static inline void LogParam(const P& p, std::string* l) {
111 typedef typename SimilarTypeTraits<P>::Type Type;
112 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
115 // Primitive ParamTraits -------------------------------------------------------
117 template <>
118 struct ParamTraits<bool> {
119 typedef bool param_type;
120 static void Write(Message* m, const param_type& p) {
121 m->WriteBool(p);
123 static bool Read(const Message* m,
124 base::PickleIterator* iter,
125 param_type* r) {
126 return iter->ReadBool(r);
128 IPC_EXPORT static void Log(const param_type& p, std::string* l);
131 template <>
132 struct IPC_EXPORT ParamTraits<unsigned char> {
133 typedef unsigned char param_type;
134 static void Write(Message* m, const param_type& p);
135 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
136 static void Log(const param_type& p, std::string* l);
139 template <>
140 struct IPC_EXPORT ParamTraits<unsigned short> {
141 typedef unsigned short param_type;
142 static void Write(Message* m, const param_type& p);
143 static bool Read(const Message* m,
144 base::PickleIterator* iter,
145 param_type* r);
146 static void Log(const param_type& p, std::string* l);
149 template <>
150 struct ParamTraits<int> {
151 typedef int param_type;
152 static void Write(Message* m, const param_type& p) {
153 m->WriteInt(p);
155 static bool Read(const Message* m,
156 base::PickleIterator* iter,
157 param_type* r) {
158 return iter->ReadInt(r);
160 IPC_EXPORT static void Log(const param_type& p, std::string* l);
163 template <>
164 struct ParamTraits<unsigned int> {
165 typedef unsigned int param_type;
166 static void Write(Message* m, const param_type& p) {
167 m->WriteInt(p);
169 static bool Read(const Message* m,
170 base::PickleIterator* iter,
171 param_type* r) {
172 return iter->ReadInt(reinterpret_cast<int*>(r));
174 IPC_EXPORT static void Log(const param_type& p, std::string* l);
177 template <>
178 struct ParamTraits<long> {
179 typedef long param_type;
180 static void Write(Message* m, const param_type& p) {
181 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
183 static bool Read(const Message* m,
184 base::PickleIterator* iter,
185 param_type* r) {
186 return iter->ReadLong(r);
188 IPC_EXPORT static void Log(const param_type& p, std::string* l);
191 template <>
192 struct ParamTraits<unsigned long> {
193 typedef unsigned long param_type;
194 static void Write(Message* m, const param_type& p) {
195 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
197 static bool Read(const Message* m,
198 base::PickleIterator* iter,
199 param_type* r) {
200 return iter->ReadLong(reinterpret_cast<long*>(r));
202 IPC_EXPORT static void Log(const param_type& p, std::string* l);
205 template <>
206 struct ParamTraits<long long> {
207 typedef long long param_type;
208 static void Write(Message* m, const param_type& p) {
209 m->WriteInt64(static_cast<int64>(p));
211 static bool Read(const Message* m,
212 base::PickleIterator* iter,
213 param_type* r) {
214 return iter->ReadInt64(reinterpret_cast<int64*>(r));
216 IPC_EXPORT static void Log(const param_type& p, std::string* l);
219 template <>
220 struct ParamTraits<unsigned long long> {
221 typedef unsigned long long param_type;
222 static void Write(Message* m, const param_type& p) {
223 m->WriteInt64(p);
225 static bool Read(const Message* m,
226 base::PickleIterator* iter,
227 param_type* r) {
228 return iter->ReadInt64(reinterpret_cast<int64*>(r));
230 IPC_EXPORT static void Log(const param_type& p, std::string* l);
233 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
234 // should be sure to check the sanity of these values after receiving them over
235 // IPC.
236 template <>
237 struct IPC_EXPORT ParamTraits<float> {
238 typedef float param_type;
239 static void Write(Message* m, const param_type& p) {
240 m->WriteFloat(p);
242 static bool Read(const Message* m,
243 base::PickleIterator* iter,
244 param_type* r) {
245 return iter->ReadFloat(r);
247 static void Log(const param_type& p, std::string* l);
250 template <>
251 struct IPC_EXPORT ParamTraits<double> {
252 typedef double param_type;
253 static void Write(Message* m, const param_type& p);
254 static bool Read(const Message* m,
255 base::PickleIterator* iter,
256 param_type* r);
257 static void Log(const param_type& p, std::string* l);
260 // STL ParamTraits -------------------------------------------------------------
262 template <>
263 struct ParamTraits<std::string> {
264 typedef std::string param_type;
265 static void Write(Message* m, const param_type& p) {
266 m->WriteString(p);
268 static bool Read(const Message* m,
269 base::PickleIterator* iter,
270 param_type* r) {
271 return iter->ReadString(r);
273 IPC_EXPORT static void Log(const param_type& p, std::string* l);
276 template <>
277 struct ParamTraits<base::string16> {
278 typedef base::string16 param_type;
279 static void Write(Message* m, const param_type& p) {
280 m->WriteString16(p);
282 static bool Read(const Message* m,
283 base::PickleIterator* iter,
284 param_type* r) {
285 return iter->ReadString16(r);
287 IPC_EXPORT static void Log(const param_type& p, std::string* l);
290 template <>
291 struct IPC_EXPORT ParamTraits<std::vector<char> > {
292 typedef std::vector<char> param_type;
293 static void Write(Message* m, const param_type& p);
294 static bool Read(const Message*,
295 base::PickleIterator* iter,
296 param_type* r);
297 static void Log(const param_type& p, std::string* l);
300 template <>
301 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
302 typedef std::vector<unsigned char> param_type;
303 static void Write(Message* m, const param_type& p);
304 static bool Read(const Message* m,
305 base::PickleIterator* iter,
306 param_type* r);
307 static void Log(const param_type& p, std::string* l);
310 template <>
311 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
312 typedef std::vector<bool> param_type;
313 static void Write(Message* m, const param_type& p);
314 static bool Read(const Message* m,
315 base::PickleIterator* iter,
316 param_type* r);
317 static void Log(const param_type& p, std::string* l);
320 template <class P>
321 struct ParamTraits<std::vector<P> > {
322 typedef std::vector<P> param_type;
323 static void Write(Message* m, const param_type& p) {
324 WriteParam(m, static_cast<int>(p.size()));
325 for (size_t i = 0; i < p.size(); i++)
326 WriteParam(m, p[i]);
328 static bool Read(const Message* m,
329 base::PickleIterator* iter,
330 param_type* r) {
331 int size;
332 // ReadLength() checks for < 0 itself.
333 if (!iter->ReadLength(&size))
334 return false;
335 // Resizing beforehand is not safe, see BUG 1006367 for details.
336 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
337 return false;
338 r->resize(size);
339 for (int i = 0; i < size; i++) {
340 if (!ReadParam(m, iter, &(*r)[i]))
341 return false;
343 return true;
345 static void Log(const param_type& p, std::string* l) {
346 for (size_t i = 0; i < p.size(); ++i) {
347 if (i != 0)
348 l->append(" ");
349 LogParam((p[i]), l);
354 template <class P>
355 struct ParamTraits<std::set<P> > {
356 typedef std::set<P> param_type;
357 static void Write(Message* m, const param_type& p) {
358 WriteParam(m, static_cast<int>(p.size()));
359 typename param_type::const_iterator iter;
360 for (iter = p.begin(); iter != p.end(); ++iter)
361 WriteParam(m, *iter);
363 static bool Read(const Message* m,
364 base::PickleIterator* iter,
365 param_type* r) {
366 int size;
367 if (!iter->ReadLength(&size))
368 return false;
369 for (int i = 0; i < size; ++i) {
370 P item;
371 if (!ReadParam(m, iter, &item))
372 return false;
373 r->insert(item);
375 return true;
377 static void Log(const param_type& p, std::string* l) {
378 l->append("<std::set>");
382 template <class K, class V, class C, class A>
383 struct ParamTraits<std::map<K, V, C, A> > {
384 typedef std::map<K, V, C, A> param_type;
385 static void Write(Message* m, const param_type& p) {
386 WriteParam(m, static_cast<int>(p.size()));
387 typename param_type::const_iterator iter;
388 for (iter = p.begin(); iter != p.end(); ++iter) {
389 WriteParam(m, iter->first);
390 WriteParam(m, iter->second);
393 static bool Read(const Message* m,
394 base::PickleIterator* iter,
395 param_type* r) {
396 int size;
397 if (!ReadParam(m, iter, &size) || size < 0)
398 return false;
399 for (int i = 0; i < size; ++i) {
400 K k;
401 if (!ReadParam(m, iter, &k))
402 return false;
403 V& value = (*r)[k];
404 if (!ReadParam(m, iter, &value))
405 return false;
407 return true;
409 static void Log(const param_type& p, std::string* l) {
410 l->append("<std::map>");
414 template <class A, class B>
415 struct ParamTraits<std::pair<A, B> > {
416 typedef std::pair<A, B> param_type;
417 static void Write(Message* m, const param_type& p) {
418 WriteParam(m, p.first);
419 WriteParam(m, p.second);
421 static bool Read(const Message* m,
422 base::PickleIterator* iter,
423 param_type* r) {
424 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
426 static void Log(const param_type& p, std::string* l) {
427 l->append("(");
428 LogParam(p.first, l);
429 l->append(", ");
430 LogParam(p.second, l);
431 l->append(")");
435 // Base ParamTraits ------------------------------------------------------------
437 template <>
438 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
439 typedef base::DictionaryValue param_type;
440 static void Write(Message* m, const param_type& p);
441 static bool Read(const Message* m,
442 base::PickleIterator* iter,
443 param_type* r);
444 static void Log(const param_type& p, std::string* l);
447 #if defined(OS_POSIX)
448 // FileDescriptors may be serialised over IPC channels on POSIX. On the
449 // receiving side, the FileDescriptor is a valid duplicate of the file
450 // descriptor which was transmitted: *it is not just a copy of the integer like
451 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
452 // this case, the receiving end will see a value of -1. *Zero is a valid file
453 // descriptor*.
455 // The received file descriptor will have the |auto_close| flag set to true. The
456 // code which handles the message is responsible for taking ownership of it.
457 // File descriptors are OS resources and must be closed when no longer needed.
459 // When sending a file descriptor, the file descriptor must be valid at the time
460 // of transmission. Since transmission is not synchronous, one should consider
461 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
462 // flag, which causes the file descriptor to be closed after writing.
463 template<>
464 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
465 typedef base::FileDescriptor param_type;
466 static void Write(Message* m, const param_type& p);
467 static bool Read(const Message* m,
468 base::PickleIterator* iter,
469 param_type* r);
470 static void Log(const param_type& p, std::string* l);
472 #endif // defined(OS_POSIX)
474 #if defined(OS_MACOSX) && !defined(OS_IOS)
475 template <>
476 struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
477 typedef base::SharedMemoryHandle param_type;
478 static void Write(Message* m, const param_type& p);
479 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
480 static void Log(const param_type& p, std::string* l);
482 #endif
484 template <>
485 struct IPC_EXPORT ParamTraits<base::FilePath> {
486 typedef base::FilePath param_type;
487 static void Write(Message* m, const param_type& p);
488 static bool Read(const Message* m,
489 base::PickleIterator* iter,
490 param_type* r);
491 static void Log(const param_type& p, std::string* l);
494 template <>
495 struct IPC_EXPORT ParamTraits<base::ListValue> {
496 typedef base::ListValue param_type;
497 static void Write(Message* m, const param_type& p);
498 static bool Read(const Message* m,
499 base::PickleIterator* iter,
500 param_type* r);
501 static void Log(const param_type& p, std::string* l);
504 template <>
505 struct IPC_EXPORT ParamTraits<base::NullableString16> {
506 typedef base::NullableString16 param_type;
507 static void Write(Message* m, const param_type& p);
508 static bool Read(const Message* m,
509 base::PickleIterator* iter,
510 param_type* r);
511 static void Log(const param_type& p, std::string* l);
514 template <>
515 struct IPC_EXPORT ParamTraits<base::File::Info> {
516 typedef base::File::Info param_type;
517 static void Write(Message* m, const param_type& p);
518 static bool Read(const Message* m,
519 base::PickleIterator* iter,
520 param_type* r);
521 static void Log(const param_type& p, std::string* l);
524 template <>
525 struct SimilarTypeTraits<base::File::Error> {
526 typedef int Type;
529 #if defined(OS_WIN)
530 template <>
531 struct SimilarTypeTraits<HWND> {
532 typedef HANDLE Type;
534 #endif // defined(OS_WIN)
536 template <>
537 struct IPC_EXPORT ParamTraits<base::Time> {
538 typedef base::Time param_type;
539 static void Write(Message* m, const param_type& p);
540 static bool Read(const Message* m,
541 base::PickleIterator* iter,
542 param_type* r);
543 static void Log(const param_type& p, std::string* l);
546 template <>
547 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
548 typedef base::TimeDelta param_type;
549 static void Write(Message* m, const param_type& p);
550 static bool Read(const Message* m,
551 base::PickleIterator* iter,
552 param_type* r);
553 static void Log(const param_type& p, std::string* l);
556 template <>
557 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
558 typedef base::TimeTicks param_type;
559 static void Write(Message* m, const param_type& p);
560 static bool Read(const Message* m,
561 base::PickleIterator* iter,
562 param_type* r);
563 static void Log(const param_type& p, std::string* l);
566 template <>
567 struct IPC_EXPORT ParamTraits<base::TraceTicks> {
568 typedef base::TraceTicks param_type;
569 static void Write(Message* m, const param_type& p);
570 static bool Read(const Message* m,
571 base::PickleIterator* iter,
572 param_type* r);
573 static void Log(const param_type& p, std::string* l);
576 template <>
577 struct ParamTraits<base::Tuple<>> {
578 typedef base::Tuple<> param_type;
579 static void Write(Message* m, const param_type& p) {
581 static bool Read(const Message* m,
582 base::PickleIterator* iter,
583 param_type* r) {
584 return true;
586 static void Log(const param_type& p, std::string* l) {
590 template <class A>
591 struct ParamTraits<base::Tuple<A>> {
592 typedef base::Tuple<A> param_type;
593 static void Write(Message* m, const param_type& p) {
594 WriteParam(m, base::get<0>(p));
596 static bool Read(const Message* m,
597 base::PickleIterator* iter,
598 param_type* r) {
599 return ReadParam(m, iter, &base::get<0>(*r));
601 static void Log(const param_type& p, std::string* l) {
602 LogParam(base::get<0>(p), l);
606 template <class A, class B>
607 struct ParamTraits<base::Tuple<A, B>> {
608 typedef base::Tuple<A, B> param_type;
609 static void Write(Message* m, const param_type& p) {
610 WriteParam(m, base::get<0>(p));
611 WriteParam(m, base::get<1>(p));
613 static bool Read(const Message* m,
614 base::PickleIterator* iter,
615 param_type* r) {
616 return (ReadParam(m, iter, &base::get<0>(*r)) &&
617 ReadParam(m, iter, &base::get<1>(*r)));
619 static void Log(const param_type& p, std::string* l) {
620 LogParam(base::get<0>(p), l);
621 l->append(", ");
622 LogParam(base::get<1>(p), l);
626 template <class A, class B, class C>
627 struct ParamTraits<base::Tuple<A, B, C>> {
628 typedef base::Tuple<A, B, C> param_type;
629 static void Write(Message* m, const param_type& p) {
630 WriteParam(m, base::get<0>(p));
631 WriteParam(m, base::get<1>(p));
632 WriteParam(m, base::get<2>(p));
634 static bool Read(const Message* m,
635 base::PickleIterator* iter,
636 param_type* r) {
637 return (ReadParam(m, iter, &base::get<0>(*r)) &&
638 ReadParam(m, iter, &base::get<1>(*r)) &&
639 ReadParam(m, iter, &base::get<2>(*r)));
641 static void Log(const param_type& p, std::string* l) {
642 LogParam(base::get<0>(p), l);
643 l->append(", ");
644 LogParam(base::get<1>(p), l);
645 l->append(", ");
646 LogParam(base::get<2>(p), l);
650 template <class A, class B, class C, class D>
651 struct ParamTraits<base::Tuple<A, B, C, D>> {
652 typedef base::Tuple<A, B, C, D> param_type;
653 static void Write(Message* m, const param_type& p) {
654 WriteParam(m, base::get<0>(p));
655 WriteParam(m, base::get<1>(p));
656 WriteParam(m, base::get<2>(p));
657 WriteParam(m, base::get<3>(p));
659 static bool Read(const Message* m,
660 base::PickleIterator* iter,
661 param_type* r) {
662 return (ReadParam(m, iter, &base::get<0>(*r)) &&
663 ReadParam(m, iter, &base::get<1>(*r)) &&
664 ReadParam(m, iter, &base::get<2>(*r)) &&
665 ReadParam(m, iter, &base::get<3>(*r)));
667 static void Log(const param_type& p, std::string* l) {
668 LogParam(base::get<0>(p), l);
669 l->append(", ");
670 LogParam(base::get<1>(p), l);
671 l->append(", ");
672 LogParam(base::get<2>(p), l);
673 l->append(", ");
674 LogParam(base::get<3>(p), l);
678 template <class A, class B, class C, class D, class E>
679 struct ParamTraits<base::Tuple<A, B, C, D, E>> {
680 typedef base::Tuple<A, B, C, D, E> param_type;
681 static void Write(Message* m, const param_type& p) {
682 WriteParam(m, base::get<0>(p));
683 WriteParam(m, base::get<1>(p));
684 WriteParam(m, base::get<2>(p));
685 WriteParam(m, base::get<3>(p));
686 WriteParam(m, base::get<4>(p));
688 static bool Read(const Message* m,
689 base::PickleIterator* iter,
690 param_type* r) {
691 return (ReadParam(m, iter, &base::get<0>(*r)) &&
692 ReadParam(m, iter, &base::get<1>(*r)) &&
693 ReadParam(m, iter, &base::get<2>(*r)) &&
694 ReadParam(m, iter, &base::get<3>(*r)) &&
695 ReadParam(m, iter, &base::get<4>(*r)));
697 static void Log(const param_type& p, std::string* l) {
698 LogParam(base::get<0>(p), l);
699 l->append(", ");
700 LogParam(base::get<1>(p), l);
701 l->append(", ");
702 LogParam(base::get<2>(p), l);
703 l->append(", ");
704 LogParam(base::get<3>(p), l);
705 l->append(", ");
706 LogParam(base::get<4>(p), l);
710 template<class P>
711 struct ParamTraits<ScopedVector<P> > {
712 typedef ScopedVector<P> param_type;
713 static void Write(Message* m, const param_type& p) {
714 WriteParam(m, static_cast<int>(p.size()));
715 for (size_t i = 0; i < p.size(); i++)
716 WriteParam(m, *p[i]);
718 static bool Read(const Message* m,
719 base::PickleIterator* iter,
720 param_type* r) {
721 int size = 0;
722 if (!iter->ReadLength(&size))
723 return false;
724 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
725 return false;
726 r->resize(size);
727 for (int i = 0; i < size; i++) {
728 (*r)[i] = new P();
729 if (!ReadParam(m, iter, (*r)[i]))
730 return false;
732 return true;
734 static void Log(const param_type& p, std::string* l) {
735 for (size_t i = 0; i < p.size(); ++i) {
736 if (i != 0)
737 l->append(" ");
738 LogParam(*p[i], l);
743 template <typename NormalMap,
744 int kArraySize,
745 typename EqualKey,
746 typename MapInit>
747 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
748 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
749 typedef typename param_type::key_type K;
750 typedef typename param_type::data_type V;
751 static void Write(Message* m, const param_type& p) {
752 WriteParam(m, static_cast<int>(p.size()));
753 typename param_type::const_iterator iter;
754 for (iter = p.begin(); iter != p.end(); ++iter) {
755 WriteParam(m, iter->first);
756 WriteParam(m, iter->second);
759 static bool Read(const Message* m,
760 base::PickleIterator* iter,
761 param_type* r) {
762 int size;
763 if (!iter->ReadLength(&size))
764 return false;
765 for (int i = 0; i < size; ++i) {
766 K key;
767 if (!ReadParam(m, iter, &key))
768 return false;
769 V& value = (*r)[key];
770 if (!ReadParam(m, iter, &value))
771 return false;
773 return true;
775 static void Log(const param_type& p, std::string* l) {
776 l->append("<base::SmallMap>");
780 template <class P>
781 struct ParamTraits<scoped_ptr<P> > {
782 typedef scoped_ptr<P> param_type;
783 static void Write(Message* m, const param_type& p) {
784 bool valid = !!p;
785 WriteParam(m, valid);
786 if (valid)
787 WriteParam(m, *p);
789 static bool Read(const Message* m,
790 base::PickleIterator* iter,
791 param_type* r) {
792 bool valid = false;
793 if (!ReadParam(m, iter, &valid))
794 return false;
796 if (!valid) {
797 r->reset();
798 return true;
801 param_type temp(new P());
802 if (!ReadParam(m, iter, temp.get()))
803 return false;
805 r->swap(temp);
806 return true;
808 static void Log(const param_type& p, std::string* l) {
809 if (p)
810 LogParam(*p, l);
811 else
812 l->append("NULL");
816 // IPC types ParamTraits -------------------------------------------------------
818 // A ChannelHandle is basically a platform-inspecific wrapper around the
819 // fact that IPC endpoints are handled specially on POSIX. See above comments
820 // on FileDescriptor for more background.
821 template<>
822 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
823 typedef ChannelHandle param_type;
824 static void Write(Message* m, const param_type& p);
825 static bool Read(const Message* m,
826 base::PickleIterator* iter,
827 param_type* r);
828 static void Log(const param_type& p, std::string* l);
831 template <>
832 struct IPC_EXPORT ParamTraits<LogData> {
833 typedef LogData param_type;
834 static void Write(Message* m, const param_type& p);
835 static bool Read(const Message* m,
836 base::PickleIterator* iter,
837 param_type* r);
838 static void Log(const param_type& p, std::string* l);
841 template <>
842 struct IPC_EXPORT ParamTraits<Message> {
843 static void Write(Message* m, const Message& p);
844 static bool Read(const Message* m,
845 base::PickleIterator* iter,
846 Message* r);
847 static void Log(const Message& p, std::string* l);
850 // Windows ParamTraits ---------------------------------------------------------
852 #if defined(OS_WIN)
853 template <>
854 struct IPC_EXPORT ParamTraits<HANDLE> {
855 typedef HANDLE param_type;
856 static void Write(Message* m, const param_type& p);
857 static bool Read(const Message* m,
858 base::PickleIterator* iter,
859 param_type* r);
860 static void Log(const param_type& p, std::string* l);
863 template <>
864 struct IPC_EXPORT ParamTraits<LOGFONT> {
865 typedef LOGFONT param_type;
866 static void Write(Message* m, const param_type& p);
867 static bool Read(const Message* m,
868 base::PickleIterator* iter,
869 param_type* r);
870 static void Log(const param_type& p, std::string* l);
873 template <>
874 struct IPC_EXPORT ParamTraits<MSG> {
875 typedef MSG param_type;
876 static void Write(Message* m, const param_type& p);
877 static bool Read(const Message* m,
878 base::PickleIterator* iter,
879 param_type* r);
880 static void Log(const param_type& p, std::string* l);
882 #endif // defined(OS_WIN)
884 //-----------------------------------------------------------------------------
885 // Generic message subclasses
887 // Used for asynchronous messages.
888 template <class ParamType>
889 class MessageSchema {
890 public:
891 typedef ParamType Param;
892 typedef typename base::TupleTypes<ParamType>::ParamTuple RefParam;
894 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
895 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
898 // defined in ipc_logging.cc
899 IPC_EXPORT void GenerateLogData(const std::string& channel,
900 const Message& message,
901 LogData* data, bool get_params);
904 #if defined(IPC_MESSAGE_LOG_ENABLED)
905 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
906 const std::string& output_params = msg->output_params();
907 if (!l->empty() && !output_params.empty())
908 l->append(", ");
910 l->append(output_params);
913 template <class ReplyParamType>
914 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
915 const Message* msg) {
916 if (msg->received_time() != 0) {
917 std::string output_params;
918 LogParam(reply_params, &output_params);
919 msg->set_output_params(output_params);
923 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
924 if (msg->sent_time()) {
925 // Don't log the sync message after dispatch, as we don't have the
926 // output parameters at that point. Instead, save its data and log it
927 // with the outgoing reply message when it's sent.
928 LogData* data = new LogData;
929 GenerateLogData("", *msg, data, true);
930 msg->set_dont_log();
931 reply->set_sync_log_data(data);
934 #else
935 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
937 template <class ReplyParamType>
938 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
939 const Message* msg) {}
941 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
942 #endif
944 // This class assumes that its template argument is a RefTuple (a Tuple with
945 // reference elements). This would go into ipc_message_utils_impl.h, but it is
946 // also used by chrome_frame.
947 template <class RefTuple>
948 class ParamDeserializer : public MessageReplyDeserializer {
949 public:
950 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
952 bool SerializeOutputParameters(const IPC::Message& msg,
953 base::PickleIterator iter) override {
954 return ReadParam(&msg, &iter, &out_);
957 RefTuple out_;
960 // Used for synchronous messages.
961 template <class SendParamType, class ReplyParamType>
962 class SyncMessageSchema {
963 public:
964 typedef SendParamType SendParam;
965 typedef typename base::TupleTypes<SendParam>::ParamTuple RefSendParam;
966 typedef ReplyParamType ReplyParam;
968 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
969 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
970 static bool ReadReplyParam(
971 const Message* msg,
972 typename base::TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
974 template<class T, class S, class Method>
975 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
976 const Message* msg, T* obj, S* sender,
977 Method func) {
978 Message* reply = SyncMessage::GenerateReply(msg);
979 if (ok) {
980 typename base::TupleTypes<ReplyParam>::ValueTuple reply_params;
981 DispatchToMethod(obj, func, send_params, &reply_params);
982 WriteParam(reply, reply_params);
983 LogReplyParamsToMessage(reply_params, msg);
984 } else {
985 NOTREACHED() << "Error deserializing message " << msg->type();
986 reply->set_reply_error();
988 sender->Send(reply);
989 return ok;
992 template<class T, class Method>
993 static bool DispatchDelayReplyWithSendParams(bool ok,
994 const SendParam& send_params,
995 const Message* msg, T* obj,
996 Method func) {
997 Message* reply = SyncMessage::GenerateReply(msg);
998 if (ok) {
999 base::Tuple<Message&> t = base::MakeRefTuple(*reply);
1000 ConnectMessageAndReply(msg, reply);
1001 DispatchToMethod(obj, func, send_params, &t);
1002 } else {
1003 NOTREACHED() << "Error deserializing message " << msg->type();
1004 reply->set_reply_error();
1005 obj->Send(reply);
1007 return ok;
1010 template <typename... Ts>
1011 static void WriteReplyParams(Message* reply, Ts... args) {
1012 ReplyParam p(args...);
1013 WriteParam(reply, p);
1017 } // namespace IPC
1019 #endif // IPC_IPC_MESSAGE_UTILS_H_