Use a deque in ResourcePool instead of a list.
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blob1e3ee0caded15e1deddffde3e9b5056f48a78921
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 ReadParam(const Message* m,
100 PickleIterator* iter,
101 P* p) {
102 typedef typename SimilarTypeTraits<P>::Type Type;
103 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
106 template <class P>
107 static inline void LogParam(const P& p, std::string* l) {
108 typedef typename SimilarTypeTraits<P>::Type Type;
109 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
112 // Primitive ParamTraits -------------------------------------------------------
114 template <>
115 struct ParamTraits<bool> {
116 typedef bool param_type;
117 static void Write(Message* m, const param_type& p) {
118 m->WriteBool(p);
120 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
121 return iter->ReadBool(r);
123 IPC_EXPORT static void Log(const param_type& p, std::string* l);
126 template <>
127 struct IPC_EXPORT ParamTraits<unsigned char> {
128 typedef unsigned char param_type;
129 static void Write(Message* m, const param_type& p);
130 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
131 static void Log(const param_type& p, std::string* l);
134 template <>
135 struct IPC_EXPORT ParamTraits<unsigned short> {
136 typedef unsigned short param_type;
137 static void Write(Message* m, const param_type& p);
138 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
139 static void Log(const param_type& p, std::string* l);
142 template <>
143 struct ParamTraits<int> {
144 typedef int param_type;
145 static void Write(Message* m, const param_type& p) {
146 m->WriteInt(p);
148 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
149 return iter->ReadInt(r);
151 IPC_EXPORT static void Log(const param_type& p, std::string* l);
154 template <>
155 struct ParamTraits<unsigned int> {
156 typedef unsigned int param_type;
157 static void Write(Message* m, const param_type& p) {
158 m->WriteInt(p);
160 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
161 return iter->ReadInt(reinterpret_cast<int*>(r));
163 IPC_EXPORT static void Log(const param_type& p, std::string* l);
166 template <>
167 struct ParamTraits<long> {
168 typedef long param_type;
169 static void Write(Message* m, const param_type& p) {
170 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
172 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
173 return iter->ReadLong(r);
175 IPC_EXPORT static void Log(const param_type& p, std::string* l);
178 template <>
179 struct ParamTraits<unsigned long> {
180 typedef unsigned long param_type;
181 static void Write(Message* m, const param_type& p) {
182 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
184 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
185 return iter->ReadLong(reinterpret_cast<long*>(r));
187 IPC_EXPORT static void Log(const param_type& p, std::string* l);
190 template <>
191 struct ParamTraits<long long> {
192 typedef long long param_type;
193 static void Write(Message* m, const param_type& p) {
194 m->WriteInt64(static_cast<int64>(p));
196 static bool Read(const Message* m, PickleIterator* iter,
197 param_type* r) {
198 return iter->ReadInt64(reinterpret_cast<int64*>(r));
200 IPC_EXPORT static void Log(const param_type& p, std::string* l);
203 template <>
204 struct ParamTraits<unsigned long long> {
205 typedef unsigned long long param_type;
206 static void Write(Message* m, const param_type& p) {
207 m->WriteInt64(p);
209 static bool Read(const Message* m, PickleIterator* iter,
210 param_type* r) {
211 return iter->ReadInt64(reinterpret_cast<int64*>(r));
213 IPC_EXPORT static void Log(const param_type& p, std::string* l);
216 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
217 // should be sure to check the sanity of these values after receiving them over
218 // IPC.
219 template <>
220 struct IPC_EXPORT ParamTraits<float> {
221 typedef float param_type;
222 static void Write(Message* m, const param_type& p) {
223 m->WriteFloat(p);
225 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
226 return iter->ReadFloat(r);
228 static void Log(const param_type& p, std::string* l);
231 template <>
232 struct IPC_EXPORT ParamTraits<double> {
233 typedef double param_type;
234 static void Write(Message* m, const param_type& p);
235 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
236 static void Log(const param_type& p, std::string* l);
239 // STL ParamTraits -------------------------------------------------------------
241 template <>
242 struct ParamTraits<std::string> {
243 typedef std::string param_type;
244 static void Write(Message* m, const param_type& p) {
245 m->WriteString(p);
247 static bool Read(const Message* m, PickleIterator* iter,
248 param_type* r) {
249 return iter->ReadString(r);
251 IPC_EXPORT static void Log(const param_type& p, std::string* l);
254 template <>
255 struct ParamTraits<base::string16> {
256 typedef base::string16 param_type;
257 static void Write(Message* m, const param_type& p) {
258 m->WriteString16(p);
260 static bool Read(const Message* m, PickleIterator* iter,
261 param_type* r) {
262 return iter->ReadString16(r);
264 IPC_EXPORT static void Log(const param_type& p, std::string* l);
267 template <>
268 struct IPC_EXPORT ParamTraits<std::vector<char> > {
269 typedef std::vector<char> param_type;
270 static void Write(Message* m, const param_type& p);
271 static bool Read(const Message*, PickleIterator* iter, param_type* r);
272 static void Log(const param_type& p, std::string* l);
275 template <>
276 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
277 typedef std::vector<unsigned char> param_type;
278 static void Write(Message* m, const param_type& p);
279 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
280 static void Log(const param_type& p, std::string* l);
283 template <>
284 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
285 typedef std::vector<bool> param_type;
286 static void Write(Message* m, const param_type& p);
287 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
288 static void Log(const param_type& p, std::string* l);
291 template <class P>
292 struct ParamTraits<std::vector<P> > {
293 typedef std::vector<P> param_type;
294 static void Write(Message* m, const param_type& p) {
295 WriteParam(m, static_cast<int>(p.size()));
296 for (size_t i = 0; i < p.size(); i++)
297 WriteParam(m, p[i]);
299 static bool Read(const Message* m, PickleIterator* iter,
300 param_type* r) {
301 int size;
302 // ReadLength() checks for < 0 itself.
303 if (!iter->ReadLength(&size))
304 return false;
305 // Resizing beforehand is not safe, see BUG 1006367 for details.
306 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
307 return false;
308 r->resize(size);
309 for (int i = 0; i < size; i++) {
310 if (!ReadParam(m, iter, &(*r)[i]))
311 return false;
313 return true;
315 static void Log(const param_type& p, std::string* l) {
316 for (size_t i = 0; i < p.size(); ++i) {
317 if (i != 0)
318 l->append(" ");
319 LogParam((p[i]), l);
324 template <class P>
325 struct ParamTraits<std::set<P> > {
326 typedef std::set<P> param_type;
327 static void Write(Message* m, const param_type& p) {
328 WriteParam(m, static_cast<int>(p.size()));
329 typename param_type::const_iterator iter;
330 for (iter = p.begin(); iter != p.end(); ++iter)
331 WriteParam(m, *iter);
333 static bool Read(const Message* m, PickleIterator* iter,
334 param_type* r) {
335 int size;
336 if (!iter->ReadLength(&size))
337 return false;
338 for (int i = 0; i < size; ++i) {
339 P item;
340 if (!ReadParam(m, iter, &item))
341 return false;
342 r->insert(item);
344 return true;
346 static void Log(const param_type& p, std::string* l) {
347 l->append("<std::set>");
351 template <class K, class V, class C, class A>
352 struct ParamTraits<std::map<K, V, C, A> > {
353 typedef std::map<K, V, C, A> param_type;
354 static void Write(Message* m, const param_type& p) {
355 WriteParam(m, static_cast<int>(p.size()));
356 typename param_type::const_iterator iter;
357 for (iter = p.begin(); iter != p.end(); ++iter) {
358 WriteParam(m, iter->first);
359 WriteParam(m, iter->second);
362 static bool Read(const Message* m, PickleIterator* iter,
363 param_type* r) {
364 int size;
365 if (!ReadParam(m, iter, &size) || size < 0)
366 return false;
367 for (int i = 0; i < size; ++i) {
368 K k;
369 if (!ReadParam(m, iter, &k))
370 return false;
371 V& value = (*r)[k];
372 if (!ReadParam(m, iter, &value))
373 return false;
375 return true;
377 static void Log(const param_type& p, std::string* l) {
378 l->append("<std::map>");
382 template <class A, class B>
383 struct ParamTraits<std::pair<A, B> > {
384 typedef std::pair<A, B> param_type;
385 static void Write(Message* m, const param_type& p) {
386 WriteParam(m, p.first);
387 WriteParam(m, p.second);
389 static bool Read(const Message* m, PickleIterator* iter,
390 param_type* r) {
391 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
393 static void Log(const param_type& p, std::string* l) {
394 l->append("(");
395 LogParam(p.first, l);
396 l->append(", ");
397 LogParam(p.second, l);
398 l->append(")");
402 // Base ParamTraits ------------------------------------------------------------
404 template <>
405 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
406 typedef base::DictionaryValue param_type;
407 static void Write(Message* m, const param_type& p);
408 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
409 static void Log(const param_type& p, std::string* l);
412 #if defined(OS_POSIX)
413 // FileDescriptors may be serialised over IPC channels on POSIX. On the
414 // receiving side, the FileDescriptor is a valid duplicate of the file
415 // descriptor which was transmitted: *it is not just a copy of the integer like
416 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
417 // this case, the receiving end will see a value of -1. *Zero is a valid file
418 // descriptor*.
420 // The received file descriptor will have the |auto_close| flag set to true. The
421 // code which handles the message is responsible for taking ownership of it.
422 // File descriptors are OS resources and must be closed when no longer needed.
424 // When sending a file descriptor, the file descriptor must be valid at the time
425 // of transmission. Since transmission is not synchronous, one should consider
426 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
427 // flag, which causes the file descriptor to be closed after writing.
428 template<>
429 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
430 typedef base::FileDescriptor param_type;
431 static void Write(Message* m, const param_type& p);
432 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
433 static void Log(const param_type& p, std::string* l);
435 #endif // defined(OS_POSIX)
437 template <>
438 struct IPC_EXPORT ParamTraits<base::FilePath> {
439 typedef base::FilePath param_type;
440 static void Write(Message* m, const param_type& p);
441 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
442 static void Log(const param_type& p, std::string* l);
445 template <>
446 struct IPC_EXPORT ParamTraits<base::ListValue> {
447 typedef base::ListValue param_type;
448 static void Write(Message* m, const param_type& p);
449 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
450 static void Log(const param_type& p, std::string* l);
453 template <>
454 struct IPC_EXPORT ParamTraits<base::NullableString16> {
455 typedef base::NullableString16 param_type;
456 static void Write(Message* m, const param_type& p);
457 static bool Read(const Message* m, PickleIterator* iter,
458 param_type* r);
459 static void Log(const param_type& p, std::string* l);
462 template <>
463 struct IPC_EXPORT ParamTraits<base::File::Info> {
464 typedef base::File::Info param_type;
465 static void Write(Message* m, const param_type& p);
466 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
467 static void Log(const param_type& p, std::string* l);
470 template <>
471 struct SimilarTypeTraits<base::File::Error> {
472 typedef int Type;
475 #if defined(OS_WIN)
476 template <>
477 struct SimilarTypeTraits<HWND> {
478 typedef HANDLE Type;
480 #endif // defined(OS_WIN)
482 template <>
483 struct IPC_EXPORT ParamTraits<base::Time> {
484 typedef base::Time param_type;
485 static void Write(Message* m, const param_type& p);
486 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
487 static void Log(const param_type& p, std::string* l);
490 template <>
491 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
492 typedef base::TimeDelta param_type;
493 static void Write(Message* m, const param_type& p);
494 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
495 static void Log(const param_type& p, std::string* l);
498 template <>
499 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
500 typedef base::TimeTicks param_type;
501 static void Write(Message* m, const param_type& p);
502 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
503 static void Log(const param_type& p, std::string* l);
506 template <>
507 struct IPC_EXPORT ParamTraits<base::TraceTicks> {
508 typedef base::TraceTicks param_type;
509 static void Write(Message* m, const param_type& p);
510 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
511 static void Log(const param_type& p, std::string* l);
514 template <>
515 struct ParamTraits<base::Tuple<>> {
516 typedef base::Tuple<> param_type;
517 static void Write(Message* m, const param_type& p) {
519 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
520 return true;
522 static void Log(const param_type& p, std::string* l) {
526 template <class A>
527 struct ParamTraits<base::Tuple<A>> {
528 typedef base::Tuple<A> param_type;
529 static void Write(Message* m, const param_type& p) {
530 WriteParam(m, base::get<0>(p));
532 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
533 return ReadParam(m, iter, &base::get<0>(*r));
535 static void Log(const param_type& p, std::string* l) {
536 LogParam(base::get<0>(p), l);
540 template <class A, class B>
541 struct ParamTraits<base::Tuple<A, B>> {
542 typedef base::Tuple<A, B> param_type;
543 static void Write(Message* m, const param_type& p) {
544 WriteParam(m, base::get<0>(p));
545 WriteParam(m, base::get<1>(p));
547 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
548 return (ReadParam(m, iter, &base::get<0>(*r)) &&
549 ReadParam(m, iter, &base::get<1>(*r)));
551 static void Log(const param_type& p, std::string* l) {
552 LogParam(base::get<0>(p), l);
553 l->append(", ");
554 LogParam(base::get<1>(p), l);
558 template <class A, class B, class C>
559 struct ParamTraits<base::Tuple<A, B, C>> {
560 typedef base::Tuple<A, B, C> param_type;
561 static void Write(Message* m, const param_type& p) {
562 WriteParam(m, base::get<0>(p));
563 WriteParam(m, base::get<1>(p));
564 WriteParam(m, base::get<2>(p));
566 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
567 return (ReadParam(m, iter, &base::get<0>(*r)) &&
568 ReadParam(m, iter, &base::get<1>(*r)) &&
569 ReadParam(m, iter, &base::get<2>(*r)));
571 static void Log(const param_type& p, std::string* l) {
572 LogParam(base::get<0>(p), l);
573 l->append(", ");
574 LogParam(base::get<1>(p), l);
575 l->append(", ");
576 LogParam(base::get<2>(p), l);
580 template <class A, class B, class C, class D>
581 struct ParamTraits<base::Tuple<A, B, C, D>> {
582 typedef base::Tuple<A, B, C, D> param_type;
583 static void Write(Message* m, const param_type& p) {
584 WriteParam(m, base::get<0>(p));
585 WriteParam(m, base::get<1>(p));
586 WriteParam(m, base::get<2>(p));
587 WriteParam(m, base::get<3>(p));
589 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
590 return (ReadParam(m, iter, &base::get<0>(*r)) &&
591 ReadParam(m, iter, &base::get<1>(*r)) &&
592 ReadParam(m, iter, &base::get<2>(*r)) &&
593 ReadParam(m, iter, &base::get<3>(*r)));
595 static void Log(const param_type& p, std::string* l) {
596 LogParam(base::get<0>(p), l);
597 l->append(", ");
598 LogParam(base::get<1>(p), l);
599 l->append(", ");
600 LogParam(base::get<2>(p), l);
601 l->append(", ");
602 LogParam(base::get<3>(p), l);
606 template <class A, class B, class C, class D, class E>
607 struct ParamTraits<base::Tuple<A, B, C, D, E>> {
608 typedef base::Tuple<A, B, C, D, E> param_type;
609 static void Write(Message* m, const param_type& p) {
610 WriteParam(m, base::get<0>(p));
611 WriteParam(m, base::get<1>(p));
612 WriteParam(m, base::get<2>(p));
613 WriteParam(m, base::get<3>(p));
614 WriteParam(m, base::get<4>(p));
616 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
617 return (ReadParam(m, iter, &base::get<0>(*r)) &&
618 ReadParam(m, iter, &base::get<1>(*r)) &&
619 ReadParam(m, iter, &base::get<2>(*r)) &&
620 ReadParam(m, iter, &base::get<3>(*r)) &&
621 ReadParam(m, iter, &base::get<4>(*r)));
623 static void Log(const param_type& p, std::string* l) {
624 LogParam(base::get<0>(p), l);
625 l->append(", ");
626 LogParam(base::get<1>(p), l);
627 l->append(", ");
628 LogParam(base::get<2>(p), l);
629 l->append(", ");
630 LogParam(base::get<3>(p), l);
631 l->append(", ");
632 LogParam(base::get<4>(p), l);
636 template<class P>
637 struct ParamTraits<ScopedVector<P> > {
638 typedef ScopedVector<P> param_type;
639 static void Write(Message* m, const param_type& p) {
640 WriteParam(m, static_cast<int>(p.size()));
641 for (size_t i = 0; i < p.size(); i++)
642 WriteParam(m, *p[i]);
644 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
645 int size = 0;
646 if (!iter->ReadLength(&size))
647 return false;
648 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
649 return false;
650 r->resize(size);
651 for (int i = 0; i < size; i++) {
652 (*r)[i] = new P();
653 if (!ReadParam(m, iter, (*r)[i]))
654 return false;
656 return true;
658 static void Log(const param_type& p, std::string* l) {
659 for (size_t i = 0; i < p.size(); ++i) {
660 if (i != 0)
661 l->append(" ");
662 LogParam(*p[i], l);
667 template <typename NormalMap,
668 int kArraySize,
669 typename EqualKey,
670 typename MapInit>
671 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
672 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
673 typedef typename param_type::key_type K;
674 typedef typename param_type::data_type V;
675 static void Write(Message* m, const param_type& p) {
676 WriteParam(m, static_cast<int>(p.size()));
677 typename param_type::const_iterator iter;
678 for (iter = p.begin(); iter != p.end(); ++iter) {
679 WriteParam(m, iter->first);
680 WriteParam(m, iter->second);
683 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
684 int size;
685 if (!iter->ReadLength(&size))
686 return false;
687 for (int i = 0; i < size; ++i) {
688 K key;
689 if (!ReadParam(m, iter, &key))
690 return false;
691 V& value = (*r)[key];
692 if (!ReadParam(m, iter, &value))
693 return false;
695 return true;
697 static void Log(const param_type& p, std::string* l) {
698 l->append("<base::SmallMap>");
702 template <class P>
703 struct ParamTraits<scoped_ptr<P> > {
704 typedef scoped_ptr<P> param_type;
705 static void Write(Message* m, const param_type& p) {
706 bool valid = !!p;
707 WriteParam(m, valid);
708 if (valid)
709 WriteParam(m, *p);
711 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
712 bool valid = false;
713 if (!ReadParam(m, iter, &valid))
714 return false;
716 if (!valid) {
717 r->reset();
718 return true;
721 param_type temp(new P());
722 if (!ReadParam(m, iter, temp.get()))
723 return false;
725 r->swap(temp);
726 return true;
728 static void Log(const param_type& p, std::string* l) {
729 if (p)
730 LogParam(*p, l);
731 else
732 l->append("NULL");
736 // IPC types ParamTraits -------------------------------------------------------
738 // A ChannelHandle is basically a platform-inspecific wrapper around the
739 // fact that IPC endpoints are handled specially on POSIX. See above comments
740 // on FileDescriptor for more background.
741 template<>
742 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
743 typedef ChannelHandle param_type;
744 static void Write(Message* m, const param_type& p);
745 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
746 static void Log(const param_type& p, std::string* l);
749 template <>
750 struct IPC_EXPORT ParamTraits<LogData> {
751 typedef LogData param_type;
752 static void Write(Message* m, const param_type& p);
753 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
754 static void Log(const param_type& p, std::string* l);
757 template <>
758 struct IPC_EXPORT ParamTraits<Message> {
759 static void Write(Message* m, const Message& p);
760 static bool Read(const Message* m, PickleIterator* iter, Message* r);
761 static void Log(const Message& p, std::string* l);
764 // Windows ParamTraits ---------------------------------------------------------
766 #if defined(OS_WIN)
767 template <>
768 struct IPC_EXPORT ParamTraits<HANDLE> {
769 typedef HANDLE param_type;
770 static void Write(Message* m, const param_type& p);
771 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
772 static void Log(const param_type& p, std::string* l);
775 template <>
776 struct IPC_EXPORT ParamTraits<LOGFONT> {
777 typedef LOGFONT param_type;
778 static void Write(Message* m, const param_type& p);
779 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
780 static void Log(const param_type& p, std::string* l);
783 template <>
784 struct IPC_EXPORT ParamTraits<MSG> {
785 typedef MSG param_type;
786 static void Write(Message* m, const param_type& p);
787 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
788 static void Log(const param_type& p, std::string* l);
790 #endif // defined(OS_WIN)
792 //-----------------------------------------------------------------------------
793 // Generic message subclasses
795 // Used for asynchronous messages.
796 template <class ParamType>
797 class MessageSchema {
798 public:
799 typedef ParamType Param;
800 typedef typename base::TupleTypes<ParamType>::ParamTuple RefParam;
802 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
803 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
806 // defined in ipc_logging.cc
807 IPC_EXPORT void GenerateLogData(const std::string& channel,
808 const Message& message,
809 LogData* data, bool get_params);
812 #if defined(IPC_MESSAGE_LOG_ENABLED)
813 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
814 const std::string& output_params = msg->output_params();
815 if (!l->empty() && !output_params.empty())
816 l->append(", ");
818 l->append(output_params);
821 template <class ReplyParamType>
822 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
823 const Message* msg) {
824 if (msg->received_time() != 0) {
825 std::string output_params;
826 LogParam(reply_params, &output_params);
827 msg->set_output_params(output_params);
831 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
832 if (msg->sent_time()) {
833 // Don't log the sync message after dispatch, as we don't have the
834 // output parameters at that point. Instead, save its data and log it
835 // with the outgoing reply message when it's sent.
836 LogData* data = new LogData;
837 GenerateLogData("", *msg, data, true);
838 msg->set_dont_log();
839 reply->set_sync_log_data(data);
842 #else
843 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
845 template <class ReplyParamType>
846 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
847 const Message* msg) {}
849 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
850 #endif
852 // This class assumes that its template argument is a RefTuple (a Tuple with
853 // reference elements). This would go into ipc_message_utils_impl.h, but it is
854 // also used by chrome_frame.
855 template <class RefTuple>
856 class ParamDeserializer : public MessageReplyDeserializer {
857 public:
858 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
860 bool SerializeOutputParameters(const IPC::Message& msg,
861 PickleIterator iter) override {
862 return ReadParam(&msg, &iter, &out_);
865 RefTuple out_;
868 // Used for synchronous messages.
869 template <class SendParamType, class ReplyParamType>
870 class SyncMessageSchema {
871 public:
872 typedef SendParamType SendParam;
873 typedef typename base::TupleTypes<SendParam>::ParamTuple RefSendParam;
874 typedef ReplyParamType ReplyParam;
876 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
877 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
878 static bool ReadReplyParam(
879 const Message* msg,
880 typename base::TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
882 template<class T, class S, class Method>
883 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
884 const Message* msg, T* obj, S* sender,
885 Method func) {
886 Message* reply = SyncMessage::GenerateReply(msg);
887 if (ok) {
888 typename base::TupleTypes<ReplyParam>::ValueTuple reply_params;
889 DispatchToMethod(obj, func, send_params, &reply_params);
890 WriteParam(reply, reply_params);
891 LogReplyParamsToMessage(reply_params, msg);
892 } else {
893 NOTREACHED() << "Error deserializing message " << msg->type();
894 reply->set_reply_error();
896 sender->Send(reply);
897 return ok;
900 template<class T, class Method>
901 static bool DispatchDelayReplyWithSendParams(bool ok,
902 const SendParam& send_params,
903 const Message* msg, T* obj,
904 Method func) {
905 Message* reply = SyncMessage::GenerateReply(msg);
906 if (ok) {
907 base::Tuple<Message&> t = base::MakeRefTuple(*reply);
908 ConnectMessageAndReply(msg, reply);
909 DispatchToMethod(obj, func, send_params, &t);
910 } else {
911 NOTREACHED() << "Error deserializing message " << msg->type();
912 reply->set_reply_error();
913 obj->Send(reply);
915 return ok;
918 template <typename... Ts>
919 static void WriteReplyParams(Message* reply, Ts... args) {
920 ReplyParam p(args...);
921 WriteParam(reply, p);
925 } // namespace IPC
927 #endif // IPC_IPC_MESSAGE_UTILS_H_