Fix scroll regression when specifying an extension id.
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blob6787c8e2eb80dd0a6da16009c6eff03bedfe959e
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 struct FileDescriptor;
61 namespace IPC {
63 struct ChannelHandle;
65 // -----------------------------------------------------------------------------
66 // How we send IPC message logs across channels.
67 struct IPC_EXPORT LogData {
68 LogData();
69 ~LogData();
71 std::string channel;
72 int32 routing_id;
73 uint32 type; // "User-defined" message type, from ipc_message.h.
74 std::string flags;
75 int64 sent; // Time that the message was sent (i.e. at Send()).
76 int64 receive; // Time before it was dispatched (i.e. before calling
77 // OnMessageReceived).
78 int64 dispatch; // Time after it was dispatched (i.e. after calling
79 // OnMessageReceived).
80 std::string message_name;
81 std::string params;
84 //-----------------------------------------------------------------------------
86 // A dummy struct to place first just to allow leading commas for all
87 // members in the macro-generated constructor initializer lists.
88 struct NoParams {
91 template <class P>
92 static inline void WriteParam(Message* m, const P& p) {
93 typedef typename SimilarTypeTraits<P>::Type Type;
94 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
97 template <class P>
98 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m,
99 PickleIterator* iter,
100 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, PickleIterator* iter, param_type* r) {
120 return iter->ReadBool(r);
122 IPC_EXPORT static void Log(const param_type& p, std::string* l);
125 template <>
126 struct IPC_EXPORT ParamTraits<unsigned char> {
127 typedef unsigned char param_type;
128 static void Write(Message* m, const param_type& p);
129 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
130 static void Log(const param_type& p, std::string* l);
133 template <>
134 struct IPC_EXPORT ParamTraits<unsigned short> {
135 typedef unsigned short param_type;
136 static void Write(Message* m, const param_type& p);
137 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
138 static void Log(const param_type& p, std::string* l);
141 template <>
142 struct ParamTraits<int> {
143 typedef int param_type;
144 static void Write(Message* m, const param_type& p) {
145 m->WriteInt(p);
147 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
148 return iter->ReadInt(r);
150 IPC_EXPORT static void Log(const param_type& p, std::string* l);
153 template <>
154 struct ParamTraits<unsigned int> {
155 typedef unsigned int param_type;
156 static void Write(Message* m, const param_type& p) {
157 m->WriteInt(p);
159 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
160 return iter->ReadInt(reinterpret_cast<int*>(r));
162 IPC_EXPORT static void Log(const param_type& p, std::string* l);
165 template <>
166 struct ParamTraits<long> {
167 typedef long param_type;
168 static void Write(Message* m, const param_type& p) {
169 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
171 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
172 return iter->ReadLong(r);
174 IPC_EXPORT static void Log(const param_type& p, std::string* l);
177 template <>
178 struct ParamTraits<unsigned long> {
179 typedef unsigned long param_type;
180 static void Write(Message* m, const param_type& p) {
181 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
183 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
184 return iter->ReadLong(reinterpret_cast<long*>(r));
186 IPC_EXPORT static void Log(const param_type& p, std::string* l);
189 template <>
190 struct ParamTraits<long long> {
191 typedef long long param_type;
192 static void Write(Message* m, const param_type& p) {
193 m->WriteInt64(static_cast<int64>(p));
195 static bool Read(const Message* m, PickleIterator* iter,
196 param_type* r) {
197 return iter->ReadInt64(reinterpret_cast<int64*>(r));
199 IPC_EXPORT static void Log(const param_type& p, std::string* l);
202 template <>
203 struct ParamTraits<unsigned long long> {
204 typedef unsigned long long param_type;
205 static void Write(Message* m, const param_type& p) {
206 m->WriteInt64(p);
208 static bool Read(const Message* m, 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 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
216 // should be sure to check the sanity of these values after receiving them over
217 // IPC.
218 template <>
219 struct IPC_EXPORT ParamTraits<float> {
220 typedef float param_type;
221 static void Write(Message* m, const param_type& p) {
222 m->WriteFloat(p);
224 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
225 return iter->ReadFloat(r);
227 static void Log(const param_type& p, std::string* l);
230 template <>
231 struct IPC_EXPORT ParamTraits<double> {
232 typedef double param_type;
233 static void Write(Message* m, const param_type& p);
234 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
235 static void Log(const param_type& p, std::string* l);
238 // STL ParamTraits -------------------------------------------------------------
240 template <>
241 struct ParamTraits<std::string> {
242 typedef std::string param_type;
243 static void Write(Message* m, const param_type& p) {
244 m->WriteString(p);
246 static bool Read(const Message* m, PickleIterator* iter,
247 param_type* r) {
248 return iter->ReadString(r);
250 IPC_EXPORT static void Log(const param_type& p, std::string* l);
253 template <>
254 struct ParamTraits<base::string16> {
255 typedef base::string16 param_type;
256 static void Write(Message* m, const param_type& p) {
257 m->WriteString16(p);
259 static bool Read(const Message* m, PickleIterator* iter,
260 param_type* r) {
261 return iter->ReadString16(r);
263 IPC_EXPORT static void Log(const param_type& p, std::string* l);
266 template <>
267 struct IPC_EXPORT ParamTraits<std::vector<char> > {
268 typedef std::vector<char> param_type;
269 static void Write(Message* m, const param_type& p);
270 static bool Read(const Message*, PickleIterator* iter, param_type* r);
271 static void Log(const param_type& p, std::string* l);
274 template <>
275 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
276 typedef std::vector<unsigned char> param_type;
277 static void Write(Message* m, const param_type& p);
278 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
279 static void Log(const param_type& p, std::string* l);
282 template <>
283 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
284 typedef std::vector<bool> param_type;
285 static void Write(Message* m, const param_type& p);
286 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
287 static void Log(const param_type& p, std::string* l);
290 template <class P>
291 struct ParamTraits<std::vector<P> > {
292 typedef std::vector<P> param_type;
293 static void Write(Message* m, const param_type& p) {
294 WriteParam(m, static_cast<int>(p.size()));
295 for (size_t i = 0; i < p.size(); i++)
296 WriteParam(m, p[i]);
298 static bool Read(const Message* m, PickleIterator* iter,
299 param_type* r) {
300 int size;
301 // ReadLength() checks for < 0 itself.
302 if (!iter->ReadLength(&size))
303 return false;
304 // Resizing beforehand is not safe, see BUG 1006367 for details.
305 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
306 return false;
307 r->resize(size);
308 for (int i = 0; i < size; i++) {
309 if (!ReadParam(m, iter, &(*r)[i]))
310 return false;
312 return true;
314 static void Log(const param_type& p, std::string* l) {
315 for (size_t i = 0; i < p.size(); ++i) {
316 if (i != 0)
317 l->append(" ");
318 LogParam((p[i]), l);
323 template <class P>
324 struct ParamTraits<std::set<P> > {
325 typedef std::set<P> param_type;
326 static void Write(Message* m, const param_type& p) {
327 WriteParam(m, static_cast<int>(p.size()));
328 typename param_type::const_iterator iter;
329 for (iter = p.begin(); iter != p.end(); ++iter)
330 WriteParam(m, *iter);
332 static bool Read(const Message* m, PickleIterator* iter,
333 param_type* r) {
334 int size;
335 if (!iter->ReadLength(&size))
336 return false;
337 for (int i = 0; i < size; ++i) {
338 P item;
339 if (!ReadParam(m, iter, &item))
340 return false;
341 r->insert(item);
343 return true;
345 static void Log(const param_type& p, std::string* l) {
346 l->append("<std::set>");
350 template <class K, class V, class C, class A>
351 struct ParamTraits<std::map<K, V, C, A> > {
352 typedef std::map<K, V, C, A> 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->first);
358 WriteParam(m, iter->second);
361 static bool Read(const Message* m, PickleIterator* iter,
362 param_type* r) {
363 int size;
364 if (!ReadParam(m, iter, &size) || size < 0)
365 return false;
366 for (int i = 0; i < size; ++i) {
367 K k;
368 if (!ReadParam(m, iter, &k))
369 return false;
370 V& value = (*r)[k];
371 if (!ReadParam(m, iter, &value))
372 return false;
374 return true;
376 static void Log(const param_type& p, std::string* l) {
377 l->append("<std::map>");
381 template <class A, class B>
382 struct ParamTraits<std::pair<A, B> > {
383 typedef std::pair<A, B> param_type;
384 static void Write(Message* m, const param_type& p) {
385 WriteParam(m, p.first);
386 WriteParam(m, p.second);
388 static bool Read(const Message* m, PickleIterator* iter,
389 param_type* r) {
390 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
392 static void Log(const param_type& p, std::string* l) {
393 l->append("(");
394 LogParam(p.first, l);
395 l->append(", ");
396 LogParam(p.second, l);
397 l->append(")");
401 // Base ParamTraits ------------------------------------------------------------
403 template <>
404 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
405 typedef base::DictionaryValue param_type;
406 static void Write(Message* m, const param_type& p);
407 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
408 static void Log(const param_type& p, std::string* l);
411 #if defined(OS_POSIX)
412 // FileDescriptors may be serialised over IPC channels on POSIX. On the
413 // receiving side, the FileDescriptor is a valid duplicate of the file
414 // descriptor which was transmitted: *it is not just a copy of the integer like
415 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
416 // this case, the receiving end will see a value of -1. *Zero is a valid file
417 // descriptor*.
419 // The received file descriptor will have the |auto_close| flag set to true. The
420 // code which handles the message is responsible for taking ownership of it.
421 // File descriptors are OS resources and must be closed when no longer needed.
423 // When sending a file descriptor, the file descriptor must be valid at the time
424 // of transmission. Since transmission is not synchronous, one should consider
425 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
426 // flag, which causes the file descriptor to be closed after writing.
427 template<>
428 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
429 typedef base::FileDescriptor param_type;
430 static void Write(Message* m, const param_type& p);
431 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
432 static void Log(const param_type& p, std::string* l);
434 #endif // defined(OS_POSIX)
436 template <>
437 struct IPC_EXPORT ParamTraits<base::FilePath> {
438 typedef base::FilePath param_type;
439 static void Write(Message* m, const param_type& p);
440 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
441 static void Log(const param_type& p, std::string* l);
444 template <>
445 struct IPC_EXPORT ParamTraits<base::ListValue> {
446 typedef base::ListValue param_type;
447 static void Write(Message* m, const param_type& p);
448 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
449 static void Log(const param_type& p, std::string* l);
452 template <>
453 struct IPC_EXPORT ParamTraits<base::NullableString16> {
454 typedef base::NullableString16 param_type;
455 static void Write(Message* m, const param_type& p);
456 static bool Read(const Message* m, PickleIterator* iter,
457 param_type* r);
458 static void Log(const param_type& p, std::string* l);
461 template <>
462 struct IPC_EXPORT ParamTraits<base::File::Info> {
463 typedef base::File::Info param_type;
464 static void Write(Message* m, const param_type& p);
465 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
466 static void Log(const param_type& p, std::string* l);
469 template <>
470 struct SimilarTypeTraits<base::File::Error> {
471 typedef int Type;
474 #if defined(OS_WIN)
475 template <>
476 struct SimilarTypeTraits<HWND> {
477 typedef HANDLE Type;
479 #endif // defined(OS_WIN)
481 template <>
482 struct IPC_EXPORT ParamTraits<base::Time> {
483 typedef base::Time param_type;
484 static void Write(Message* m, const param_type& p);
485 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
486 static void Log(const param_type& p, std::string* l);
489 template <>
490 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
491 typedef base::TimeDelta param_type;
492 static void Write(Message* m, const param_type& p);
493 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
494 static void Log(const param_type& p, std::string* l);
497 template <>
498 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
499 typedef base::TimeTicks param_type;
500 static void Write(Message* m, const param_type& p);
501 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
502 static void Log(const param_type& p, std::string* l);
505 template <>
506 struct ParamTraits<Tuple<>> {
507 typedef Tuple<> param_type;
508 static void Write(Message* m, const param_type& p) {
510 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
511 return true;
513 static void Log(const param_type& p, std::string* l) {
517 template <class A>
518 struct ParamTraits<Tuple<A>> {
519 typedef Tuple<A> param_type;
520 static void Write(Message* m, const param_type& p) {
521 WriteParam(m, get<0>(p));
523 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
524 return ReadParam(m, iter, &get<0>(*r));
526 static void Log(const param_type& p, std::string* l) {
527 LogParam(get<0>(p), l);
531 template <class A, class B>
532 struct ParamTraits< Tuple<A, B> > {
533 typedef Tuple<A, B> param_type;
534 static void Write(Message* m, const param_type& p) {
535 WriteParam(m, get<0>(p));
536 WriteParam(m, get<1>(p));
538 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
539 return (ReadParam(m, iter, &get<0>(*r)) &&
540 ReadParam(m, iter, &get<1>(*r)));
542 static void Log(const param_type& p, std::string* l) {
543 LogParam(get<0>(p), l);
544 l->append(", ");
545 LogParam(get<1>(p), l);
549 template <class A, class B, class C>
550 struct ParamTraits< Tuple<A, B, C> > {
551 typedef Tuple<A, B, C> param_type;
552 static void Write(Message* m, const param_type& p) {
553 WriteParam(m, get<0>(p));
554 WriteParam(m, get<1>(p));
555 WriteParam(m, get<2>(p));
557 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
558 return (ReadParam(m, iter, &get<0>(*r)) &&
559 ReadParam(m, iter, &get<1>(*r)) &&
560 ReadParam(m, iter, &get<2>(*r)));
562 static void Log(const param_type& p, std::string* l) {
563 LogParam(get<0>(p), l);
564 l->append(", ");
565 LogParam(get<1>(p), l);
566 l->append(", ");
567 LogParam(get<2>(p), l);
571 template <class A, class B, class C, class D>
572 struct ParamTraits< Tuple<A, B, C, D> > {
573 typedef Tuple<A, B, C, D> param_type;
574 static void Write(Message* m, const param_type& p) {
575 WriteParam(m, get<0>(p));
576 WriteParam(m, get<1>(p));
577 WriteParam(m, get<2>(p));
578 WriteParam(m, get<3>(p));
580 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
581 return (ReadParam(m, iter, &get<0>(*r)) &&
582 ReadParam(m, iter, &get<1>(*r)) &&
583 ReadParam(m, iter, &get<2>(*r)) &&
584 ReadParam(m, iter, &get<3>(*r)));
586 static void Log(const param_type& p, std::string* l) {
587 LogParam(get<0>(p), l);
588 l->append(", ");
589 LogParam(get<1>(p), l);
590 l->append(", ");
591 LogParam(get<2>(p), l);
592 l->append(", ");
593 LogParam(get<3>(p), l);
597 template <class A, class B, class C, class D, class E>
598 struct ParamTraits< Tuple<A, B, C, D, E> > {
599 typedef Tuple<A, B, C, D, E> param_type;
600 static void Write(Message* m, const param_type& p) {
601 WriteParam(m, get<0>(p));
602 WriteParam(m, get<1>(p));
603 WriteParam(m, get<2>(p));
604 WriteParam(m, get<3>(p));
605 WriteParam(m, get<4>(p));
607 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
608 return (ReadParam(m, iter, &get<0>(*r)) &&
609 ReadParam(m, iter, &get<1>(*r)) &&
610 ReadParam(m, iter, &get<2>(*r)) &&
611 ReadParam(m, iter, &get<3>(*r)) &&
612 ReadParam(m, iter, &get<4>(*r)));
614 static void Log(const param_type& p, std::string* l) {
615 LogParam(get<0>(p), l);
616 l->append(", ");
617 LogParam(get<1>(p), l);
618 l->append(", ");
619 LogParam(get<2>(p), l);
620 l->append(", ");
621 LogParam(get<3>(p), l);
622 l->append(", ");
623 LogParam(get<4>(p), l);
627 template<class P>
628 struct ParamTraits<ScopedVector<P> > {
629 typedef ScopedVector<P> param_type;
630 static void Write(Message* m, const param_type& p) {
631 WriteParam(m, static_cast<int>(p.size()));
632 for (size_t i = 0; i < p.size(); i++)
633 WriteParam(m, *p[i]);
635 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
636 int size = 0;
637 if (!iter->ReadLength(&size))
638 return false;
639 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
640 return false;
641 r->resize(size);
642 for (int i = 0; i < size; i++) {
643 (*r)[i] = new P();
644 if (!ReadParam(m, iter, (*r)[i]))
645 return false;
647 return true;
649 static void Log(const param_type& p, std::string* l) {
650 for (size_t i = 0; i < p.size(); ++i) {
651 if (i != 0)
652 l->append(" ");
653 LogParam(*p[i], l);
658 template <typename NormalMap,
659 int kArraySize,
660 typename EqualKey,
661 typename MapInit>
662 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
663 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
664 typedef typename param_type::key_type K;
665 typedef typename param_type::data_type V;
666 static void Write(Message* m, const param_type& p) {
667 WriteParam(m, static_cast<int>(p.size()));
668 typename param_type::const_iterator iter;
669 for (iter = p.begin(); iter != p.end(); ++iter) {
670 WriteParam(m, iter->first);
671 WriteParam(m, iter->second);
674 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
675 int size;
676 if (!iter->ReadLength(&size))
677 return false;
678 for (int i = 0; i < size; ++i) {
679 K key;
680 if (!ReadParam(m, iter, &key))
681 return false;
682 V& value = (*r)[key];
683 if (!ReadParam(m, iter, &value))
684 return false;
686 return true;
688 static void Log(const param_type& p, std::string* l) {
689 l->append("<base::SmallMap>");
693 template <class P>
694 struct ParamTraits<scoped_ptr<P> > {
695 typedef scoped_ptr<P> param_type;
696 static void Write(Message* m, const param_type& p) {
697 bool valid = !!p;
698 WriteParam(m, valid);
699 if (valid)
700 WriteParam(m, *p);
702 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
703 bool valid = false;
704 if (!ReadParam(m, iter, &valid))
705 return false;
707 if (!valid) {
708 r->reset();
709 return true;
712 param_type temp(new P());
713 if (!ReadParam(m, iter, temp.get()))
714 return false;
716 r->swap(temp);
717 return true;
719 static void Log(const param_type& p, std::string* l) {
720 if (p)
721 LogParam(*p, l);
722 else
723 l->append("NULL");
727 // IPC types ParamTraits -------------------------------------------------------
729 // A ChannelHandle is basically a platform-inspecific wrapper around the
730 // fact that IPC endpoints are handled specially on POSIX. See above comments
731 // on FileDescriptor for more background.
732 template<>
733 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
734 typedef ChannelHandle param_type;
735 static void Write(Message* m, const param_type& p);
736 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
737 static void Log(const param_type& p, std::string* l);
740 template <>
741 struct IPC_EXPORT ParamTraits<LogData> {
742 typedef LogData param_type;
743 static void Write(Message* m, const param_type& p);
744 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
745 static void Log(const param_type& p, std::string* l);
748 template <>
749 struct IPC_EXPORT ParamTraits<Message> {
750 static void Write(Message* m, const Message& p);
751 static bool Read(const Message* m, PickleIterator* iter, Message* r);
752 static void Log(const Message& p, std::string* l);
755 // Windows ParamTraits ---------------------------------------------------------
757 #if defined(OS_WIN)
758 template <>
759 struct IPC_EXPORT ParamTraits<HANDLE> {
760 typedef HANDLE param_type;
761 static void Write(Message* m, const param_type& p);
762 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
763 static void Log(const param_type& p, std::string* l);
766 template <>
767 struct IPC_EXPORT ParamTraits<LOGFONT> {
768 typedef LOGFONT param_type;
769 static void Write(Message* m, const param_type& p);
770 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
771 static void Log(const param_type& p, std::string* l);
774 template <>
775 struct IPC_EXPORT ParamTraits<MSG> {
776 typedef MSG param_type;
777 static void Write(Message* m, const param_type& p);
778 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
779 static void Log(const param_type& p, std::string* l);
781 #endif // defined(OS_WIN)
783 //-----------------------------------------------------------------------------
784 // Generic message subclasses
786 // Used for asynchronous messages.
787 template <class ParamType>
788 class MessageSchema {
789 public:
790 typedef ParamType Param;
791 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
793 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
794 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
797 // defined in ipc_logging.cc
798 IPC_EXPORT void GenerateLogData(const std::string& channel,
799 const Message& message,
800 LogData* data, bool get_params);
803 #if defined(IPC_MESSAGE_LOG_ENABLED)
804 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
805 const std::string& output_params = msg->output_params();
806 if (!l->empty() && !output_params.empty())
807 l->append(", ");
809 l->append(output_params);
812 template <class ReplyParamType>
813 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
814 const Message* msg) {
815 if (msg->received_time() != 0) {
816 std::string output_params;
817 LogParam(reply_params, &output_params);
818 msg->set_output_params(output_params);
822 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
823 if (msg->sent_time()) {
824 // Don't log the sync message after dispatch, as we don't have the
825 // output parameters at that point. Instead, save its data and log it
826 // with the outgoing reply message when it's sent.
827 LogData* data = new LogData;
828 GenerateLogData("", *msg, data, true);
829 msg->set_dont_log();
830 reply->set_sync_log_data(data);
833 #else
834 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
836 template <class ReplyParamType>
837 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
838 const Message* msg) {}
840 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
841 #endif
843 // This class assumes that its template argument is a RefTuple (a Tuple with
844 // reference elements). This would go into ipc_message_utils_impl.h, but it is
845 // also used by chrome_frame.
846 template <class RefTuple>
847 class ParamDeserializer : public MessageReplyDeserializer {
848 public:
849 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
851 bool SerializeOutputParameters(const IPC::Message& msg,
852 PickleIterator iter) override {
853 return ReadParam(&msg, &iter, &out_);
856 RefTuple out_;
859 // Used for synchronous messages.
860 template <class SendParamType, class ReplyParamType>
861 class SyncMessageSchema {
862 public:
863 typedef SendParamType SendParam;
864 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
865 typedef ReplyParamType ReplyParam;
867 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
868 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
869 static bool ReadReplyParam(
870 const Message* msg,
871 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
873 template<class T, class S, class Method>
874 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
875 const Message* msg, T* obj, S* sender,
876 Method func) {
877 Message* reply = SyncMessage::GenerateReply(msg);
878 if (ok) {
879 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
880 DispatchToMethod(obj, func, send_params, &reply_params);
881 WriteParam(reply, reply_params);
882 LogReplyParamsToMessage(reply_params, msg);
883 } else {
884 NOTREACHED() << "Error deserializing message " << msg->type();
885 reply->set_reply_error();
887 sender->Send(reply);
888 return ok;
891 template<class T, class Method>
892 static bool DispatchDelayReplyWithSendParams(bool ok,
893 const SendParam& send_params,
894 const Message* msg, T* obj,
895 Method func) {
896 Message* reply = SyncMessage::GenerateReply(msg);
897 if (ok) {
898 Tuple<Message&> t = MakeRefTuple(*reply);
899 ConnectMessageAndReply(msg, reply);
900 DispatchToMethod(obj, func, send_params, &t);
901 } else {
902 NOTREACHED() << "Error deserializing message " << msg->type();
903 reply->set_reply_error();
904 obj->Send(reply);
906 return ok;
909 template <typename... Ts>
910 static void WriteReplyParams(Message* reply, Ts... args) {
911 ReplyParam p(args...);
912 WriteParam(reply, p);
916 } // namespace IPC
918 #endif // IPC_IPC_MESSAGE_UTILS_H_