Add ICU message format support
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blob9d70aff58bcb761aecc638d1c24a6229d7501c08
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/containers/stack_container.h"
16 #include "base/files/file.h"
17 #include "base/format_macros.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/scoped_vector.h"
20 #include "base/strings/string16.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/tuple.h"
24 #include "ipc/brokerable_attachment.h"
25 #include "ipc/ipc_message_start.h"
26 #include "ipc/ipc_param_traits.h"
27 #include "ipc/ipc_sync_message.h"
29 #if defined(COMPILER_GCC)
30 // GCC "helpfully" tries to inline template methods in release mode. Except we
31 // want the majority of the template junk being expanded once in the
32 // implementation file (and only provide the definitions in
33 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
34 // at every call site. Special note: GCC happily accepts the attribute before
35 // the method declaration, but only acts on it if it is after.
36 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
37 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
38 // the introduced noclone attribute, which will create specialized versions of
39 // functions/methods when certain types are constant.
40 // www.gnu.org/software/gcc/gcc-4.5/changes.html
41 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
42 #else
43 #define IPC_MSG_NOINLINE __attribute__((noinline));
44 #endif
45 #elif defined(COMPILER_MSVC)
46 // MSVC++ doesn't do this.
47 #define IPC_MSG_NOINLINE
48 #else
49 #error "Please add the noinline property for your new compiler here."
50 #endif
52 namespace base {
53 class DictionaryValue;
54 class FilePath;
55 class ListValue;
56 class NullableString16;
57 class Time;
58 class TimeDelta;
59 class TimeTicks;
60 class TraceTicks;
61 struct FileDescriptor;
63 #if defined(OS_MACOSX) && !defined(OS_IOS)
64 class SharedMemoryHandle;
65 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
68 namespace IPC {
70 struct ChannelHandle;
72 // -----------------------------------------------------------------------------
73 // How we send IPC message logs across channels.
74 struct IPC_EXPORT LogData {
75 LogData();
76 ~LogData();
78 std::string channel;
79 int32 routing_id;
80 uint32 type; // "User-defined" message type, from ipc_message.h.
81 std::string flags;
82 int64 sent; // Time that the message was sent (i.e. at Send()).
83 int64 receive; // Time before it was dispatched (i.e. before calling
84 // OnMessageReceived).
85 int64 dispatch; // Time after it was dispatched (i.e. after calling
86 // OnMessageReceived).
87 std::string message_name;
88 std::string params;
91 //-----------------------------------------------------------------------------
93 // A dummy struct to place first just to allow leading commas for all
94 // members in the macro-generated constructor initializer lists.
95 struct NoParams {
98 template <class P>
99 static inline void WriteParam(Message* m, const P& p) {
100 typedef typename SimilarTypeTraits<P>::Type Type;
101 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
104 template <class P>
105 static inline bool WARN_UNUSED_RESULT
106 ReadParam(const Message* m, base::PickleIterator* iter, P* p) {
107 typedef typename SimilarTypeTraits<P>::Type Type;
108 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
111 template <class P>
112 static inline void LogParam(const P& p, std::string* l) {
113 typedef typename SimilarTypeTraits<P>::Type Type;
114 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
117 // Primitive ParamTraits -------------------------------------------------------
119 template <>
120 struct ParamTraits<bool> {
121 typedef bool param_type;
122 static void Write(Message* m, const param_type& p) {
123 m->WriteBool(p);
125 static bool Read(const Message* m,
126 base::PickleIterator* iter,
127 param_type* r) {
128 return iter->ReadBool(r);
130 IPC_EXPORT static void Log(const param_type& p, std::string* l);
133 template <>
134 struct IPC_EXPORT ParamTraits<unsigned char> {
135 typedef unsigned char param_type;
136 static void Write(Message* m, const param_type& p);
137 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
138 static void Log(const param_type& p, std::string* l);
141 template <>
142 struct IPC_EXPORT ParamTraits<unsigned short> {
143 typedef unsigned short param_type;
144 static void Write(Message* m, const param_type& p);
145 static bool Read(const Message* m,
146 base::PickleIterator* iter,
147 param_type* r);
148 static void Log(const param_type& p, std::string* l);
151 template <>
152 struct ParamTraits<int> {
153 typedef int param_type;
154 static void Write(Message* m, const param_type& p) {
155 m->WriteInt(p);
157 static bool Read(const Message* m,
158 base::PickleIterator* iter,
159 param_type* r) {
160 return iter->ReadInt(r);
162 IPC_EXPORT static void Log(const param_type& p, std::string* l);
165 template <>
166 struct ParamTraits<unsigned int> {
167 typedef unsigned int param_type;
168 static void Write(Message* m, const param_type& p) {
169 m->WriteInt(p);
171 static bool Read(const Message* m,
172 base::PickleIterator* iter,
173 param_type* r) {
174 return iter->ReadInt(reinterpret_cast<int*>(r));
176 IPC_EXPORT static void Log(const param_type& p, std::string* l);
179 template <>
180 struct ParamTraits<long> {
181 typedef long param_type;
182 static void Write(Message* m, const param_type& p) {
183 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
185 static bool Read(const Message* m,
186 base::PickleIterator* iter,
187 param_type* r) {
188 return iter->ReadLong(r);
190 IPC_EXPORT static void Log(const param_type& p, std::string* l);
193 template <>
194 struct ParamTraits<unsigned long> {
195 typedef unsigned long param_type;
196 static void Write(Message* m, const param_type& p) {
197 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
199 static bool Read(const Message* m,
200 base::PickleIterator* iter,
201 param_type* r) {
202 return iter->ReadLong(reinterpret_cast<long*>(r));
204 IPC_EXPORT static void Log(const param_type& p, std::string* l);
207 template <>
208 struct ParamTraits<long long> {
209 typedef long long param_type;
210 static void Write(Message* m, const param_type& p) {
211 m->WriteInt64(static_cast<int64>(p));
213 static bool Read(const Message* m,
214 base::PickleIterator* iter,
215 param_type* r) {
216 return iter->ReadInt64(reinterpret_cast<int64*>(r));
218 IPC_EXPORT static void Log(const param_type& p, std::string* l);
221 template <>
222 struct ParamTraits<unsigned long long> {
223 typedef unsigned long long param_type;
224 static void Write(Message* m, const param_type& p) {
225 m->WriteInt64(p);
227 static bool Read(const Message* m,
228 base::PickleIterator* iter,
229 param_type* r) {
230 return iter->ReadInt64(reinterpret_cast<int64*>(r));
232 IPC_EXPORT static void Log(const param_type& p, std::string* l);
235 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
236 // should be sure to check the sanity of these values after receiving them over
237 // IPC.
238 template <>
239 struct IPC_EXPORT ParamTraits<float> {
240 typedef float param_type;
241 static void Write(Message* m, const param_type& p) {
242 m->WriteFloat(p);
244 static bool Read(const Message* m,
245 base::PickleIterator* iter,
246 param_type* r) {
247 return iter->ReadFloat(r);
249 static void Log(const param_type& p, std::string* l);
252 template <>
253 struct IPC_EXPORT ParamTraits<double> {
254 typedef double param_type;
255 static void Write(Message* m, const param_type& p);
256 static bool Read(const Message* m,
257 base::PickleIterator* iter,
258 param_type* r);
259 static void Log(const param_type& p, std::string* l);
262 // STL ParamTraits -------------------------------------------------------------
264 template <>
265 struct ParamTraits<std::string> {
266 typedef std::string param_type;
267 static void Write(Message* m, const param_type& p) {
268 m->WriteString(p);
270 static bool Read(const Message* m,
271 base::PickleIterator* iter,
272 param_type* r) {
273 return iter->ReadString(r);
275 IPC_EXPORT static void Log(const param_type& p, std::string* l);
278 template <>
279 struct ParamTraits<base::string16> {
280 typedef base::string16 param_type;
281 static void Write(Message* m, const param_type& p) {
282 m->WriteString16(p);
284 static bool Read(const Message* m,
285 base::PickleIterator* iter,
286 param_type* r) {
287 return iter->ReadString16(r);
289 IPC_EXPORT static void Log(const param_type& p, std::string* l);
292 template <>
293 struct IPC_EXPORT ParamTraits<std::vector<char> > {
294 typedef std::vector<char> param_type;
295 static void Write(Message* m, const param_type& p);
296 static bool Read(const Message*,
297 base::PickleIterator* iter,
298 param_type* r);
299 static void Log(const param_type& p, std::string* l);
302 template <>
303 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
304 typedef std::vector<unsigned char> param_type;
305 static void Write(Message* m, const param_type& p);
306 static bool Read(const Message* m,
307 base::PickleIterator* iter,
308 param_type* r);
309 static void Log(const param_type& p, std::string* l);
312 template <>
313 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
314 typedef std::vector<bool> param_type;
315 static void Write(Message* m, const param_type& p);
316 static bool Read(const Message* m,
317 base::PickleIterator* iter,
318 param_type* r);
319 static void Log(const param_type& p, std::string* l);
322 template <class P>
323 struct ParamTraits<std::vector<P> > {
324 typedef std::vector<P> param_type;
325 static void Write(Message* m, const param_type& p) {
326 WriteParam(m, static_cast<int>(p.size()));
327 for (size_t i = 0; i < p.size(); i++)
328 WriteParam(m, p[i]);
330 static bool Read(const Message* m,
331 base::PickleIterator* iter,
332 param_type* r) {
333 int size;
334 // ReadLength() checks for < 0 itself.
335 if (!iter->ReadLength(&size))
336 return false;
337 // Resizing beforehand is not safe, see BUG 1006367 for details.
338 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
339 return false;
340 r->resize(size);
341 for (int i = 0; i < size; i++) {
342 if (!ReadParam(m, iter, &(*r)[i]))
343 return false;
345 return true;
347 static void Log(const param_type& p, std::string* l) {
348 for (size_t i = 0; i < p.size(); ++i) {
349 if (i != 0)
350 l->append(" ");
351 LogParam((p[i]), l);
356 template <class P>
357 struct ParamTraits<std::set<P> > {
358 typedef std::set<P> param_type;
359 static void Write(Message* m, const param_type& p) {
360 WriteParam(m, static_cast<int>(p.size()));
361 typename param_type::const_iterator iter;
362 for (iter = p.begin(); iter != p.end(); ++iter)
363 WriteParam(m, *iter);
365 static bool Read(const Message* m,
366 base::PickleIterator* iter,
367 param_type* r) {
368 int size;
369 if (!iter->ReadLength(&size))
370 return false;
371 for (int i = 0; i < size; ++i) {
372 P item;
373 if (!ReadParam(m, iter, &item))
374 return false;
375 r->insert(item);
377 return true;
379 static void Log(const param_type& p, std::string* l) {
380 l->append("<std::set>");
384 template <class K, class V, class C, class A>
385 struct ParamTraits<std::map<K, V, C, A> > {
386 typedef std::map<K, V, C, A> param_type;
387 static void Write(Message* m, const param_type& p) {
388 WriteParam(m, static_cast<int>(p.size()));
389 typename param_type::const_iterator iter;
390 for (iter = p.begin(); iter != p.end(); ++iter) {
391 WriteParam(m, iter->first);
392 WriteParam(m, iter->second);
395 static bool Read(const Message* m,
396 base::PickleIterator* iter,
397 param_type* r) {
398 int size;
399 if (!ReadParam(m, iter, &size) || size < 0)
400 return false;
401 for (int i = 0; i < size; ++i) {
402 K k;
403 if (!ReadParam(m, iter, &k))
404 return false;
405 V& value = (*r)[k];
406 if (!ReadParam(m, iter, &value))
407 return false;
409 return true;
411 static void Log(const param_type& p, std::string* l) {
412 l->append("<std::map>");
416 template <class A, class B>
417 struct ParamTraits<std::pair<A, B> > {
418 typedef std::pair<A, B> param_type;
419 static void Write(Message* m, const param_type& p) {
420 WriteParam(m, p.first);
421 WriteParam(m, p.second);
423 static bool Read(const Message* m,
424 base::PickleIterator* iter,
425 param_type* r) {
426 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
428 static void Log(const param_type& p, std::string* l) {
429 l->append("(");
430 LogParam(p.first, l);
431 l->append(", ");
432 LogParam(p.second, l);
433 l->append(")");
437 // IPC ParamTraits -------------------------------------------------------------
438 template <>
439 struct IPC_EXPORT ParamTraits<BrokerableAttachment::AttachmentId> {
440 typedef BrokerableAttachment::AttachmentId param_type;
441 static void Write(Message* m, const param_type& p);
442 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
443 static void Log(const param_type& p, std::string* l);
446 // Base ParamTraits ------------------------------------------------------------
448 template <>
449 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
450 typedef base::DictionaryValue param_type;
451 static void Write(Message* m, const param_type& p);
452 static bool Read(const Message* m,
453 base::PickleIterator* iter,
454 param_type* r);
455 static void Log(const param_type& p, std::string* l);
458 #if defined(OS_POSIX)
459 // FileDescriptors may be serialised over IPC channels on POSIX. On the
460 // receiving side, the FileDescriptor is a valid duplicate of the file
461 // descriptor which was transmitted: *it is not just a copy of the integer like
462 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
463 // this case, the receiving end will see a value of -1. *Zero is a valid file
464 // descriptor*.
466 // The received file descriptor will have the |auto_close| flag set to true. The
467 // code which handles the message is responsible for taking ownership of it.
468 // File descriptors are OS resources and must be closed when no longer needed.
470 // When sending a file descriptor, the file descriptor must be valid at the time
471 // of transmission. Since transmission is not synchronous, one should consider
472 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
473 // flag, which causes the file descriptor to be closed after writing.
474 template<>
475 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
476 typedef base::FileDescriptor param_type;
477 static void Write(Message* m, const param_type& p);
478 static bool Read(const Message* m,
479 base::PickleIterator* iter,
480 param_type* r);
481 static void Log(const param_type& p, std::string* l);
483 #endif // defined(OS_POSIX)
485 #if defined(OS_MACOSX) && !defined(OS_IOS)
486 template <>
487 struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
488 typedef base::SharedMemoryHandle param_type;
489 static void Write(Message* m, const param_type& p);
490 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
491 static void Log(const param_type& p, std::string* l);
493 #endif
495 template <>
496 struct IPC_EXPORT ParamTraits<base::FilePath> {
497 typedef base::FilePath param_type;
498 static void Write(Message* m, const param_type& p);
499 static bool Read(const Message* m,
500 base::PickleIterator* iter,
501 param_type* r);
502 static void Log(const param_type& p, std::string* l);
505 template <>
506 struct IPC_EXPORT ParamTraits<base::ListValue> {
507 typedef base::ListValue param_type;
508 static void Write(Message* m, const param_type& p);
509 static bool Read(const Message* m,
510 base::PickleIterator* iter,
511 param_type* r);
512 static void Log(const param_type& p, std::string* l);
515 template <>
516 struct IPC_EXPORT ParamTraits<base::NullableString16> {
517 typedef base::NullableString16 param_type;
518 static void Write(Message* m, const param_type& p);
519 static bool Read(const Message* m,
520 base::PickleIterator* iter,
521 param_type* r);
522 static void Log(const param_type& p, std::string* l);
525 template <>
526 struct IPC_EXPORT ParamTraits<base::File::Info> {
527 typedef base::File::Info param_type;
528 static void Write(Message* m, const param_type& p);
529 static bool Read(const Message* m,
530 base::PickleIterator* iter,
531 param_type* r);
532 static void Log(const param_type& p, std::string* l);
535 template <>
536 struct SimilarTypeTraits<base::File::Error> {
537 typedef int Type;
540 #if defined(OS_WIN)
541 template <>
542 struct SimilarTypeTraits<HWND> {
543 typedef HANDLE Type;
545 #endif // defined(OS_WIN)
547 template <>
548 struct IPC_EXPORT ParamTraits<base::Time> {
549 typedef base::Time param_type;
550 static void Write(Message* m, const param_type& p);
551 static bool Read(const Message* m,
552 base::PickleIterator* iter,
553 param_type* r);
554 static void Log(const param_type& p, std::string* l);
557 template <>
558 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
559 typedef base::TimeDelta param_type;
560 static void Write(Message* m, const param_type& p);
561 static bool Read(const Message* m,
562 base::PickleIterator* iter,
563 param_type* r);
564 static void Log(const param_type& p, std::string* l);
567 template <>
568 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
569 typedef base::TimeTicks param_type;
570 static void Write(Message* m, const param_type& p);
571 static bool Read(const Message* m,
572 base::PickleIterator* iter,
573 param_type* r);
574 static void Log(const param_type& p, std::string* l);
577 template <>
578 struct IPC_EXPORT ParamTraits<base::TraceTicks> {
579 typedef base::TraceTicks param_type;
580 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 static void Log(const param_type& p, std::string* l);
587 template <>
588 struct ParamTraits<base::Tuple<>> {
589 typedef base::Tuple<> param_type;
590 static void Write(Message* m, const param_type& p) {
592 static bool Read(const Message* m,
593 base::PickleIterator* iter,
594 param_type* r) {
595 return true;
597 static void Log(const param_type& p, std::string* l) {
601 template <class A>
602 struct ParamTraits<base::Tuple<A>> {
603 typedef base::Tuple<A> param_type;
604 static void Write(Message* m, const param_type& p) {
605 WriteParam(m, base::get<0>(p));
607 static bool Read(const Message* m,
608 base::PickleIterator* iter,
609 param_type* r) {
610 return ReadParam(m, iter, &base::get<0>(*r));
612 static void Log(const param_type& p, std::string* l) {
613 LogParam(base::get<0>(p), l);
617 template <class A, class B>
618 struct ParamTraits<base::Tuple<A, B>> {
619 typedef base::Tuple<A, B> param_type;
620 static void Write(Message* m, const param_type& p) {
621 WriteParam(m, base::get<0>(p));
622 WriteParam(m, base::get<1>(p));
624 static bool Read(const Message* m,
625 base::PickleIterator* iter,
626 param_type* r) {
627 return (ReadParam(m, iter, &base::get<0>(*r)) &&
628 ReadParam(m, iter, &base::get<1>(*r)));
630 static void Log(const param_type& p, std::string* l) {
631 LogParam(base::get<0>(p), l);
632 l->append(", ");
633 LogParam(base::get<1>(p), l);
637 template <class A, class B, class C>
638 struct ParamTraits<base::Tuple<A, B, C>> {
639 typedef base::Tuple<A, B, C> param_type;
640 static void Write(Message* m, const param_type& p) {
641 WriteParam(m, base::get<0>(p));
642 WriteParam(m, base::get<1>(p));
643 WriteParam(m, base::get<2>(p));
645 static bool Read(const Message* m,
646 base::PickleIterator* iter,
647 param_type* r) {
648 return (ReadParam(m, iter, &base::get<0>(*r)) &&
649 ReadParam(m, iter, &base::get<1>(*r)) &&
650 ReadParam(m, iter, &base::get<2>(*r)));
652 static void Log(const param_type& p, std::string* l) {
653 LogParam(base::get<0>(p), l);
654 l->append(", ");
655 LogParam(base::get<1>(p), l);
656 l->append(", ");
657 LogParam(base::get<2>(p), l);
661 template <class A, class B, class C, class D>
662 struct ParamTraits<base::Tuple<A, B, C, D>> {
663 typedef base::Tuple<A, B, C, D> param_type;
664 static void Write(Message* m, const param_type& p) {
665 WriteParam(m, base::get<0>(p));
666 WriteParam(m, base::get<1>(p));
667 WriteParam(m, base::get<2>(p));
668 WriteParam(m, base::get<3>(p));
670 static bool Read(const Message* m,
671 base::PickleIterator* iter,
672 param_type* r) {
673 return (ReadParam(m, iter, &base::get<0>(*r)) &&
674 ReadParam(m, iter, &base::get<1>(*r)) &&
675 ReadParam(m, iter, &base::get<2>(*r)) &&
676 ReadParam(m, iter, &base::get<3>(*r)));
678 static void Log(const param_type& p, std::string* l) {
679 LogParam(base::get<0>(p), l);
680 l->append(", ");
681 LogParam(base::get<1>(p), l);
682 l->append(", ");
683 LogParam(base::get<2>(p), l);
684 l->append(", ");
685 LogParam(base::get<3>(p), l);
689 template <class A, class B, class C, class D, class E>
690 struct ParamTraits<base::Tuple<A, B, C, D, E>> {
691 typedef base::Tuple<A, B, C, D, E> param_type;
692 static void Write(Message* m, const param_type& p) {
693 WriteParam(m, base::get<0>(p));
694 WriteParam(m, base::get<1>(p));
695 WriteParam(m, base::get<2>(p));
696 WriteParam(m, base::get<3>(p));
697 WriteParam(m, base::get<4>(p));
699 static bool Read(const Message* m,
700 base::PickleIterator* iter,
701 param_type* r) {
702 return (ReadParam(m, iter, &base::get<0>(*r)) &&
703 ReadParam(m, iter, &base::get<1>(*r)) &&
704 ReadParam(m, iter, &base::get<2>(*r)) &&
705 ReadParam(m, iter, &base::get<3>(*r)) &&
706 ReadParam(m, iter, &base::get<4>(*r)));
708 static void Log(const param_type& p, std::string* l) {
709 LogParam(base::get<0>(p), l);
710 l->append(", ");
711 LogParam(base::get<1>(p), l);
712 l->append(", ");
713 LogParam(base::get<2>(p), l);
714 l->append(", ");
715 LogParam(base::get<3>(p), l);
716 l->append(", ");
717 LogParam(base::get<4>(p), l);
721 template<class P>
722 struct ParamTraits<ScopedVector<P> > {
723 typedef ScopedVector<P> param_type;
724 static void Write(Message* m, const param_type& p) {
725 WriteParam(m, static_cast<int>(p.size()));
726 for (size_t i = 0; i < p.size(); i++)
727 WriteParam(m, *p[i]);
729 static bool Read(const Message* m,
730 base::PickleIterator* iter,
731 param_type* r) {
732 int size = 0;
733 if (!iter->ReadLength(&size))
734 return false;
735 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
736 return false;
737 r->resize(size);
738 for (int i = 0; i < size; i++) {
739 (*r)[i] = new P();
740 if (!ReadParam(m, iter, (*r)[i]))
741 return false;
743 return true;
745 static void Log(const param_type& p, std::string* l) {
746 for (size_t i = 0; i < p.size(); ++i) {
747 if (i != 0)
748 l->append(" ");
749 LogParam(*p[i], l);
754 template <class P, size_t stack_capacity>
755 struct ParamTraits<base::StackVector<P, stack_capacity> > {
756 typedef base::StackVector<P, stack_capacity> param_type;
757 static void Write(Message* m, const param_type& p) {
758 WriteParam(m, static_cast<int>(p->size()));
759 for (size_t i = 0; i < p->size(); i++)
760 WriteParam(m, p[i]);
762 static bool Read(const Message* m,
763 base::PickleIterator* iter,
764 param_type* r) {
765 int size;
766 // ReadLength() checks for < 0 itself.
767 if (!iter->ReadLength(&size))
768 return false;
769 // Sanity check for the vector size.
770 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
771 return false;
772 P value;
773 for (int i = 0; i < size; i++) {
774 if (!ReadParam(m, iter, &value))
775 return false;
776 (*r)->push_back(value);
778 return true;
780 static void Log(const param_type& p, std::string* l) {
781 for (size_t i = 0; i < p->size(); ++i) {
782 if (i != 0)
783 l->append(" ");
784 LogParam((p[i]), l);
789 template <typename NormalMap,
790 int kArraySize,
791 typename EqualKey,
792 typename MapInit>
793 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
794 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
795 typedef typename param_type::key_type K;
796 typedef typename param_type::data_type V;
797 static void Write(Message* m, const param_type& p) {
798 WriteParam(m, static_cast<int>(p.size()));
799 typename param_type::const_iterator iter;
800 for (iter = p.begin(); iter != p.end(); ++iter) {
801 WriteParam(m, iter->first);
802 WriteParam(m, iter->second);
805 static bool Read(const Message* m,
806 base::PickleIterator* iter,
807 param_type* r) {
808 int size;
809 if (!iter->ReadLength(&size))
810 return false;
811 for (int i = 0; i < size; ++i) {
812 K key;
813 if (!ReadParam(m, iter, &key))
814 return false;
815 V& value = (*r)[key];
816 if (!ReadParam(m, iter, &value))
817 return false;
819 return true;
821 static void Log(const param_type& p, std::string* l) {
822 l->append("<base::SmallMap>");
826 template <class P>
827 struct ParamTraits<scoped_ptr<P> > {
828 typedef scoped_ptr<P> param_type;
829 static void Write(Message* m, const param_type& p) {
830 bool valid = !!p;
831 WriteParam(m, valid);
832 if (valid)
833 WriteParam(m, *p);
835 static bool Read(const Message* m,
836 base::PickleIterator* iter,
837 param_type* r) {
838 bool valid = false;
839 if (!ReadParam(m, iter, &valid))
840 return false;
842 if (!valid) {
843 r->reset();
844 return true;
847 param_type temp(new P());
848 if (!ReadParam(m, iter, temp.get()))
849 return false;
851 r->swap(temp);
852 return true;
854 static void Log(const param_type& p, std::string* l) {
855 if (p)
856 LogParam(*p, l);
857 else
858 l->append("NULL");
862 // IPC types ParamTraits -------------------------------------------------------
864 // A ChannelHandle is basically a platform-inspecific wrapper around the
865 // fact that IPC endpoints are handled specially on POSIX. See above comments
866 // on FileDescriptor for more background.
867 template<>
868 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
869 typedef ChannelHandle param_type;
870 static void Write(Message* m, const param_type& p);
871 static bool Read(const Message* m,
872 base::PickleIterator* iter,
873 param_type* r);
874 static void Log(const param_type& p, std::string* l);
877 template <>
878 struct IPC_EXPORT ParamTraits<LogData> {
879 typedef LogData param_type;
880 static void Write(Message* m, const param_type& p);
881 static bool Read(const Message* m,
882 base::PickleIterator* iter,
883 param_type* r);
884 static void Log(const param_type& p, std::string* l);
887 template <>
888 struct IPC_EXPORT ParamTraits<Message> {
889 static void Write(Message* m, const Message& p);
890 static bool Read(const Message* m,
891 base::PickleIterator* iter,
892 Message* r);
893 static void Log(const Message& p, std::string* l);
896 // Windows ParamTraits ---------------------------------------------------------
898 #if defined(OS_WIN)
899 template <>
900 struct IPC_EXPORT ParamTraits<HANDLE> {
901 typedef HANDLE param_type;
902 static void Write(Message* m, const param_type& p);
903 static bool Read(const Message* m,
904 base::PickleIterator* iter,
905 param_type* r);
906 static void Log(const param_type& p, std::string* l);
909 template <>
910 struct IPC_EXPORT ParamTraits<LOGFONT> {
911 typedef LOGFONT param_type;
912 static void Write(Message* m, const param_type& p);
913 static bool Read(const Message* m,
914 base::PickleIterator* iter,
915 param_type* r);
916 static void Log(const param_type& p, std::string* l);
919 template <>
920 struct IPC_EXPORT ParamTraits<MSG> {
921 typedef MSG param_type;
922 static void Write(Message* m, const param_type& p);
923 static bool Read(const Message* m,
924 base::PickleIterator* iter,
925 param_type* r);
926 static void Log(const param_type& p, std::string* l);
928 #endif // defined(OS_WIN)
930 //-----------------------------------------------------------------------------
931 // Generic message subclasses
933 // Used for asynchronous messages.
934 template <class ParamType>
935 class MessageSchema {
936 public:
937 typedef ParamType Param;
938 typedef typename base::TupleTypes<ParamType>::ParamTuple RefParam;
940 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
941 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
944 // defined in ipc_logging.cc
945 IPC_EXPORT void GenerateLogData(const std::string& channel,
946 const Message& message,
947 LogData* data, bool get_params);
950 #if defined(IPC_MESSAGE_LOG_ENABLED)
951 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
952 const std::string& output_params = msg->output_params();
953 if (!l->empty() && !output_params.empty())
954 l->append(", ");
956 l->append(output_params);
959 template <class ReplyParamType>
960 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
961 const Message* msg) {
962 if (msg->received_time() != 0) {
963 std::string output_params;
964 LogParam(reply_params, &output_params);
965 msg->set_output_params(output_params);
969 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
970 if (msg->sent_time()) {
971 // Don't log the sync message after dispatch, as we don't have the
972 // output parameters at that point. Instead, save its data and log it
973 // with the outgoing reply message when it's sent.
974 LogData* data = new LogData;
975 GenerateLogData("", *msg, data, true);
976 msg->set_dont_log();
977 reply->set_sync_log_data(data);
980 #else
981 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
983 template <class ReplyParamType>
984 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
985 const Message* msg) {}
987 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
988 #endif
990 // This class assumes that its template argument is a RefTuple (a Tuple with
991 // reference elements). This would go into ipc_message_utils_impl.h, but it is
992 // also used by chrome_frame.
993 template <class RefTuple>
994 class ParamDeserializer : public MessageReplyDeserializer {
995 public:
996 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
998 bool SerializeOutputParameters(const IPC::Message& msg,
999 base::PickleIterator iter) override {
1000 return ReadParam(&msg, &iter, &out_);
1003 RefTuple out_;
1006 // Used for synchronous messages.
1007 template <class SendParamType, class ReplyParamType>
1008 class SyncMessageSchema {
1009 public:
1010 typedef SendParamType SendParam;
1011 typedef typename base::TupleTypes<SendParam>::ParamTuple RefSendParam;
1012 typedef ReplyParamType ReplyParam;
1014 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
1015 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
1016 static bool ReadReplyParam(
1017 const Message* msg,
1018 typename base::TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
1020 template<class T, class S, class Method>
1021 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
1022 const Message* msg, T* obj, S* sender,
1023 Method func) {
1024 Message* reply = SyncMessage::GenerateReply(msg);
1025 if (ok) {
1026 typename base::TupleTypes<ReplyParam>::ValueTuple reply_params;
1027 DispatchToMethod(obj, func, send_params, &reply_params);
1028 WriteParam(reply, reply_params);
1029 LogReplyParamsToMessage(reply_params, msg);
1030 } else {
1031 NOTREACHED() << "Error deserializing message " << msg->type();
1032 reply->set_reply_error();
1034 sender->Send(reply);
1035 return ok;
1038 template<class T, class Method>
1039 static bool DispatchDelayReplyWithSendParams(bool ok,
1040 const SendParam& send_params,
1041 const Message* msg, T* obj,
1042 Method func) {
1043 Message* reply = SyncMessage::GenerateReply(msg);
1044 if (ok) {
1045 base::Tuple<Message&> t = base::MakeRefTuple(*reply);
1046 ConnectMessageAndReply(msg, reply);
1047 DispatchToMethod(obj, func, send_params, &t);
1048 } else {
1049 NOTREACHED() << "Error deserializing message " << msg->type();
1050 reply->set_reply_error();
1051 obj->Send(reply);
1053 return ok;
1056 template <typename... Ts>
1057 static void WriteReplyParams(Message* reply, Ts... args) {
1058 ReplyParam p(args...);
1059 WriteParam(reply, p);
1063 } // namespace IPC
1065 #endif // IPC_IPC_MESSAGE_UTILS_H_