Compute if a layer is clipped outside CalcDrawProps
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blobdbbd642ca53c809ad650f567bd33ebb52e95e672
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/brokerable_attachment.h"
24 #include "ipc/ipc_message_start.h"
25 #include "ipc/ipc_param_traits.h"
26 #include "ipc/ipc_sync_message.h"
28 #if defined(COMPILER_GCC)
29 // GCC "helpfully" tries to inline template methods in release mode. Except we
30 // want the majority of the template junk being expanded once in the
31 // implementation file (and only provide the definitions in
32 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
33 // at every call site. Special note: GCC happily accepts the attribute before
34 // the method declaration, but only acts on it if it is after.
35 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
36 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
37 // the introduced noclone attribute, which will create specialized versions of
38 // functions/methods when certain types are constant.
39 // www.gnu.org/software/gcc/gcc-4.5/changes.html
40 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
41 #else
42 #define IPC_MSG_NOINLINE __attribute__((noinline));
43 #endif
44 #elif defined(COMPILER_MSVC)
45 // MSVC++ doesn't do this.
46 #define IPC_MSG_NOINLINE
47 #else
48 #error "Please add the noinline property for your new compiler here."
49 #endif
51 namespace base {
52 class DictionaryValue;
53 class FilePath;
54 class ListValue;
55 class NullableString16;
56 class Time;
57 class TimeDelta;
58 class TimeTicks;
59 class TraceTicks;
60 struct FileDescriptor;
62 #if defined(OS_MACOSX) && !defined(OS_IOS)
63 class SharedMemoryHandle;
64 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
67 namespace IPC {
69 struct ChannelHandle;
71 // -----------------------------------------------------------------------------
72 // How we send IPC message logs across channels.
73 struct IPC_EXPORT LogData {
74 LogData();
75 ~LogData();
77 std::string channel;
78 int32 routing_id;
79 uint32 type; // "User-defined" message type, from ipc_message.h.
80 std::string flags;
81 int64 sent; // Time that the message was sent (i.e. at Send()).
82 int64 receive; // Time before it was dispatched (i.e. before calling
83 // OnMessageReceived).
84 int64 dispatch; // Time after it was dispatched (i.e. after calling
85 // OnMessageReceived).
86 std::string message_name;
87 std::string params;
90 //-----------------------------------------------------------------------------
92 // A dummy struct to place first just to allow leading commas for all
93 // members in the macro-generated constructor initializer lists.
94 struct NoParams {
97 template <class P>
98 static inline void WriteParam(Message* m, const P& p) {
99 typedef typename SimilarTypeTraits<P>::Type Type;
100 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
103 template <class P>
104 static inline bool WARN_UNUSED_RESULT
105 ReadParam(const Message* m, base::PickleIterator* iter, P* p) {
106 typedef typename SimilarTypeTraits<P>::Type Type;
107 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
110 template <class P>
111 static inline void LogParam(const P& p, std::string* l) {
112 typedef typename SimilarTypeTraits<P>::Type Type;
113 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
116 // Primitive ParamTraits -------------------------------------------------------
118 template <>
119 struct ParamTraits<bool> {
120 typedef bool param_type;
121 static void Write(Message* m, const param_type& p) {
122 m->WriteBool(p);
124 static bool Read(const Message* m,
125 base::PickleIterator* iter,
126 param_type* r) {
127 return iter->ReadBool(r);
129 IPC_EXPORT static void Log(const param_type& p, std::string* l);
132 template <>
133 struct IPC_EXPORT ParamTraits<unsigned char> {
134 typedef unsigned char param_type;
135 static void Write(Message* m, const param_type& p);
136 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
137 static void Log(const param_type& p, std::string* l);
140 template <>
141 struct IPC_EXPORT ParamTraits<unsigned short> {
142 typedef unsigned short param_type;
143 static void Write(Message* m, const param_type& p);
144 static bool Read(const Message* m,
145 base::PickleIterator* iter,
146 param_type* r);
147 static void Log(const param_type& p, std::string* l);
150 template <>
151 struct ParamTraits<int> {
152 typedef int param_type;
153 static void Write(Message* m, const param_type& p) {
154 m->WriteInt(p);
156 static bool Read(const Message* m,
157 base::PickleIterator* iter,
158 param_type* r) {
159 return iter->ReadInt(r);
161 IPC_EXPORT static void Log(const param_type& p, std::string* l);
164 template <>
165 struct ParamTraits<unsigned int> {
166 typedef unsigned int param_type;
167 static void Write(Message* m, const param_type& p) {
168 m->WriteInt(p);
170 static bool Read(const Message* m,
171 base::PickleIterator* iter,
172 param_type* r) {
173 return iter->ReadInt(reinterpret_cast<int*>(r));
175 IPC_EXPORT static void Log(const param_type& p, std::string* l);
178 template <>
179 struct ParamTraits<long> {
180 typedef long param_type;
181 static void Write(Message* m, const param_type& p) {
182 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
184 static bool Read(const Message* m,
185 base::PickleIterator* iter,
186 param_type* r) {
187 return iter->ReadLong(r);
189 IPC_EXPORT static void Log(const param_type& p, std::string* l);
192 template <>
193 struct ParamTraits<unsigned long> {
194 typedef unsigned long param_type;
195 static void Write(Message* m, const param_type& p) {
196 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
198 static bool Read(const Message* m,
199 base::PickleIterator* iter,
200 param_type* r) {
201 return iter->ReadLong(reinterpret_cast<long*>(r));
203 IPC_EXPORT static void Log(const param_type& p, std::string* l);
206 template <>
207 struct ParamTraits<long long> {
208 typedef long long param_type;
209 static void Write(Message* m, const param_type& p) {
210 m->WriteInt64(static_cast<int64>(p));
212 static bool Read(const Message* m,
213 base::PickleIterator* iter,
214 param_type* r) {
215 return iter->ReadInt64(reinterpret_cast<int64*>(r));
217 IPC_EXPORT static void Log(const param_type& p, std::string* l);
220 template <>
221 struct ParamTraits<unsigned long long> {
222 typedef unsigned long long param_type;
223 static void Write(Message* m, const param_type& p) {
224 m->WriteInt64(p);
226 static bool Read(const Message* m,
227 base::PickleIterator* iter,
228 param_type* r) {
229 return iter->ReadInt64(reinterpret_cast<int64*>(r));
231 IPC_EXPORT static void Log(const param_type& p, std::string* l);
234 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
235 // should be sure to check the sanity of these values after receiving them over
236 // IPC.
237 template <>
238 struct IPC_EXPORT ParamTraits<float> {
239 typedef float param_type;
240 static void Write(Message* m, const param_type& p) {
241 m->WriteFloat(p);
243 static bool Read(const Message* m,
244 base::PickleIterator* iter,
245 param_type* r) {
246 return iter->ReadFloat(r);
248 static void Log(const param_type& p, std::string* l);
251 template <>
252 struct IPC_EXPORT ParamTraits<double> {
253 typedef double param_type;
254 static void Write(Message* m, const param_type& p);
255 static bool Read(const Message* m,
256 base::PickleIterator* iter,
257 param_type* r);
258 static void Log(const param_type& p, std::string* l);
261 // STL ParamTraits -------------------------------------------------------------
263 template <>
264 struct ParamTraits<std::string> {
265 typedef std::string param_type;
266 static void Write(Message* m, const param_type& p) {
267 m->WriteString(p);
269 static bool Read(const Message* m,
270 base::PickleIterator* iter,
271 param_type* r) {
272 return iter->ReadString(r);
274 IPC_EXPORT static void Log(const param_type& p, std::string* l);
277 template <>
278 struct ParamTraits<base::string16> {
279 typedef base::string16 param_type;
280 static void Write(Message* m, const param_type& p) {
281 m->WriteString16(p);
283 static bool Read(const Message* m,
284 base::PickleIterator* iter,
285 param_type* r) {
286 return iter->ReadString16(r);
288 IPC_EXPORT static void Log(const param_type& p, std::string* l);
291 template <>
292 struct IPC_EXPORT ParamTraits<std::vector<char> > {
293 typedef std::vector<char> param_type;
294 static void Write(Message* m, const param_type& p);
295 static bool Read(const Message*,
296 base::PickleIterator* iter,
297 param_type* r);
298 static void Log(const param_type& p, std::string* l);
301 template <>
302 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > {
303 typedef std::vector<unsigned char> param_type;
304 static void Write(Message* m, const param_type& p);
305 static bool Read(const Message* m,
306 base::PickleIterator* iter,
307 param_type* r);
308 static void Log(const param_type& p, std::string* l);
311 template <>
312 struct IPC_EXPORT ParamTraits<std::vector<bool> > {
313 typedef std::vector<bool> param_type;
314 static void Write(Message* m, const param_type& p);
315 static bool Read(const Message* m,
316 base::PickleIterator* iter,
317 param_type* r);
318 static void Log(const param_type& p, std::string* l);
321 template <class P>
322 struct ParamTraits<std::vector<P> > {
323 typedef std::vector<P> param_type;
324 static void Write(Message* m, const param_type& p) {
325 WriteParam(m, static_cast<int>(p.size()));
326 for (size_t i = 0; i < p.size(); i++)
327 WriteParam(m, p[i]);
329 static bool Read(const Message* m,
330 base::PickleIterator* iter,
331 param_type* r) {
332 int size;
333 // ReadLength() checks for < 0 itself.
334 if (!iter->ReadLength(&size))
335 return false;
336 // Resizing beforehand is not safe, see BUG 1006367 for details.
337 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
338 return false;
339 r->resize(size);
340 for (int i = 0; i < size; i++) {
341 if (!ReadParam(m, iter, &(*r)[i]))
342 return false;
344 return true;
346 static void Log(const param_type& p, std::string* l) {
347 for (size_t i = 0; i < p.size(); ++i) {
348 if (i != 0)
349 l->append(" ");
350 LogParam((p[i]), l);
355 template <class P>
356 struct ParamTraits<std::set<P> > {
357 typedef std::set<P> param_type;
358 static void Write(Message* m, const param_type& p) {
359 WriteParam(m, static_cast<int>(p.size()));
360 typename param_type::const_iterator iter;
361 for (iter = p.begin(); iter != p.end(); ++iter)
362 WriteParam(m, *iter);
364 static bool Read(const Message* m,
365 base::PickleIterator* iter,
366 param_type* r) {
367 int size;
368 if (!iter->ReadLength(&size))
369 return false;
370 for (int i = 0; i < size; ++i) {
371 P item;
372 if (!ReadParam(m, iter, &item))
373 return false;
374 r->insert(item);
376 return true;
378 static void Log(const param_type& p, std::string* l) {
379 l->append("<std::set>");
383 template <class K, class V, class C, class A>
384 struct ParamTraits<std::map<K, V, C, A> > {
385 typedef std::map<K, V, C, A> param_type;
386 static void Write(Message* m, const param_type& p) {
387 WriteParam(m, static_cast<int>(p.size()));
388 typename param_type::const_iterator iter;
389 for (iter = p.begin(); iter != p.end(); ++iter) {
390 WriteParam(m, iter->first);
391 WriteParam(m, iter->second);
394 static bool Read(const Message* m,
395 base::PickleIterator* iter,
396 param_type* r) {
397 int size;
398 if (!ReadParam(m, iter, &size) || size < 0)
399 return false;
400 for (int i = 0; i < size; ++i) {
401 K k;
402 if (!ReadParam(m, iter, &k))
403 return false;
404 V& value = (*r)[k];
405 if (!ReadParam(m, iter, &value))
406 return false;
408 return true;
410 static void Log(const param_type& p, std::string* l) {
411 l->append("<std::map>");
415 template <class A, class B>
416 struct ParamTraits<std::pair<A, B> > {
417 typedef std::pair<A, B> param_type;
418 static void Write(Message* m, const param_type& p) {
419 WriteParam(m, p.first);
420 WriteParam(m, p.second);
422 static bool Read(const Message* m,
423 base::PickleIterator* iter,
424 param_type* r) {
425 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
427 static void Log(const param_type& p, std::string* l) {
428 l->append("(");
429 LogParam(p.first, l);
430 l->append(", ");
431 LogParam(p.second, l);
432 l->append(")");
436 // IPC ParamTraits -------------------------------------------------------------
437 template <>
438 struct IPC_EXPORT ParamTraits<BrokerableAttachment::AttachmentId> {
439 typedef BrokerableAttachment::AttachmentId param_type;
440 static void Write(Message* m, const param_type& p);
441 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
442 static void Log(const param_type& p, std::string* l);
445 // Base ParamTraits ------------------------------------------------------------
447 template <>
448 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
449 typedef base::DictionaryValue param_type;
450 static void Write(Message* m, const param_type& p);
451 static bool Read(const Message* m,
452 base::PickleIterator* iter,
453 param_type* r);
454 static void Log(const param_type& p, std::string* l);
457 #if defined(OS_POSIX)
458 // FileDescriptors may be serialised over IPC channels on POSIX. On the
459 // receiving side, the FileDescriptor is a valid duplicate of the file
460 // descriptor which was transmitted: *it is not just a copy of the integer like
461 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
462 // this case, the receiving end will see a value of -1. *Zero is a valid file
463 // descriptor*.
465 // The received file descriptor will have the |auto_close| flag set to true. The
466 // code which handles the message is responsible for taking ownership of it.
467 // File descriptors are OS resources and must be closed when no longer needed.
469 // When sending a file descriptor, the file descriptor must be valid at the time
470 // of transmission. Since transmission is not synchronous, one should consider
471 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
472 // flag, which causes the file descriptor to be closed after writing.
473 template<>
474 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
475 typedef base::FileDescriptor param_type;
476 static void Write(Message* m, const param_type& p);
477 static bool Read(const Message* m,
478 base::PickleIterator* iter,
479 param_type* r);
480 static void Log(const param_type& p, std::string* l);
482 #endif // defined(OS_POSIX)
484 #if defined(OS_MACOSX) && !defined(OS_IOS)
485 template <>
486 struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> {
487 typedef base::SharedMemoryHandle param_type;
488 static void Write(Message* m, const param_type& p);
489 static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
490 static void Log(const param_type& p, std::string* l);
492 #endif
494 template <>
495 struct IPC_EXPORT ParamTraits<base::FilePath> {
496 typedef base::FilePath param_type;
497 static void Write(Message* m, const param_type& p);
498 static bool Read(const Message* m,
499 base::PickleIterator* iter,
500 param_type* r);
501 static void Log(const param_type& p, std::string* l);
504 template <>
505 struct IPC_EXPORT ParamTraits<base::ListValue> {
506 typedef base::ListValue param_type;
507 static void Write(Message* m, const param_type& p);
508 static bool Read(const Message* m,
509 base::PickleIterator* iter,
510 param_type* r);
511 static void Log(const param_type& p, std::string* l);
514 template <>
515 struct IPC_EXPORT ParamTraits<base::NullableString16> {
516 typedef base::NullableString16 param_type;
517 static void Write(Message* m, const param_type& p);
518 static bool Read(const Message* m,
519 base::PickleIterator* iter,
520 param_type* r);
521 static void Log(const param_type& p, std::string* l);
524 template <>
525 struct IPC_EXPORT ParamTraits<base::File::Info> {
526 typedef base::File::Info param_type;
527 static void Write(Message* m, const param_type& p);
528 static bool Read(const Message* m,
529 base::PickleIterator* iter,
530 param_type* r);
531 static void Log(const param_type& p, std::string* l);
534 template <>
535 struct SimilarTypeTraits<base::File::Error> {
536 typedef int Type;
539 #if defined(OS_WIN)
540 template <>
541 struct SimilarTypeTraits<HWND> {
542 typedef HANDLE Type;
544 #endif // defined(OS_WIN)
546 template <>
547 struct IPC_EXPORT ParamTraits<base::Time> {
548 typedef base::Time param_type;
549 static void Write(Message* m, const param_type& p);
550 static bool Read(const Message* m,
551 base::PickleIterator* iter,
552 param_type* r);
553 static void Log(const param_type& p, std::string* l);
556 template <>
557 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
558 typedef base::TimeDelta param_type;
559 static void Write(Message* m, const param_type& p);
560 static bool Read(const Message* m,
561 base::PickleIterator* iter,
562 param_type* r);
563 static void Log(const param_type& p, std::string* l);
566 template <>
567 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
568 typedef base::TimeTicks param_type;
569 static void Write(Message* m, const param_type& p);
570 static bool Read(const Message* m,
571 base::PickleIterator* iter,
572 param_type* r);
573 static void Log(const param_type& p, std::string* l);
576 template <>
577 struct IPC_EXPORT ParamTraits<base::TraceTicks> {
578 typedef base::TraceTicks param_type;
579 static void Write(Message* m, const param_type& p);
580 static bool Read(const Message* m,
581 base::PickleIterator* iter,
582 param_type* r);
583 static void Log(const param_type& p, std::string* l);
586 template <>
587 struct ParamTraits<base::Tuple<>> {
588 typedef base::Tuple<> param_type;
589 static void Write(Message* m, const param_type& p) {
591 static bool Read(const Message* m,
592 base::PickleIterator* iter,
593 param_type* r) {
594 return true;
596 static void Log(const param_type& p, std::string* l) {
600 template <class A>
601 struct ParamTraits<base::Tuple<A>> {
602 typedef base::Tuple<A> param_type;
603 static void Write(Message* m, const param_type& p) {
604 WriteParam(m, base::get<0>(p));
606 static bool Read(const Message* m,
607 base::PickleIterator* iter,
608 param_type* r) {
609 return ReadParam(m, iter, &base::get<0>(*r));
611 static void Log(const param_type& p, std::string* l) {
612 LogParam(base::get<0>(p), l);
616 template <class A, class B>
617 struct ParamTraits<base::Tuple<A, B>> {
618 typedef base::Tuple<A, B> param_type;
619 static void Write(Message* m, const param_type& p) {
620 WriteParam(m, base::get<0>(p));
621 WriteParam(m, base::get<1>(p));
623 static bool Read(const Message* m,
624 base::PickleIterator* iter,
625 param_type* r) {
626 return (ReadParam(m, iter, &base::get<0>(*r)) &&
627 ReadParam(m, iter, &base::get<1>(*r)));
629 static void Log(const param_type& p, std::string* l) {
630 LogParam(base::get<0>(p), l);
631 l->append(", ");
632 LogParam(base::get<1>(p), l);
636 template <class A, class B, class C>
637 struct ParamTraits<base::Tuple<A, B, C>> {
638 typedef base::Tuple<A, B, C> 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));
644 static bool Read(const Message* m,
645 base::PickleIterator* iter,
646 param_type* r) {
647 return (ReadParam(m, iter, &base::get<0>(*r)) &&
648 ReadParam(m, iter, &base::get<1>(*r)) &&
649 ReadParam(m, iter, &base::get<2>(*r)));
651 static void Log(const param_type& p, std::string* l) {
652 LogParam(base::get<0>(p), l);
653 l->append(", ");
654 LogParam(base::get<1>(p), l);
655 l->append(", ");
656 LogParam(base::get<2>(p), l);
660 template <class A, class B, class C, class D>
661 struct ParamTraits<base::Tuple<A, B, C, D>> {
662 typedef base::Tuple<A, B, C, D> param_type;
663 static void Write(Message* m, const param_type& p) {
664 WriteParam(m, base::get<0>(p));
665 WriteParam(m, base::get<1>(p));
666 WriteParam(m, base::get<2>(p));
667 WriteParam(m, base::get<3>(p));
669 static bool Read(const Message* m,
670 base::PickleIterator* iter,
671 param_type* r) {
672 return (ReadParam(m, iter, &base::get<0>(*r)) &&
673 ReadParam(m, iter, &base::get<1>(*r)) &&
674 ReadParam(m, iter, &base::get<2>(*r)) &&
675 ReadParam(m, iter, &base::get<3>(*r)));
677 static void Log(const param_type& p, std::string* l) {
678 LogParam(base::get<0>(p), l);
679 l->append(", ");
680 LogParam(base::get<1>(p), l);
681 l->append(", ");
682 LogParam(base::get<2>(p), l);
683 l->append(", ");
684 LogParam(base::get<3>(p), l);
688 template <class A, class B, class C, class D, class E>
689 struct ParamTraits<base::Tuple<A, B, C, D, E>> {
690 typedef base::Tuple<A, B, C, D, E> param_type;
691 static void Write(Message* m, const param_type& p) {
692 WriteParam(m, base::get<0>(p));
693 WriteParam(m, base::get<1>(p));
694 WriteParam(m, base::get<2>(p));
695 WriteParam(m, base::get<3>(p));
696 WriteParam(m, base::get<4>(p));
698 static bool Read(const Message* m,
699 base::PickleIterator* iter,
700 param_type* r) {
701 return (ReadParam(m, iter, &base::get<0>(*r)) &&
702 ReadParam(m, iter, &base::get<1>(*r)) &&
703 ReadParam(m, iter, &base::get<2>(*r)) &&
704 ReadParam(m, iter, &base::get<3>(*r)) &&
705 ReadParam(m, iter, &base::get<4>(*r)));
707 static void Log(const param_type& p, std::string* l) {
708 LogParam(base::get<0>(p), l);
709 l->append(", ");
710 LogParam(base::get<1>(p), l);
711 l->append(", ");
712 LogParam(base::get<2>(p), l);
713 l->append(", ");
714 LogParam(base::get<3>(p), l);
715 l->append(", ");
716 LogParam(base::get<4>(p), l);
720 template<class P>
721 struct ParamTraits<ScopedVector<P> > {
722 typedef ScopedVector<P> param_type;
723 static void Write(Message* m, const param_type& p) {
724 WriteParam(m, static_cast<int>(p.size()));
725 for (size_t i = 0; i < p.size(); i++)
726 WriteParam(m, *p[i]);
728 static bool Read(const Message* m,
729 base::PickleIterator* iter,
730 param_type* r) {
731 int size = 0;
732 if (!iter->ReadLength(&size))
733 return false;
734 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size))
735 return false;
736 r->resize(size);
737 for (int i = 0; i < size; i++) {
738 (*r)[i] = new P();
739 if (!ReadParam(m, iter, (*r)[i]))
740 return false;
742 return true;
744 static void Log(const param_type& p, std::string* l) {
745 for (size_t i = 0; i < p.size(); ++i) {
746 if (i != 0)
747 l->append(" ");
748 LogParam(*p[i], l);
753 template <typename NormalMap,
754 int kArraySize,
755 typename EqualKey,
756 typename MapInit>
757 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > {
758 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type;
759 typedef typename param_type::key_type K;
760 typedef typename param_type::data_type V;
761 static void Write(Message* m, const param_type& p) {
762 WriteParam(m, static_cast<int>(p.size()));
763 typename param_type::const_iterator iter;
764 for (iter = p.begin(); iter != p.end(); ++iter) {
765 WriteParam(m, iter->first);
766 WriteParam(m, iter->second);
769 static bool Read(const Message* m,
770 base::PickleIterator* iter,
771 param_type* r) {
772 int size;
773 if (!iter->ReadLength(&size))
774 return false;
775 for (int i = 0; i < size; ++i) {
776 K key;
777 if (!ReadParam(m, iter, &key))
778 return false;
779 V& value = (*r)[key];
780 if (!ReadParam(m, iter, &value))
781 return false;
783 return true;
785 static void Log(const param_type& p, std::string* l) {
786 l->append("<base::SmallMap>");
790 template <class P>
791 struct ParamTraits<scoped_ptr<P> > {
792 typedef scoped_ptr<P> param_type;
793 static void Write(Message* m, const param_type& p) {
794 bool valid = !!p;
795 WriteParam(m, valid);
796 if (valid)
797 WriteParam(m, *p);
799 static bool Read(const Message* m,
800 base::PickleIterator* iter,
801 param_type* r) {
802 bool valid = false;
803 if (!ReadParam(m, iter, &valid))
804 return false;
806 if (!valid) {
807 r->reset();
808 return true;
811 param_type temp(new P());
812 if (!ReadParam(m, iter, temp.get()))
813 return false;
815 r->swap(temp);
816 return true;
818 static void Log(const param_type& p, std::string* l) {
819 if (p)
820 LogParam(*p, l);
821 else
822 l->append("NULL");
826 // IPC types ParamTraits -------------------------------------------------------
828 // A ChannelHandle is basically a platform-inspecific wrapper around the
829 // fact that IPC endpoints are handled specially on POSIX. See above comments
830 // on FileDescriptor for more background.
831 template<>
832 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
833 typedef ChannelHandle param_type;
834 static void Write(Message* m, const param_type& p);
835 static bool Read(const Message* m,
836 base::PickleIterator* iter,
837 param_type* r);
838 static void Log(const param_type& p, std::string* l);
841 template <>
842 struct IPC_EXPORT ParamTraits<LogData> {
843 typedef LogData param_type;
844 static void Write(Message* m, const param_type& p);
845 static bool Read(const Message* m,
846 base::PickleIterator* iter,
847 param_type* r);
848 static void Log(const param_type& p, std::string* l);
851 template <>
852 struct IPC_EXPORT ParamTraits<Message> {
853 static void Write(Message* m, const Message& p);
854 static bool Read(const Message* m,
855 base::PickleIterator* iter,
856 Message* r);
857 static void Log(const Message& p, std::string* l);
860 // Windows ParamTraits ---------------------------------------------------------
862 #if defined(OS_WIN)
863 template <>
864 struct IPC_EXPORT ParamTraits<HANDLE> {
865 typedef HANDLE param_type;
866 static void Write(Message* m, const param_type& p);
867 static bool Read(const Message* m,
868 base::PickleIterator* iter,
869 param_type* r);
870 static void Log(const param_type& p, std::string* l);
873 template <>
874 struct IPC_EXPORT ParamTraits<LOGFONT> {
875 typedef LOGFONT param_type;
876 static void Write(Message* m, const param_type& p);
877 static bool Read(const Message* m,
878 base::PickleIterator* iter,
879 param_type* r);
880 static void Log(const param_type& p, std::string* l);
883 template <>
884 struct IPC_EXPORT ParamTraits<MSG> {
885 typedef MSG param_type;
886 static void Write(Message* m, const param_type& p);
887 static bool Read(const Message* m,
888 base::PickleIterator* iter,
889 param_type* r);
890 static void Log(const param_type& p, std::string* l);
892 #endif // defined(OS_WIN)
894 //-----------------------------------------------------------------------------
895 // Generic message subclasses
897 // Used for asynchronous messages.
898 template <class ParamType>
899 class MessageSchema {
900 public:
901 typedef ParamType Param;
902 typedef typename base::TupleTypes<ParamType>::ParamTuple RefParam;
904 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
905 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
908 // defined in ipc_logging.cc
909 IPC_EXPORT void GenerateLogData(const std::string& channel,
910 const Message& message,
911 LogData* data, bool get_params);
914 #if defined(IPC_MESSAGE_LOG_ENABLED)
915 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
916 const std::string& output_params = msg->output_params();
917 if (!l->empty() && !output_params.empty())
918 l->append(", ");
920 l->append(output_params);
923 template <class ReplyParamType>
924 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
925 const Message* msg) {
926 if (msg->received_time() != 0) {
927 std::string output_params;
928 LogParam(reply_params, &output_params);
929 msg->set_output_params(output_params);
933 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
934 if (msg->sent_time()) {
935 // Don't log the sync message after dispatch, as we don't have the
936 // output parameters at that point. Instead, save its data and log it
937 // with the outgoing reply message when it's sent.
938 LogData* data = new LogData;
939 GenerateLogData("", *msg, data, true);
940 msg->set_dont_log();
941 reply->set_sync_log_data(data);
944 #else
945 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
947 template <class ReplyParamType>
948 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
949 const Message* msg) {}
951 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
952 #endif
954 // This class assumes that its template argument is a RefTuple (a Tuple with
955 // reference elements). This would go into ipc_message_utils_impl.h, but it is
956 // also used by chrome_frame.
957 template <class RefTuple>
958 class ParamDeserializer : public MessageReplyDeserializer {
959 public:
960 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
962 bool SerializeOutputParameters(const IPC::Message& msg,
963 base::PickleIterator iter) override {
964 return ReadParam(&msg, &iter, &out_);
967 RefTuple out_;
970 // Used for synchronous messages.
971 template <class SendParamType, class ReplyParamType>
972 class SyncMessageSchema {
973 public:
974 typedef SendParamType SendParam;
975 typedef typename base::TupleTypes<SendParam>::ParamTuple RefSendParam;
976 typedef ReplyParamType ReplyParam;
978 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
979 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
980 static bool ReadReplyParam(
981 const Message* msg,
982 typename base::TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
984 template<class T, class S, class Method>
985 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
986 const Message* msg, T* obj, S* sender,
987 Method func) {
988 Message* reply = SyncMessage::GenerateReply(msg);
989 if (ok) {
990 typename base::TupleTypes<ReplyParam>::ValueTuple reply_params;
991 DispatchToMethod(obj, func, send_params, &reply_params);
992 WriteParam(reply, reply_params);
993 LogReplyParamsToMessage(reply_params, msg);
994 } else {
995 NOTREACHED() << "Error deserializing message " << msg->type();
996 reply->set_reply_error();
998 sender->Send(reply);
999 return ok;
1002 template<class T, class Method>
1003 static bool DispatchDelayReplyWithSendParams(bool ok,
1004 const SendParam& send_params,
1005 const Message* msg, T* obj,
1006 Method func) {
1007 Message* reply = SyncMessage::GenerateReply(msg);
1008 if (ok) {
1009 base::Tuple<Message&> t = base::MakeRefTuple(*reply);
1010 ConnectMessageAndReply(msg, reply);
1011 DispatchToMethod(obj, func, send_params, &t);
1012 } else {
1013 NOTREACHED() << "Error deserializing message " << msg->type();
1014 reply->set_reply_error();
1015 obj->Send(reply);
1017 return ok;
1020 template <typename... Ts>
1021 static void WriteReplyParams(Message* reply, Ts... args) {
1022 ReplyParam p(args...);
1023 WriteParam(reply, p);
1027 } // namespace IPC
1029 #endif // IPC_IPC_MESSAGE_UTILS_H_