Roll ANGLE e754fb8..6ffeb74
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blob94651419be23314484f6fe6b91a8d2fc643c1e3e
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;
62 namespace IPC {
64 struct ChannelHandle;
66 // -----------------------------------------------------------------------------
67 // How we send IPC message logs across channels.
68 struct IPC_EXPORT LogData {
69 LogData();
70 ~LogData();
72 std::string channel;
73 int32 routing_id;
74 uint32 type; // "User-defined" message type, from ipc_message.h.
75 std::string flags;
76 int64 sent; // Time that the message was sent (i.e. at Send()).
77 int64 receive; // Time before it was dispatched (i.e. before calling
78 // OnMessageReceived).
79 int64 dispatch; // Time after it was dispatched (i.e. after calling
80 // OnMessageReceived).
81 std::string message_name;
82 std::string params;
85 //-----------------------------------------------------------------------------
87 // A dummy struct to place first just to allow leading commas for all
88 // members in the macro-generated constructor initializer lists.
89 struct NoParams {
92 template <class P>
93 static inline void WriteParam(Message* m, const P& p) {
94 typedef typename SimilarTypeTraits<P>::Type Type;
95 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
98 template <class P>
99 static inline bool WARN_UNUSED_RESULT
100 ReadParam(const Message* m, base::PickleIterator* iter, P* p) {
101 typedef typename SimilarTypeTraits<P>::Type Type;
102 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
105 template <class P>
106 static inline void LogParam(const P& p, std::string* l) {
107 typedef typename SimilarTypeTraits<P>::Type Type;
108 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
111 // Primitive ParamTraits -------------------------------------------------------
113 template <>
114 struct ParamTraits<bool> {
115 typedef bool param_type;
116 static void Write(Message* m, const param_type& p) {
117 m->WriteBool(p);
119 static bool Read(const Message* m,
120 base::PickleIterator* iter,
121 param_type* r) {
122 return iter->ReadBool(r);
124 IPC_EXPORT static void Log(const param_type& p, std::string* l);
127 template <>
128 struct IPC_EXPORT ParamTraits<unsigned char> {
129 typedef unsigned char param_type;
130 static void Write(Message* m, const param_type& p);
131 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
132 static void Log(const param_type& p, std::string* l);
135 template <>
136 struct IPC_EXPORT ParamTraits<unsigned short> {
137 typedef unsigned short param_type;
138 static void Write(Message* m, const param_type& p);
139 static bool Read(const Message* m,
140 base::PickleIterator* iter,
141 param_type* r);
142 static void Log(const param_type& p, std::string* l);
145 template <>
146 struct ParamTraits<int> {
147 typedef int param_type;
148 static void Write(Message* m, const param_type& p) {
149 m->WriteInt(p);
151 static bool Read(const Message* m,
152 base::PickleIterator* iter,
153 param_type* r) {
154 return iter->ReadInt(r);
156 IPC_EXPORT static void Log(const param_type& p, std::string* l);
159 template <>
160 struct ParamTraits<unsigned int> {
161 typedef unsigned int param_type;
162 static void Write(Message* m, const param_type& p) {
163 m->WriteInt(p);
165 static bool Read(const Message* m,
166 base::PickleIterator* iter,
167 param_type* r) {
168 return iter->ReadInt(reinterpret_cast<int*>(r));
170 IPC_EXPORT static void Log(const param_type& p, std::string* l);
173 template <>
174 struct ParamTraits<long> {
175 typedef long param_type;
176 static void Write(Message* m, const param_type& p) {
177 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
179 static bool Read(const Message* m,
180 base::PickleIterator* iter,
181 param_type* r) {
182 return iter->ReadLong(r);
184 IPC_EXPORT static void Log(const param_type& p, std::string* l);
187 template <>
188 struct ParamTraits<unsigned long> {
189 typedef unsigned long param_type;
190 static void Write(Message* m, const param_type& p) {
191 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
193 static bool Read(const Message* m,
194 base::PickleIterator* iter,
195 param_type* r) {
196 return iter->ReadLong(reinterpret_cast<long*>(r));
198 IPC_EXPORT static void Log(const param_type& p, std::string* l);
201 template <>
202 struct ParamTraits<long long> {
203 typedef long long param_type;
204 static void Write(Message* m, const param_type& p) {
205 m->WriteInt64(static_cast<int64>(p));
207 static bool Read(const Message* m,
208 base::PickleIterator* iter,
209 param_type* r) {
210 return iter->ReadInt64(reinterpret_cast<int64*>(r));
212 IPC_EXPORT static void Log(const param_type& p, std::string* l);
215 template <>
216 struct ParamTraits<unsigned long long> {
217 typedef unsigned long long param_type;
218 static void Write(Message* m, const param_type& p) {
219 m->WriteInt64(p);
221 static bool Read(const Message* m,
222 base::PickleIterator* iter,
223 param_type* r) {
224 return iter->ReadInt64(reinterpret_cast<int64*>(r));
226 IPC_EXPORT static void Log(const param_type& p, std::string* l);
229 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
230 // should be sure to check the sanity of these values after receiving them over
231 // IPC.
232 template <>
233 struct IPC_EXPORT ParamTraits<float> {
234 typedef float param_type;
235 static void Write(Message* m, const param_type& p) {
236 m->WriteFloat(p);
238 static bool Read(const Message* m,
239 base::PickleIterator* iter,
240 param_type* r) {
241 return iter->ReadFloat(r);
243 static void Log(const param_type& p, std::string* l);
246 template <>
247 struct IPC_EXPORT ParamTraits<double> {
248 typedef double param_type;
249 static void Write(Message* m, const param_type& p);
250 static bool Read(const Message* m,
251 base::PickleIterator* iter,
252 param_type* r);
253 static void Log(const param_type& p, std::string* l);
256 // STL ParamTraits -------------------------------------------------------------
258 template <>
259 struct ParamTraits<std::string> {
260 typedef std::string param_type;
261 static void Write(Message* m, const param_type& p) {
262 m->WriteString(p);
264 static bool Read(const Message* m,
265 base::PickleIterator* iter,
266 param_type* r) {
267 return iter->ReadString(r);
269 IPC_EXPORT static void Log(const param_type& p, std::string* l);
272 template <>
273 struct ParamTraits<base::string16> {
274 typedef base::string16 param_type;
275 static void Write(Message* m, const param_type& p) {
276 m->WriteString16(p);
278 static bool Read(const Message* m,
279 base::PickleIterator* iter,
280 param_type* r) {
281 return iter->ReadString16(r);
283 IPC_EXPORT static void Log(const param_type& p, std::string* l);
286 template <>
287 struct IPC_EXPORT ParamTraits<std::vector<char> > {
288 typedef std::vector<char> param_type;
289 static void Write(Message* m, const param_type& p);
290 static bool Read(const Message*,
291 base::PickleIterator* iter,
292 param_type* r);
293 static void Log(const param_type& p, std::string* l);
296 template <>
297 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
298 typedef std::vector<unsigned char> param_type;
299 static void Write(Message* m, const param_type& p);
300 static bool Read(const Message* m,
301 base::PickleIterator* iter,
302 param_type* r);
303 static void Log(const param_type& p, std::string* l);
306 template <>
307 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
308 typedef std::vector<bool> param_type;
309 static void Write(Message* m, const param_type& p);
310 static bool Read(const Message* m,
311 base::PickleIterator* iter,
312 param_type* r);
313 static void Log(const param_type& p, std::string* l);
316 template <class P>
317 struct ParamTraits<std::vector<P> > {
318 typedef std::vector<P> param_type;
319 static void Write(Message* m, const param_type& p) {
320 WriteParam(m, static_cast<int>(p.size()));
321 for (size_t i = 0; i < p.size(); i++)
322 WriteParam(m, p[i]);
324 static bool Read(const Message* m,
325 base::PickleIterator* iter,
326 param_type* r) {
327 int size;
328 // ReadLength() checks for < 0 itself.
329 if (!iter->ReadLength(&size))
330 return false;
331 // Resizing beforehand is not safe, see BUG 1006367 for details.
332 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
333 return false;
334 r->resize(size);
335 for (int i = 0; i < size; i++) {
336 if (!ReadParam(m, iter, &(*r)[i]))
337 return false;
339 return true;
341 static void Log(const param_type& p, std::string* l) {
342 for (size_t i = 0; i < p.size(); ++i) {
343 if (i != 0)
344 l->append(" ");
345 LogParam((p[i]), l);
350 template <class P>
351 struct ParamTraits<std::set<P> > {
352 typedef std::set<P> param_type;
353 static void Write(Message* m, const param_type& p) {
354 WriteParam(m, static_cast<int>(p.size()));
355 typename param_type::const_iterator iter;
356 for (iter = p.begin(); iter != p.end(); ++iter)
357 WriteParam(m, *iter);
359 static bool Read(const Message* m,
360 base::PickleIterator* iter,
361 param_type* r) {
362 int size;
363 if (!iter->ReadLength(&size))
364 return false;
365 for (int i = 0; i < size; ++i) {
366 P item;
367 if (!ReadParam(m, iter, &item))
368 return false;
369 r->insert(item);
371 return true;
373 static void Log(const param_type& p, std::string* l) {
374 l->append("<std::set>");
378 template <class K, class V, class C, class A>
379 struct ParamTraits<std::map<K, V, C, A> > {
380 typedef std::map<K, V, C, A> param_type;
381 static void Write(Message* m, const param_type& p) {
382 WriteParam(m, static_cast<int>(p.size()));
383 typename param_type::const_iterator iter;
384 for (iter = p.begin(); iter != p.end(); ++iter) {
385 WriteParam(m, iter->first);
386 WriteParam(m, iter->second);
389 static bool Read(const Message* m,
390 base::PickleIterator* iter,
391 param_type* r) {
392 int size;
393 if (!ReadParam(m, iter, &size) || size < 0)
394 return false;
395 for (int i = 0; i < size; ++i) {
396 K k;
397 if (!ReadParam(m, iter, &k))
398 return false;
399 V& value = (*r)[k];
400 if (!ReadParam(m, iter, &value))
401 return false;
403 return true;
405 static void Log(const param_type& p, std::string* l) {
406 l->append("<std::map>");
410 template <class A, class B>
411 struct ParamTraits<std::pair<A, B> > {
412 typedef std::pair<A, B> param_type;
413 static void Write(Message* m, const param_type& p) {
414 WriteParam(m, p.first);
415 WriteParam(m, p.second);
417 static bool Read(const Message* m,
418 base::PickleIterator* iter,
419 param_type* r) {
420 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
422 static void Log(const param_type& p, std::string* l) {
423 l->append("(");
424 LogParam(p.first, l);
425 l->append(", ");
426 LogParam(p.second, l);
427 l->append(")");
431 // Base ParamTraits ------------------------------------------------------------
433 template <>
434 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
435 typedef base::DictionaryValue param_type;
436 static void Write(Message* m, const param_type& p);
437 static bool Read(const Message* m,
438 base::PickleIterator* iter,
439 param_type* r);
440 static void Log(const param_type& p, std::string* l);
443 #if defined(OS_POSIX)
444 // FileDescriptors may be serialised over IPC channels on POSIX. On the
445 // receiving side, the FileDescriptor is a valid duplicate of the file
446 // descriptor which was transmitted: *it is not just a copy of the integer like
447 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
448 // this case, the receiving end will see a value of -1. *Zero is a valid file
449 // descriptor*.
451 // The received file descriptor will have the |auto_close| flag set to true. The
452 // code which handles the message is responsible for taking ownership of it.
453 // File descriptors are OS resources and must be closed when no longer needed.
455 // When sending a file descriptor, the file descriptor must be valid at the time
456 // of transmission. Since transmission is not synchronous, one should consider
457 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
458 // flag, which causes the file descriptor to be closed after writing.
459 template<>
460 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
461 typedef base::FileDescriptor param_type;
462 static void Write(Message* m, const param_type& p);
463 static bool Read(const Message* m,
464 base::PickleIterator* iter,
465 param_type* r);
466 static void Log(const param_type& p, std::string* l);
468 #endif // defined(OS_POSIX)
470 template <>
471 struct IPC_EXPORT ParamTraits<base::FilePath> {
472 typedef base::FilePath param_type;
473 static void Write(Message* m, const param_type& p);
474 static bool Read(const Message* m,
475 base::PickleIterator* iter,
476 param_type* r);
477 static void Log(const param_type& p, std::string* l);
480 template <>
481 struct IPC_EXPORT ParamTraits<base::ListValue> {
482 typedef base::ListValue param_type;
483 static void Write(Message* m, const param_type& p);
484 static bool Read(const Message* m,
485 base::PickleIterator* iter,
486 param_type* r);
487 static void Log(const param_type& p, std::string* l);
490 template <>
491 struct IPC_EXPORT ParamTraits<base::NullableString16> {
492 typedef base::NullableString16 param_type;
493 static void Write(Message* m, const param_type& p);
494 static bool Read(const Message* m,
495 base::PickleIterator* iter,
496 param_type* r);
497 static void Log(const param_type& p, std::string* l);
500 template <>
501 struct IPC_EXPORT ParamTraits<base::File::Info> {
502 typedef base::File::Info param_type;
503 static void Write(Message* m, const param_type& p);
504 static bool Read(const Message* m,
505 base::PickleIterator* iter,
506 param_type* r);
507 static void Log(const param_type& p, std::string* l);
510 template <>
511 struct SimilarTypeTraits<base::File::Error> {
512 typedef int Type;
515 #if defined(OS_WIN)
516 template <>
517 struct SimilarTypeTraits<HWND> {
518 typedef HANDLE Type;
520 #endif // defined(OS_WIN)
522 template <>
523 struct IPC_EXPORT ParamTraits<base::Time> {
524 typedef base::Time param_type;
525 static void Write(Message* m, const param_type& p);
526 static bool Read(const Message* m,
527 base::PickleIterator* iter,
528 param_type* r);
529 static void Log(const param_type& p, std::string* l);
532 template <>
533 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
534 typedef base::TimeDelta param_type;
535 static void Write(Message* m, const param_type& p);
536 static bool Read(const Message* m,
537 base::PickleIterator* iter,
538 param_type* r);
539 static void Log(const param_type& p, std::string* l);
542 template <>
543 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
544 typedef base::TimeTicks param_type;
545 static void Write(Message* m, const param_type& p);
546 static bool Read(const Message* m,
547 base::PickleIterator* iter,
548 param_type* r);
549 static void Log(const param_type& p, std::string* l);
552 template <>
553 struct IPC_EXPORT ParamTraits<base::TraceTicks> {
554 typedef base::TraceTicks param_type;
555 static void Write(Message* m, const param_type& p);
556 static bool Read(const Message* m,
557 base::PickleIterator* iter,
558 param_type* r);
559 static void Log(const param_type& p, std::string* l);
562 template <>
563 struct ParamTraits<base::Tuple<>> {
564 typedef base::Tuple<> param_type;
565 static void Write(Message* m, const param_type& p) {
567 static bool Read(const Message* m,
568 base::PickleIterator* iter,
569 param_type* r) {
570 return true;
572 static void Log(const param_type& p, std::string* l) {
576 template <class A>
577 struct ParamTraits<base::Tuple<A>> {
578 typedef base::Tuple<A> param_type;
579 static void Write(Message* m, const param_type& p) {
580 WriteParam(m, base::get<0>(p));
582 static bool Read(const Message* m,
583 base::PickleIterator* iter,
584 param_type* r) {
585 return ReadParam(m, iter, &base::get<0>(*r));
587 static void Log(const param_type& p, std::string* l) {
588 LogParam(base::get<0>(p), l);
592 template <class A, class B>
593 struct ParamTraits<base::Tuple<A, B>> {
594 typedef base::Tuple<A, B> param_type;
595 static void Write(Message* m, const param_type& p) {
596 WriteParam(m, base::get<0>(p));
597 WriteParam(m, base::get<1>(p));
599 static bool Read(const Message* m,
600 base::PickleIterator* iter,
601 param_type* r) {
602 return (ReadParam(m, iter, &base::get<0>(*r)) &&
603 ReadParam(m, iter, &base::get<1>(*r)));
605 static void Log(const param_type& p, std::string* l) {
606 LogParam(base::get<0>(p), l);
607 l->append(", ");
608 LogParam(base::get<1>(p), l);
612 template <class A, class B, class C>
613 struct ParamTraits<base::Tuple<A, B, C>> {
614 typedef base::Tuple<A, B, C> param_type;
615 static void Write(Message* m, const param_type& p) {
616 WriteParam(m, base::get<0>(p));
617 WriteParam(m, base::get<1>(p));
618 WriteParam(m, base::get<2>(p));
620 static bool Read(const Message* m,
621 base::PickleIterator* iter,
622 param_type* r) {
623 return (ReadParam(m, iter, &base::get<0>(*r)) &&
624 ReadParam(m, iter, &base::get<1>(*r)) &&
625 ReadParam(m, iter, &base::get<2>(*r)));
627 static void Log(const param_type& p, std::string* l) {
628 LogParam(base::get<0>(p), l);
629 l->append(", ");
630 LogParam(base::get<1>(p), l);
631 l->append(", ");
632 LogParam(base::get<2>(p), l);
636 template <class A, class B, class C, class D>
637 struct ParamTraits<base::Tuple<A, B, C, D>> {
638 typedef base::Tuple<A, B, C, D> param_type;
639 static void Write(Message* m, const param_type& p) {
640 WriteParam(m, base::get<0>(p));
641 WriteParam(m, base::get<1>(p));
642 WriteParam(m, base::get<2>(p));
643 WriteParam(m, base::get<3>(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)) &&
651 ReadParam(m, iter, &base::get<3>(*r)));
653 static void Log(const param_type& p, std::string* l) {
654 LogParam(base::get<0>(p), l);
655 l->append(", ");
656 LogParam(base::get<1>(p), l);
657 l->append(", ");
658 LogParam(base::get<2>(p), l);
659 l->append(", ");
660 LogParam(base::get<3>(p), l);
664 template <class A, class B, class C, class D, class E>
665 struct ParamTraits<base::Tuple<A, B, C, D, E>> {
666 typedef base::Tuple<A, B, C, D, E> param_type;
667 static void Write(Message* m, const param_type& p) {
668 WriteParam(m, base::get<0>(p));
669 WriteParam(m, base::get<1>(p));
670 WriteParam(m, base::get<2>(p));
671 WriteParam(m, base::get<3>(p));
672 WriteParam(m, base::get<4>(p));
674 static bool Read(const Message* m,
675 base::PickleIterator* iter,
676 param_type* r) {
677 return (ReadParam(m, iter, &base::get<0>(*r)) &&
678 ReadParam(m, iter, &base::get<1>(*r)) &&
679 ReadParam(m, iter, &base::get<2>(*r)) &&
680 ReadParam(m, iter, &base::get<3>(*r)) &&
681 ReadParam(m, iter, &base::get<4>(*r)));
683 static void Log(const param_type& p, std::string* l) {
684 LogParam(base::get<0>(p), l);
685 l->append(", ");
686 LogParam(base::get<1>(p), l);
687 l->append(", ");
688 LogParam(base::get<2>(p), l);
689 l->append(", ");
690 LogParam(base::get<3>(p), l);
691 l->append(", ");
692 LogParam(base::get<4>(p), l);
696 template<class P>
697 struct ParamTraits<ScopedVector<P> > {
698 typedef ScopedVector<P> param_type;
699 static void Write(Message* m, const param_type& p) {
700 WriteParam(m, static_cast<int>(p.size()));
701 for (size_t i = 0; i < p.size(); i++)
702 WriteParam(m, *p[i]);
704 static bool Read(const Message* m,
705 base::PickleIterator* iter,
706 param_type* r) {
707 int size = 0;
708 if (!iter->ReadLength(&size))
709 return false;
710 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
711 return false;
712 r->resize(size);
713 for (int i = 0; i < size; i++) {
714 (*r)[i] = new P();
715 if (!ReadParam(m, iter, (*r)[i]))
716 return false;
718 return true;
720 static void Log(const param_type& p, std::string* l) {
721 for (size_t i = 0; i < p.size(); ++i) {
722 if (i != 0)
723 l->append(" ");
724 LogParam(*p[i], l);
729 template <typename NormalMap,
730 int kArraySize,
731 typename EqualKey,
732 typename MapInit>
733 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
734 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
735 typedef typename param_type::key_type K;
736 typedef typename param_type::data_type V;
737 static void Write(Message* m, const param_type& p) {
738 WriteParam(m, static_cast<int>(p.size()));
739 typename param_type::const_iterator iter;
740 for (iter = p.begin(); iter != p.end(); ++iter) {
741 WriteParam(m, iter->first);
742 WriteParam(m, iter->second);
745 static bool Read(const Message* m,
746 base::PickleIterator* iter,
747 param_type* r) {
748 int size;
749 if (!iter->ReadLength(&size))
750 return false;
751 for (int i = 0; i < size; ++i) {
752 K key;
753 if (!ReadParam(m, iter, &key))
754 return false;
755 V& value = (*r)[key];
756 if (!ReadParam(m, iter, &value))
757 return false;
759 return true;
761 static void Log(const param_type& p, std::string* l) {
762 l->append("<base::SmallMap>");
766 template <class P>
767 struct ParamTraits<scoped_ptr<P> > {
768 typedef scoped_ptr<P> param_type;
769 static void Write(Message* m, const param_type& p) {
770 bool valid = !!p;
771 WriteParam(m, valid);
772 if (valid)
773 WriteParam(m, *p);
775 static bool Read(const Message* m,
776 base::PickleIterator* iter,
777 param_type* r) {
778 bool valid = false;
779 if (!ReadParam(m, iter, &valid))
780 return false;
782 if (!valid) {
783 r->reset();
784 return true;
787 param_type temp(new P());
788 if (!ReadParam(m, iter, temp.get()))
789 return false;
791 r->swap(temp);
792 return true;
794 static void Log(const param_type& p, std::string* l) {
795 if (p)
796 LogParam(*p, l);
797 else
798 l->append("NULL");
802 // IPC types ParamTraits -------------------------------------------------------
804 // A ChannelHandle is basically a platform-inspecific wrapper around the
805 // fact that IPC endpoints are handled specially on POSIX. See above comments
806 // on FileDescriptor for more background.
807 template<>
808 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
809 typedef ChannelHandle param_type;
810 static void Write(Message* m, const param_type& p);
811 static bool Read(const Message* m,
812 base::PickleIterator* iter,
813 param_type* r);
814 static void Log(const param_type& p, std::string* l);
817 template <>
818 struct IPC_EXPORT ParamTraits<LogData> {
819 typedef LogData param_type;
820 static void Write(Message* m, const param_type& p);
821 static bool Read(const Message* m,
822 base::PickleIterator* iter,
823 param_type* r);
824 static void Log(const param_type& p, std::string* l);
827 template <>
828 struct IPC_EXPORT ParamTraits<Message> {
829 static void Write(Message* m, const Message& p);
830 static bool Read(const Message* m,
831 base::PickleIterator* iter,
832 Message* r);
833 static void Log(const Message& p, std::string* l);
836 // Windows ParamTraits ---------------------------------------------------------
838 #if defined(OS_WIN)
839 template <>
840 struct IPC_EXPORT ParamTraits<HANDLE> {
841 typedef HANDLE param_type;
842 static void Write(Message* m, const param_type& p);
843 static bool Read(const Message* m,
844 base::PickleIterator* iter,
845 param_type* r);
846 static void Log(const param_type& p, std::string* l);
849 template <>
850 struct IPC_EXPORT ParamTraits<LOGFONT> {
851 typedef LOGFONT param_type;
852 static void Write(Message* m, const param_type& p);
853 static bool Read(const Message* m,
854 base::PickleIterator* iter,
855 param_type* r);
856 static void Log(const param_type& p, std::string* l);
859 template <>
860 struct IPC_EXPORT ParamTraits<MSG> {
861 typedef MSG param_type;
862 static void Write(Message* m, const param_type& p);
863 static bool Read(const Message* m,
864 base::PickleIterator* iter,
865 param_type* r);
866 static void Log(const param_type& p, std::string* l);
868 #endif // defined(OS_WIN)
870 //-----------------------------------------------------------------------------
871 // Generic message subclasses
873 // Used for asynchronous messages.
874 template <class ParamType>
875 class MessageSchema {
876 public:
877 typedef ParamType Param;
878 typedef typename base::TupleTypes<ParamType>::ParamTuple RefParam;
880 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
881 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
884 // defined in ipc_logging.cc
885 IPC_EXPORT void GenerateLogData(const std::string& channel,
886 const Message& message,
887 LogData* data, bool get_params);
890 #if defined(IPC_MESSAGE_LOG_ENABLED)
891 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
892 const std::string& output_params = msg->output_params();
893 if (!l->empty() && !output_params.empty())
894 l->append(", ");
896 l->append(output_params);
899 template <class ReplyParamType>
900 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
901 const Message* msg) {
902 if (msg->received_time() != 0) {
903 std::string output_params;
904 LogParam(reply_params, &output_params);
905 msg->set_output_params(output_params);
909 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
910 if (msg->sent_time()) {
911 // Don't log the sync message after dispatch, as we don't have the
912 // output parameters at that point. Instead, save its data and log it
913 // with the outgoing reply message when it's sent.
914 LogData* data = new LogData;
915 GenerateLogData("", *msg, data, true);
916 msg->set_dont_log();
917 reply->set_sync_log_data(data);
920 #else
921 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
923 template <class ReplyParamType>
924 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
925 const Message* msg) {}
927 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
928 #endif
930 // This class assumes that its template argument is a RefTuple (a Tuple with
931 // reference elements). This would go into ipc_message_utils_impl.h, but it is
932 // also used by chrome_frame.
933 template <class RefTuple>
934 class ParamDeserializer : public MessageReplyDeserializer {
935 public:
936 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
938 bool SerializeOutputParameters(const IPC::Message& msg,
939 base::PickleIterator iter) override {
940 return ReadParam(&msg, &iter, &out_);
943 RefTuple out_;
946 // Used for synchronous messages.
947 template <class SendParamType, class ReplyParamType>
948 class SyncMessageSchema {
949 public:
950 typedef SendParamType SendParam;
951 typedef typename base::TupleTypes<SendParam>::ParamTuple RefSendParam;
952 typedef ReplyParamType ReplyParam;
954 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
955 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
956 static bool ReadReplyParam(
957 const Message* msg,
958 typename base::TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
960 template<class T, class S, class Method>
961 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
962 const Message* msg, T* obj, S* sender,
963 Method func) {
964 Message* reply = SyncMessage::GenerateReply(msg);
965 if (ok) {
966 typename base::TupleTypes<ReplyParam>::ValueTuple reply_params;
967 DispatchToMethod(obj, func, send_params, &reply_params);
968 WriteParam(reply, reply_params);
969 LogReplyParamsToMessage(reply_params, msg);
970 } else {
971 NOTREACHED() << "Error deserializing message " << msg->type();
972 reply->set_reply_error();
974 sender->Send(reply);
975 return ok;
978 template<class T, class Method>
979 static bool DispatchDelayReplyWithSendParams(bool ok,
980 const SendParam& send_params,
981 const Message* msg, T* obj,
982 Method func) {
983 Message* reply = SyncMessage::GenerateReply(msg);
984 if (ok) {
985 base::Tuple<Message&> t = base::MakeRefTuple(*reply);
986 ConnectMessageAndReply(msg, reply);
987 DispatchToMethod(obj, func, send_params, &t);
988 } else {
989 NOTREACHED() << "Error deserializing message " << msg->type();
990 reply->set_reply_error();
991 obj->Send(reply);
993 return ok;
996 template <typename... Ts>
997 static void WriteReplyParams(Message* reply, Ts... args) {
998 ReplyParam p(args...);
999 WriteParam(reply, p);
1003 } // namespace IPC
1005 #endif // IPC_IPC_MESSAGE_UTILS_H_