ipc: Make sure that ChannelReader is destroyed correctly.
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blobd0c1f721bcc39a63afae9fa08dcd67bb506dc420
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 <stdint.h>
10 #include <algorithm>
11 #include <map>
12 #include <set>
13 #include <string>
14 #include <vector>
16 #include "base/containers/small_map.h"
17 #include "base/containers/stack_container.h"
18 #include "base/files/file.h"
19 #include "base/format_macros.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/memory/scoped_vector.h"
22 #include "base/strings/string16.h"
23 #include "base/strings/string_util.h"
24 #include "base/strings/stringprintf.h"
25 #include "base/tuple.h"
26 #include "ipc/brokerable_attachment.h"
27 #include "ipc/ipc_message_start.h"
28 #include "ipc/ipc_param_traits.h"
29 #include "ipc/ipc_sync_message.h"
31 #if defined(COMPILER_GCC)
32 // GCC "helpfully" tries to inline template methods in release mode. Except we
33 // want the majority of the template junk being expanded once in the
34 // implementation file (and only provide the definitions in
35 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
36 // at every call site. Special note: GCC happily accepts the attribute before
37 // the method declaration, but only acts on it if it is after.
38 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
39 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
40 // the introduced noclone attribute, which will create specialized versions of
41 // functions/methods when certain types are constant.
42 // www.gnu.org/software/gcc/gcc-4.5/changes.html
43 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
44 #else
45 #define IPC_MSG_NOINLINE __attribute__((noinline));
46 #endif
47 #elif defined(COMPILER_MSVC)
48 // MSVC++ doesn't do this.
49 #define IPC_MSG_NOINLINE
50 #else
51 #error "Please add the noinline property for your new compiler here."
52 #endif
54 namespace base {
55 class DictionaryValue;
56 class FilePath;
57 class ListValue;
58 class NullableString16;
59 class Time;
60 class TimeDelta;
61 class TimeTicks;
62 class TraceTicks;
63 struct FileDescriptor;
65 #if defined(OS_MACOSX) && !defined(OS_IOS)
66 class SharedMemoryHandle;
67 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
70 namespace IPC {
72 struct ChannelHandle;
74 // -----------------------------------------------------------------------------
75 // How we send IPC message logs across channels.
76 struct IPC_EXPORT LogData {
77 LogData();
78 ~LogData();
80 std::string channel;
81 int32_t routing_id;
82 uint32_t type; // "User-defined" message type, from ipc_message.h.
83 std::string flags;
84 int64_t sent; // Time that the message was sent (i.e. at Send()).
85 int64_t receive; // Time before it was dispatched (i.e. before calling
86 // OnMessageReceived).
87 int64_t dispatch; // Time after it was dispatched (i.e. after calling
88 // OnMessageReceived).
89 std::string message_name;
90 std::string params;
93 //-----------------------------------------------------------------------------
95 // A dummy struct to place first just to allow leading commas for all
96 // members in the macro-generated constructor initializer lists.
97 struct NoParams {
100 template <class P>
101 static inline void WriteParam(Message* m, const P& p) {
102 typedef typename SimilarTypeTraits<P>::Type Type;
103 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
106 template <class P>
107 static inline bool WARN_UNUSED_RESULT
108 ReadParam(const Message* m, base::PickleIterator* iter, P* p) {
109 typedef typename SimilarTypeTraits<P>::Type Type;
110 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
113 template <class P>
114 static inline void LogParam(const P& p, std::string* l) {
115 typedef typename SimilarTypeTraits<P>::Type Type;
116 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
119 // Primitive ParamTraits -------------------------------------------------------
121 template <>
122 struct ParamTraits<bool> {
123 typedef bool param_type;
124 static void Write(Message* m, const param_type& p) {
125 m->WriteBool(p);
127 static bool Read(const Message* m,
128 base::PickleIterator* iter,
129 param_type* r) {
130 return iter->ReadBool(r);
132 IPC_EXPORT static void Log(const param_type& p, std::string* l);
135 template <>
136 struct IPC_EXPORT ParamTraits<unsigned char> {
137 typedef unsigned char param_type;
138 static void Write(Message* m, const param_type& p);
139 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
140 static void Log(const param_type& p, std::string* l);
143 template <>
144 struct IPC_EXPORT ParamTraits<unsigned short> {
145 typedef unsigned short param_type;
146 static void Write(Message* m, const param_type& p);
147 static bool Read(const Message* m,
148 base::PickleIterator* iter,
149 param_type* r);
150 static void Log(const param_type& p, std::string* l);
153 template <>
154 struct ParamTraits<int> {
155 typedef int param_type;
156 static void Write(Message* m, const param_type& p) {
157 m->WriteInt(p);
159 static bool Read(const Message* m,
160 base::PickleIterator* iter,
161 param_type* r) {
162 return iter->ReadInt(r);
164 IPC_EXPORT static void Log(const param_type& p, std::string* l);
167 template <>
168 struct ParamTraits<unsigned int> {
169 typedef unsigned int param_type;
170 static void Write(Message* m, const param_type& p) {
171 m->WriteInt(p);
173 static bool Read(const Message* m,
174 base::PickleIterator* iter,
175 param_type* r) {
176 return iter->ReadInt(reinterpret_cast<int*>(r));
178 IPC_EXPORT static void Log(const param_type& p, std::string* l);
181 template <>
182 struct ParamTraits<long> {
183 typedef long param_type;
184 static void Write(Message* m, const param_type& p) {
185 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
187 static bool Read(const Message* m,
188 base::PickleIterator* iter,
189 param_type* r) {
190 return iter->ReadLong(r);
192 IPC_EXPORT static void Log(const param_type& p, std::string* l);
195 template <>
196 struct ParamTraits<unsigned long> {
197 typedef unsigned long param_type;
198 static void Write(Message* m, const param_type& p) {
199 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
201 static bool Read(const Message* m,
202 base::PickleIterator* iter,
203 param_type* r) {
204 return iter->ReadLong(reinterpret_cast<long*>(r));
206 IPC_EXPORT static void Log(const param_type& p, std::string* l);
209 template <>
210 struct ParamTraits<long long> {
211 typedef long long param_type;
212 static void Write(Message* m, const param_type& p) {
213 m->WriteInt64(static_cast<int64_t>(p));
215 static bool Read(const Message* m,
216 base::PickleIterator* iter,
217 param_type* r) {
218 return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
220 IPC_EXPORT static void Log(const param_type& p, std::string* l);
223 template <>
224 struct ParamTraits<unsigned long long> {
225 typedef unsigned long long param_type;
226 static void Write(Message* m, const param_type& p) {
227 m->WriteInt64(p);
229 static bool Read(const Message* m,
230 base::PickleIterator* iter,
231 param_type* r) {
232 return iter->ReadInt64(reinterpret_cast<int64_t*>(r));
234 IPC_EXPORT static void Log(const param_type& p, std::string* l);
237 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
238 // should be sure to check the sanity of these values after receiving them over
239 // IPC.
240 template <>
241 struct IPC_EXPORT ParamTraits<float> {
242 typedef float param_type;
243 static void Write(Message* m, const param_type& p) {
244 m->WriteFloat(p);
246 static bool Read(const Message* m,
247 base::PickleIterator* iter,
248 param_type* r) {
249 return iter->ReadFloat(r);
251 static void Log(const param_type& p, std::string* l);
254 template <>
255 struct IPC_EXPORT ParamTraits<double> {
256 typedef double param_type;
257 static void Write(Message* m, const param_type& p);
258 static bool Read(const Message* m,
259 base::PickleIterator* iter,
260 param_type* r);
261 static void Log(const param_type& p, std::string* l);
264 // STL ParamTraits -------------------------------------------------------------
266 template <>
267 struct ParamTraits<std::string> {
268 typedef std::string param_type;
269 static void Write(Message* m, const param_type& p) {
270 m->WriteString(p);
272 static bool Read(const Message* m,
273 base::PickleIterator* iter,
274 param_type* r) {
275 return iter->ReadString(r);
277 IPC_EXPORT static void Log(const param_type& p, std::string* l);
280 template <>
281 struct ParamTraits<base::string16> {
282 typedef base::string16 param_type;
283 static void Write(Message* m, const param_type& p) {
284 m->WriteString16(p);
286 static bool Read(const Message* m,
287 base::PickleIterator* iter,
288 param_type* r) {
289 return iter->ReadString16(r);
291 IPC_EXPORT static void Log(const param_type& p, std::string* l);
294 template <>
295 struct IPC_EXPORT ParamTraits<std::vector<char> > {
296 typedef std::vector<char> param_type;
297 static void Write(Message* m, const param_type& p);
298 static bool Read(const Message*,
299 base::PickleIterator* iter,
300 param_type* r);
301 static void Log(const param_type& p, std::string* l);
304 template <>
305 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
306 typedef std::vector<unsigned char> param_type;
307 static void Write(Message* m, const param_type& p);
308 static bool Read(const Message* m,
309 base::PickleIterator* iter,
310 param_type* r);
311 static void Log(const param_type& p, std::string* l);
314 template <>
315 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
316 typedef std::vector<bool> param_type;
317 static void Write(Message* m, const param_type& p);
318 static bool Read(const Message* m,
319 base::PickleIterator* iter,
320 param_type* r);
321 static void Log(const param_type& p, std::string* l);
324 template <class P>
325 struct ParamTraits<std::vector<P> > {
326 typedef std::vector<P> param_type;
327 static void Write(Message* m, const param_type& p) {
328 WriteParam(m, static_cast<int>(p.size()));
329 for (size_t i = 0; i < p.size(); i++)
330 WriteParam(m, p[i]);
332 static bool Read(const Message* m,
333 base::PickleIterator* iter,
334 param_type* r) {
335 int size;
336 // ReadLength() checks for < 0 itself.
337 if (!iter->ReadLength(&size))
338 return false;
339 // Resizing beforehand is not safe, see BUG 1006367 for details.
340 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
341 return false;
342 r->resize(size);
343 for (int i = 0; i < size; i++) {
344 if (!ReadParam(m, iter, &(*r)[i]))
345 return false;
347 return true;
349 static void Log(const param_type& p, std::string* l) {
350 for (size_t i = 0; i < p.size(); ++i) {
351 if (i != 0)
352 l->append(" ");
353 LogParam((p[i]), l);
358 template <class P>
359 struct ParamTraits<std::set<P> > {
360 typedef std::set<P> param_type;
361 static void Write(Message* m, const param_type& p) {
362 WriteParam(m, static_cast<int>(p.size()));
363 typename param_type::const_iterator iter;
364 for (iter = p.begin(); iter != p.end(); ++iter)
365 WriteParam(m, *iter);
367 static bool Read(const Message* m,
368 base::PickleIterator* iter,
369 param_type* r) {
370 int size;
371 if (!iter->ReadLength(&size))
372 return false;
373 for (int i = 0; i < size; ++i) {
374 P item;
375 if (!ReadParam(m, iter, &item))
376 return false;
377 r->insert(item);
379 return true;
381 static void Log(const param_type& p, std::string* l) {
382 l->append("<std::set>");
386 template <class K, class V, class C, class A>
387 struct ParamTraits<std::map<K, V, C, A> > {
388 typedef std::map<K, V, C, A> param_type;
389 static void Write(Message* m, const param_type& p) {
390 WriteParam(m, static_cast<int>(p.size()));
391 typename param_type::const_iterator iter;
392 for (iter = p.begin(); iter != p.end(); ++iter) {
393 WriteParam(m, iter->first);
394 WriteParam(m, iter->second);
397 static bool Read(const Message* m,
398 base::PickleIterator* iter,
399 param_type* r) {
400 int size;
401 if (!ReadParam(m, iter, &size) || size < 0)
402 return false;
403 for (int i = 0; i < size; ++i) {
404 K k;
405 if (!ReadParam(m, iter, &k))
406 return false;
407 V& value = (*r)[k];
408 if (!ReadParam(m, iter, &value))
409 return false;
411 return true;
413 static void Log(const param_type& p, std::string* l) {
414 l->append("<std::map>");
418 template <class A, class B>
419 struct ParamTraits<std::pair<A, B> > {
420 typedef std::pair<A, B> param_type;
421 static void Write(Message* m, const param_type& p) {
422 WriteParam(m, p.first);
423 WriteParam(m, p.second);
425 static bool Read(const Message* m,
426 base::PickleIterator* iter,
427 param_type* r) {
428 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
430 static void Log(const param_type& p, std::string* l) {
431 l->append("(");
432 LogParam(p.first, l);
433 l->append(", ");
434 LogParam(p.second, l);
435 l->append(")");
439 // IPC ParamTraits -------------------------------------------------------------
440 template <>
441 struct IPC_EXPORT ParamTraits<BrokerableAttachment::AttachmentId> {
442 typedef BrokerableAttachment::AttachmentId param_type;
443 static void Write(Message* m, const param_type& p);
444 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
445 static void Log(const param_type& p, std::string* l);
448 // Base ParamTraits ------------------------------------------------------------
450 template <>
451 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
452 typedef base::DictionaryValue param_type;
453 static void Write(Message* m, const param_type& p);
454 static bool Read(const Message* m,
455 base::PickleIterator* iter,
456 param_type* r);
457 static void Log(const param_type& p, std::string* l);
460 #if defined(OS_POSIX)
461 // FileDescriptors may be serialised over IPC channels on POSIX. On the
462 // receiving side, the FileDescriptor is a valid duplicate of the file
463 // descriptor which was transmitted: *it is not just a copy of the integer like
464 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
465 // this case, the receiving end will see a value of -1. *Zero is a valid file
466 // descriptor*.
468 // The received file descriptor will have the |auto_close| flag set to true. The
469 // code which handles the message is responsible for taking ownership of it.
470 // File descriptors are OS resources and must be closed when no longer needed.
472 // When sending a file descriptor, the file descriptor must be valid at the time
473 // of transmission. Since transmission is not synchronous, one should consider
474 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
475 // flag, which causes the file descriptor to be closed after writing.
476 template<>
477 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
478 typedef base::FileDescriptor param_type;
479 static void Write(Message* m, const param_type& p);
480 static bool Read(const Message* m,
481 base::PickleIterator* iter,
482 param_type* r);
483 static void Log(const param_type& p, std::string* l);
485 #endif // defined(OS_POSIX)
487 #if defined(OS_MACOSX) && !defined(OS_IOS)
488 template <>
489 struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
490 typedef base::SharedMemoryHandle param_type;
491 static void Write(Message* m, const param_type& p);
492 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
493 static void Log(const param_type& p, std::string* l);
495 #endif
497 template <>
498 struct IPC_EXPORT ParamTraits<base::FilePath> {
499 typedef base::FilePath param_type;
500 static void Write(Message* m, const param_type& p);
501 static bool Read(const Message* m,
502 base::PickleIterator* iter,
503 param_type* r);
504 static void Log(const param_type& p, std::string* l);
507 template <>
508 struct IPC_EXPORT ParamTraits<base::ListValue> {
509 typedef base::ListValue param_type;
510 static void Write(Message* m, const param_type& p);
511 static bool Read(const Message* m,
512 base::PickleIterator* iter,
513 param_type* r);
514 static void Log(const param_type& p, std::string* l);
517 template <>
518 struct IPC_EXPORT ParamTraits<base::NullableString16> {
519 typedef base::NullableString16 param_type;
520 static void Write(Message* m, const param_type& p);
521 static bool Read(const Message* m,
522 base::PickleIterator* iter,
523 param_type* r);
524 static void Log(const param_type& p, std::string* l);
527 template <>
528 struct IPC_EXPORT ParamTraits<base::File::Info> {
529 typedef base::File::Info param_type;
530 static void Write(Message* m, const param_type& p);
531 static bool Read(const Message* m,
532 base::PickleIterator* iter,
533 param_type* r);
534 static void Log(const param_type& p, std::string* l);
537 template <>
538 struct SimilarTypeTraits<base::File::Error> {
539 typedef int Type;
542 #if defined(OS_WIN)
543 template <>
544 struct SimilarTypeTraits<HWND> {
545 typedef HANDLE Type;
547 #endif // defined(OS_WIN)
549 template <>
550 struct IPC_EXPORT ParamTraits<base::Time> {
551 typedef base::Time param_type;
552 static void Write(Message* m, const param_type& p);
553 static bool Read(const Message* m,
554 base::PickleIterator* iter,
555 param_type* r);
556 static void Log(const param_type& p, std::string* l);
559 template <>
560 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
561 typedef base::TimeDelta param_type;
562 static void Write(Message* m, const param_type& p);
563 static bool Read(const Message* m,
564 base::PickleIterator* iter,
565 param_type* r);
566 static void Log(const param_type& p, std::string* l);
569 template <>
570 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
571 typedef base::TimeTicks param_type;
572 static void Write(Message* m, const param_type& p);
573 static bool Read(const Message* m,
574 base::PickleIterator* iter,
575 param_type* r);
576 static void Log(const param_type& p, std::string* l);
579 template <>
580 struct IPC_EXPORT ParamTraits<base::TraceTicks> {
581 typedef base::TraceTicks param_type;
582 static void Write(Message* m, const param_type& p);
583 static bool Read(const Message* m,
584 base::PickleIterator* iter,
585 param_type* r);
586 static void Log(const param_type& p, std::string* l);
589 template <>
590 struct ParamTraits<base::Tuple<>> {
591 typedef base::Tuple<> param_type;
592 static void Write(Message* m, const param_type& p) {
594 static bool Read(const Message* m,
595 base::PickleIterator* iter,
596 param_type* r) {
597 return true;
599 static void Log(const param_type& p, std::string* l) {
603 template <class A>
604 struct ParamTraits<base::Tuple<A>> {
605 typedef base::Tuple<A> param_type;
606 static void Write(Message* m, const param_type& p) {
607 WriteParam(m, base::get<0>(p));
609 static bool Read(const Message* m,
610 base::PickleIterator* iter,
611 param_type* r) {
612 return ReadParam(m, iter, &base::get<0>(*r));
614 static void Log(const param_type& p, std::string* l) {
615 LogParam(base::get<0>(p), l);
619 template <class A, class B>
620 struct ParamTraits<base::Tuple<A, B>> {
621 typedef base::Tuple<A, B> param_type;
622 static void Write(Message* m, const param_type& p) {
623 WriteParam(m, base::get<0>(p));
624 WriteParam(m, base::get<1>(p));
626 static bool Read(const Message* m,
627 base::PickleIterator* iter,
628 param_type* r) {
629 return (ReadParam(m, iter, &base::get<0>(*r)) &&
630 ReadParam(m, iter, &base::get<1>(*r)));
632 static void Log(const param_type& p, std::string* l) {
633 LogParam(base::get<0>(p), l);
634 l->append(", ");
635 LogParam(base::get<1>(p), l);
639 template <class A, class B, class C>
640 struct ParamTraits<base::Tuple<A, B, C>> {
641 typedef base::Tuple<A, B, C> param_type;
642 static void Write(Message* m, const param_type& p) {
643 WriteParam(m, base::get<0>(p));
644 WriteParam(m, base::get<1>(p));
645 WriteParam(m, base::get<2>(p));
647 static bool Read(const Message* m,
648 base::PickleIterator* iter,
649 param_type* r) {
650 return (ReadParam(m, iter, &base::get<0>(*r)) &&
651 ReadParam(m, iter, &base::get<1>(*r)) &&
652 ReadParam(m, iter, &base::get<2>(*r)));
654 static void Log(const param_type& p, std::string* l) {
655 LogParam(base::get<0>(p), l);
656 l->append(", ");
657 LogParam(base::get<1>(p), l);
658 l->append(", ");
659 LogParam(base::get<2>(p), l);
663 template <class A, class B, class C, class D>
664 struct ParamTraits<base::Tuple<A, B, C, D>> {
665 typedef base::Tuple<A, B, C, D> param_type;
666 static void Write(Message* m, const param_type& p) {
667 WriteParam(m, base::get<0>(p));
668 WriteParam(m, base::get<1>(p));
669 WriteParam(m, base::get<2>(p));
670 WriteParam(m, base::get<3>(p));
672 static bool Read(const Message* m,
673 base::PickleIterator* iter,
674 param_type* r) {
675 return (ReadParam(m, iter, &base::get<0>(*r)) &&
676 ReadParam(m, iter, &base::get<1>(*r)) &&
677 ReadParam(m, iter, &base::get<2>(*r)) &&
678 ReadParam(m, iter, &base::get<3>(*r)));
680 static void Log(const param_type& p, std::string* l) {
681 LogParam(base::get<0>(p), l);
682 l->append(", ");
683 LogParam(base::get<1>(p), l);
684 l->append(", ");
685 LogParam(base::get<2>(p), l);
686 l->append(", ");
687 LogParam(base::get<3>(p), l);
691 template <class A, class B, class C, class D, class E>
692 struct ParamTraits<base::Tuple<A, B, C, D, E>> {
693 typedef base::Tuple<A, B, C, D, E> param_type;
694 static void Write(Message* m, const param_type& p) {
695 WriteParam(m, base::get<0>(p));
696 WriteParam(m, base::get<1>(p));
697 WriteParam(m, base::get<2>(p));
698 WriteParam(m, base::get<3>(p));
699 WriteParam(m, base::get<4>(p));
701 static bool Read(const Message* m,
702 base::PickleIterator* iter,
703 param_type* r) {
704 return (ReadParam(m, iter, &base::get<0>(*r)) &&
705 ReadParam(m, iter, &base::get<1>(*r)) &&
706 ReadParam(m, iter, &base::get<2>(*r)) &&
707 ReadParam(m, iter, &base::get<3>(*r)) &&
708 ReadParam(m, iter, &base::get<4>(*r)));
710 static void Log(const param_type& p, std::string* l) {
711 LogParam(base::get<0>(p), l);
712 l->append(", ");
713 LogParam(base::get<1>(p), l);
714 l->append(", ");
715 LogParam(base::get<2>(p), l);
716 l->append(", ");
717 LogParam(base::get<3>(p), l);
718 l->append(", ");
719 LogParam(base::get<4>(p), l);
723 template<class P>
724 struct ParamTraits<ScopedVector<P> > {
725 typedef ScopedVector<P> param_type;
726 static void Write(Message* m, const param_type& p) {
727 WriteParam(m, static_cast<int>(p.size()));
728 for (size_t i = 0; i < p.size(); i++)
729 WriteParam(m, *p[i]);
731 static bool Read(const Message* m,
732 base::PickleIterator* iter,
733 param_type* r) {
734 int size = 0;
735 if (!iter->ReadLength(&size))
736 return false;
737 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
738 return false;
739 r->resize(size);
740 for (int i = 0; i < size; i++) {
741 (*r)[i] = new P();
742 if (!ReadParam(m, iter, (*r)[i]))
743 return false;
745 return true;
747 static void Log(const param_type& p, std::string* l) {
748 for (size_t i = 0; i < p.size(); ++i) {
749 if (i != 0)
750 l->append(" ");
751 LogParam(*p[i], l);
756 template <class P, size_t stack_capacity>
757 struct ParamTraits<base::StackVector<P, stack_capacity> > {
758 typedef base::StackVector<P, stack_capacity> param_type;
759 static void Write(Message* m, const param_type& p) {
760 WriteParam(m, static_cast<int>(p->size()));
761 for (size_t i = 0; i < p->size(); i++)
762 WriteParam(m, p[i]);
764 static bool Read(const Message* m,
765 base::PickleIterator* iter,
766 param_type* r) {
767 int size;
768 // ReadLength() checks for < 0 itself.
769 if (!iter->ReadLength(&size))
770 return false;
771 // Sanity check for the vector size.
772 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
773 return false;
774 P value;
775 for (int i = 0; i < size; i++) {
776 if (!ReadParam(m, iter, &value))
777 return false;
778 (*r)->push_back(value);
780 return true;
782 static void Log(const param_type& p, std::string* l) {
783 for (size_t i = 0; i < p->size(); ++i) {
784 if (i != 0)
785 l->append(" ");
786 LogParam((p[i]), l);
791 template <typename NormalMap,
792 int kArraySize,
793 typename EqualKey,
794 typename MapInit>
795 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
796 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
797 typedef typename param_type::key_type K;
798 typedef typename param_type::data_type V;
799 static void Write(Message* m, const param_type& p) {
800 WriteParam(m, static_cast<int>(p.size()));
801 typename param_type::const_iterator iter;
802 for (iter = p.begin(); iter != p.end(); ++iter) {
803 WriteParam(m, iter->first);
804 WriteParam(m, iter->second);
807 static bool Read(const Message* m,
808 base::PickleIterator* iter,
809 param_type* r) {
810 int size;
811 if (!iter->ReadLength(&size))
812 return false;
813 for (int i = 0; i < size; ++i) {
814 K key;
815 if (!ReadParam(m, iter, &key))
816 return false;
817 V& value = (*r)[key];
818 if (!ReadParam(m, iter, &value))
819 return false;
821 return true;
823 static void Log(const param_type& p, std::string* l) {
824 l->append("<base::SmallMap>");
828 template <class P>
829 struct ParamTraits<scoped_ptr<P> > {
830 typedef scoped_ptr<P> param_type;
831 static void Write(Message* m, const param_type& p) {
832 bool valid = !!p;
833 WriteParam(m, valid);
834 if (valid)
835 WriteParam(m, *p);
837 static bool Read(const Message* m,
838 base::PickleIterator* iter,
839 param_type* r) {
840 bool valid = false;
841 if (!ReadParam(m, iter, &valid))
842 return false;
844 if (!valid) {
845 r->reset();
846 return true;
849 param_type temp(new P());
850 if (!ReadParam(m, iter, temp.get()))
851 return false;
853 r->swap(temp);
854 return true;
856 static void Log(const param_type& p, std::string* l) {
857 if (p)
858 LogParam(*p, l);
859 else
860 l->append("NULL");
864 // IPC types ParamTraits -------------------------------------------------------
866 // A ChannelHandle is basically a platform-inspecific wrapper around the
867 // fact that IPC endpoints are handled specially on POSIX. See above comments
868 // on FileDescriptor for more background.
869 template<>
870 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
871 typedef ChannelHandle param_type;
872 static void Write(Message* m, const param_type& p);
873 static bool Read(const Message* m,
874 base::PickleIterator* iter,
875 param_type* r);
876 static void Log(const param_type& p, std::string* l);
879 template <>
880 struct IPC_EXPORT ParamTraits<LogData> {
881 typedef LogData param_type;
882 static void Write(Message* m, const param_type& p);
883 static bool Read(const Message* m,
884 base::PickleIterator* iter,
885 param_type* r);
886 static void Log(const param_type& p, std::string* l);
889 template <>
890 struct IPC_EXPORT ParamTraits<Message> {
891 static void Write(Message* m, const Message& p);
892 static bool Read(const Message* m,
893 base::PickleIterator* iter,
894 Message* r);
895 static void Log(const Message& p, std::string* l);
898 // Windows ParamTraits ---------------------------------------------------------
900 #if defined(OS_WIN)
901 template <>
902 struct IPC_EXPORT ParamTraits<HANDLE> {
903 typedef HANDLE param_type;
904 static void Write(Message* m, const param_type& p);
905 static bool Read(const Message* m,
906 base::PickleIterator* iter,
907 param_type* r);
908 static void Log(const param_type& p, std::string* l);
911 template <>
912 struct IPC_EXPORT ParamTraits<LOGFONT> {
913 typedef LOGFONT param_type;
914 static void Write(Message* m, const param_type& p);
915 static bool Read(const Message* m,
916 base::PickleIterator* iter,
917 param_type* r);
918 static void Log(const param_type& p, std::string* l);
921 template <>
922 struct IPC_EXPORT ParamTraits<MSG> {
923 typedef MSG param_type;
924 static void Write(Message* m, const param_type& p);
925 static bool Read(const Message* m,
926 base::PickleIterator* iter,
927 param_type* r);
928 static void Log(const param_type& p, std::string* l);
930 #endif // defined(OS_WIN)
932 //-----------------------------------------------------------------------------
933 // Generic message subclasses
935 // Used for asynchronous messages.
936 template <class ParamType>
937 class MessageSchema {
938 public:
939 typedef ParamType Param;
940 typedef typename base::TupleTypes<ParamType>::ParamTuple RefParam;
942 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
943 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
946 // defined in ipc_logging.cc
947 IPC_EXPORT void GenerateLogData(const std::string& channel,
948 const Message& message,
949 LogData* data, bool get_params);
952 #if defined(IPC_MESSAGE_LOG_ENABLED)
953 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
954 const std::string& output_params = msg->output_params();
955 if (!l->empty() && !output_params.empty())
956 l->append(", ");
958 l->append(output_params);
961 template <class ReplyParamType>
962 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
963 const Message* msg) {
964 if (msg->received_time() != 0) {
965 std::string output_params;
966 LogParam(reply_params, &output_params);
967 msg->set_output_params(output_params);
971 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
972 if (msg->sent_time()) {
973 // Don't log the sync message after dispatch, as we don't have the
974 // output parameters at that point. Instead, save its data and log it
975 // with the outgoing reply message when it's sent.
976 LogData* data = new LogData;
977 GenerateLogData("", *msg, data, true);
978 msg->set_dont_log();
979 reply->set_sync_log_data(data);
982 #else
983 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
985 template <class ReplyParamType>
986 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
987 const Message* msg) {}
989 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
990 #endif
992 // This class assumes that its template argument is a RefTuple (a Tuple with
993 // reference elements). This would go into ipc_message_utils_impl.h, but it is
994 // also used by chrome_frame.
995 template <class RefTuple>
996 class ParamDeserializer : public MessageReplyDeserializer {
997 public:
998 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
1000 bool SerializeOutputParameters(const IPC::Message& msg,
1001 base::PickleIterator iter) override {
1002 return ReadParam(&msg, &iter, &out_);
1005 RefTuple out_;
1008 // Used for synchronous messages.
1009 template <class SendParamType, class ReplyParamType>
1010 class SyncMessageSchema {
1011 public:
1012 typedef SendParamType SendParam;
1013 typedef typename base::TupleTypes<SendParam>::ParamTuple RefSendParam;
1014 typedef ReplyParamType ReplyParam;
1016 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
1017 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
1018 static bool ReadReplyParam(
1019 const Message* msg,
1020 typename base::TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
1022 template<class T, class S, class Method>
1023 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
1024 const Message* msg, T* obj, S* sender,
1025 Method func) {
1026 Message* reply = SyncMessage::GenerateReply(msg);
1027 if (ok) {
1028 typename base::TupleTypes<ReplyParam>::ValueTuple reply_params;
1029 DispatchToMethod(obj, func, send_params, &reply_params);
1030 WriteParam(reply, reply_params);
1031 LogReplyParamsToMessage(reply_params, msg);
1032 } else {
1033 NOTREACHED() << "Error deserializing message " << msg->type();
1034 reply->set_reply_error();
1036 sender->Send(reply);
1037 return ok;
1040 template<class T, class Method>
1041 static bool DispatchDelayReplyWithSendParams(bool ok,
1042 const SendParam& send_params,
1043 const Message* msg, T* obj,
1044 Method func) {
1045 Message* reply = SyncMessage::GenerateReply(msg);
1046 if (ok) {
1047 base::Tuple<Message&> t = base::MakeRefTuple(*reply);
1048 ConnectMessageAndReply(msg, reply);
1049 DispatchToMethod(obj, func, send_params, &t);
1050 } else {
1051 NOTREACHED() << "Error deserializing message " << msg->type();
1052 reply->set_reply_error();
1053 obj->Send(reply);
1055 return ok;
1058 template <typename... Ts>
1059 static void WriteReplyParams(Message* reply, Ts... args) {
1060 ReplyParam p(args...);
1061 WriteParam(reply, p);
1065 } // namespace IPC
1067 #endif // IPC_IPC_MESSAGE_UTILS_H_