roll skia to 3543
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blobdc4a4be9f96645eeb86d2109c60350391d4cfe67
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_
7 #pragma once
9 #include <algorithm>
10 #include <map>
11 #include <set>
12 #include <string>
13 #include <vector>
15 #include "base/format_macros.h"
16 #include "base/string16.h"
17 #include "base/stringprintf.h"
18 #include "base/string_util.h"
19 #include "base/tuple.h"
20 #include "ipc/ipc_param_traits.h"
21 #include "ipc/ipc_sync_message.h"
23 #if defined(COMPILER_GCC)
24 // GCC "helpfully" tries to inline template methods in release mode. Except we
25 // want the majority of the template junk being expanded once in the
26 // implementation file (and only provide the definitions in
27 // ipc_message_utils_impl.h in those files) and exported, instead of expanded
28 // at every call site. Special note: GCC happily accepts the attribute before
29 // the method declaration, but only acts on it if it is after.
30 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
31 // Starting in gcc 4.5, the noinline no longer implies the concept covered by
32 // the introduced noclone attribute, which will create specialized versions of
33 // functions/methods when certain types are constant.
34 // www.gnu.org/software/gcc/gcc-4.5/changes.html
35 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
36 #else
37 #define IPC_MSG_NOINLINE __attribute__((noinline));
38 #endif
39 #elif defined(COMPILER_MSVC)
40 // MSVC++ doesn't do this.
41 #define IPC_MSG_NOINLINE
42 #else
43 #error "Please add the noinline property for your new compiler here."
44 #endif
46 // Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
47 // base. Messages have unique IDs across channels in order for the IPC logging
48 // code to figure out the message class from its ID.
49 enum IPCMessageStart {
50 AutomationMsgStart = 0,
51 ViewMsgStart,
52 PluginMsgStart,
53 ProfileImportMsgStart,
54 TestMsgStart,
55 DevToolsMsgStart,
56 WorkerMsgStart,
57 NaClMsgStart,
58 UtilityMsgStart,
59 GpuMsgStart,
60 ServiceMsgStart,
61 PpapiMsgStart,
62 FirefoxImporterUnittestMsgStart,
63 FileUtilitiesMsgStart,
64 MimeRegistryMsgStart,
65 DatabaseMsgStart,
66 DOMStorageMsgStart,
67 IndexedDBMsgStart,
68 PepperFileMsgStart,
69 SpeechRecognitionMsgStart,
70 PepperMsgStart,
71 AutofillMsgStart,
72 SafeBrowsingMsgStart,
73 P2PMsgStart,
74 SocketStreamMsgStart,
75 ResourceMsgStart,
76 FileSystemMsgStart,
77 ChildProcessMsgStart,
78 ClipboardMsgStart,
79 BlobMsgStart,
80 AppCacheMsgStart,
81 DeviceOrientationMsgStart,
82 DesktopNotificationMsgStart,
83 GeolocationMsgStart,
84 AudioMsgStart,
85 ChromeMsgStart,
86 DragMsgStart,
87 PrintMsgStart,
88 SpellCheckMsgStart,
89 ExtensionMsgStart,
90 VideoCaptureMsgStart,
91 QuotaMsgStart,
92 IconMsgStart,
93 TextInputClientMsgStart,
94 ChromeUtilityMsgStart,
95 MediaStreamMsgStart,
96 ChromeBenchmarkingMsgStart,
97 IntentsMsgStart,
98 JavaBridgeMsgStart,
99 GamepadMsgStart,
100 ShellMsgStart,
101 AccessibilityMsgStart,
102 PrerenderMsgStart,
103 ChromotingMsgStart,
104 LastIPCMsgStart // Must come last.
107 class FilePath;
108 class NullableString16;
110 namespace base {
111 class DictionaryValue;
112 class ListValue;
113 class Time;
114 class TimeDelta;
115 class TimeTicks;
116 struct FileDescriptor;
119 namespace IPC {
121 struct ChannelHandle;
123 //-----------------------------------------------------------------------------
124 // An iterator class for reading the fields contained within a Message.
126 class MessageIterator {
127 public:
128 explicit MessageIterator(const Message& m) : iter_(m) {
130 int NextInt() const {
131 int val = -1;
132 if (!iter_.ReadInt(&val))
133 NOTREACHED();
134 return val;
136 const std::string NextString() const {
137 std::string val;
138 if (!iter_.ReadString(&val))
139 NOTREACHED();
140 return val;
142 const std::wstring NextWString() const {
143 std::wstring val;
144 if (!iter_.ReadWString(&val))
145 NOTREACHED();
146 return val;
148 void NextData(const char** data, int* length) const {
149 if (!iter_.ReadData(data, length)) {
150 NOTREACHED();
153 private:
154 mutable PickleIterator iter_;
157 //-----------------------------------------------------------------------------
158 // A dummy struct to place first just to allow leading commas for all
159 // members in the macro-generated constructor initializer lists.
160 struct NoParams {
163 //-----------------------------------------------------------------------------
164 // ParamTraits specializations, etc.
166 template <class P>
167 static inline void WriteParam(Message* m, const P& p) {
168 typedef typename SimilarTypeTraits<P>::Type Type;
169 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
172 template <class P>
173 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m,
174 PickleIterator* iter,
175 P* p) {
176 typedef typename SimilarTypeTraits<P>::Type Type;
177 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
180 template <class P>
181 static inline void LogParam(const P& p, std::string* l) {
182 typedef typename SimilarTypeTraits<P>::Type Type;
183 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
186 template <>
187 struct ParamTraits<bool> {
188 typedef bool param_type;
189 static void Write(Message* m, const param_type& p) {
190 m->WriteBool(p);
192 static bool Read(const Message* m, PickleIterator* iter,
193 param_type* r) {
194 return m->ReadBool(iter, r);
196 static void Log(const param_type& p, std::string* l) {
197 l->append(p ? "true" : "false");
201 template <>
202 struct ParamTraits<int> {
203 typedef int param_type;
204 static void Write(Message* m, const param_type& p) {
205 m->WriteInt(p);
207 static bool Read(const Message* m, PickleIterator* iter,
208 param_type* r) {
209 return m->ReadInt(iter, r);
211 IPC_EXPORT static void Log(const param_type& p, std::string* l);
214 template <>
215 struct ParamTraits<unsigned int> {
216 typedef unsigned int param_type;
217 static void Write(Message* m, const param_type& p) {
218 m->WriteInt(p);
220 static bool Read(const Message* m, PickleIterator* iter,
221 param_type* r) {
222 return m->ReadInt(iter, reinterpret_cast<int*>(r));
224 IPC_EXPORT static void Log(const param_type& p, std::string* l);
227 template <>
228 struct ParamTraits<long> {
229 typedef long param_type;
230 static void Write(Message* m, const param_type& p) {
231 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
233 static bool Read(const Message* m, PickleIterator* iter,
234 param_type* r) {
235 return m->ReadLong(iter, r);
237 IPC_EXPORT static void Log(const param_type& p, std::string* l);
240 template <>
241 struct ParamTraits<unsigned long> {
242 typedef unsigned long param_type;
243 static void Write(Message* m, const param_type& p) {
244 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
246 static bool Read(const Message* m, PickleIterator* iter,
247 param_type* r) {
248 return m->ReadLong(iter, reinterpret_cast<long*>(r));
250 IPC_EXPORT static void Log(const param_type& p, std::string* l);
253 template <>
254 struct ParamTraits<long long> {
255 typedef long long param_type;
256 static void Write(Message* m, const param_type& p) {
257 m->WriteInt64(static_cast<int64>(p));
259 static bool Read(const Message* m, PickleIterator* iter,
260 param_type* r) {
261 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
263 IPC_EXPORT static void Log(const param_type& p, std::string* l);
266 template <>
267 struct ParamTraits<unsigned long long> {
268 typedef unsigned long long param_type;
269 static void Write(Message* m, const param_type& p) {
270 m->WriteInt64(p);
272 static bool Read(const Message* m, PickleIterator* iter,
273 param_type* r) {
274 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
276 IPC_EXPORT static void Log(const param_type& p, std::string* l);
279 template <>
280 struct IPC_EXPORT ParamTraits<unsigned short> {
281 typedef unsigned short param_type;
282 static void Write(Message* m, const param_type& p);
283 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
284 static void Log(const param_type& p, std::string* l);
287 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
288 // should be sure to check the sanity of these values after receiving them over
289 // IPC.
290 template <>
291 struct ParamTraits<float> {
292 typedef float param_type;
293 static void Write(Message* m, const param_type& p) {
294 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
296 static bool Read(const Message* m, PickleIterator* iter,
297 param_type* r) {
298 const char *data;
299 int data_size;
300 if (!m->ReadData(iter, &data, &data_size) ||
301 data_size != sizeof(param_type)) {
302 NOTREACHED();
303 return false;
305 memcpy(r, data, sizeof(param_type));
306 return true;
308 static void Log(const param_type& p, std::string* l) {
309 l->append(StringPrintf("%e", p));
313 template <>
314 struct ParamTraits<double> {
315 typedef double param_type;
316 static void Write(Message* m, const param_type& p) {
317 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
319 static bool Read(const Message* m, PickleIterator* iter,
320 param_type* r) {
321 const char *data;
322 int data_size;
323 if (!m->ReadData(iter, &data, &data_size) ||
324 data_size != sizeof(param_type)) {
325 NOTREACHED();
326 return false;
328 memcpy(r, data, sizeof(param_type));
329 return true;
331 static void Log(const param_type& p, std::string* l) {
332 l->append(StringPrintf("%e", p));
336 template <>
337 struct IPC_EXPORT ParamTraits<base::Time> {
338 typedef base::Time param_type;
339 static void Write(Message* m, const param_type& p);
340 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
341 static void Log(const param_type& p, std::string* l);
344 template <>
345 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
346 typedef base::TimeDelta param_type;
347 static void Write(Message* m, const param_type& p);
348 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
349 static void Log(const param_type& p, std::string* l);
352 template <>
353 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
354 typedef base::TimeTicks param_type;
355 static void Write(Message* m, const param_type& p);
356 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
357 static void Log(const param_type& p, std::string* l);
360 #if defined(OS_WIN)
361 template <>
362 struct ParamTraits<LOGFONT> {
363 typedef LOGFONT param_type;
364 static void Write(Message* m, const param_type& p) {
365 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
367 static bool Read(const Message* m, PickleIterator* iter,
368 param_type* r) {
369 const char *data;
370 int data_size = 0;
371 bool result = m->ReadData(iter, &data, &data_size);
372 if (result && data_size == sizeof(LOGFONT)) {
373 memcpy(r, data, sizeof(LOGFONT));
374 } else {
375 result = false;
376 NOTREACHED();
379 return result;
381 static void Log(const param_type& p, std::string* l) {
382 l->append(StringPrintf("<LOGFONT>"));
386 template <>
387 struct ParamTraits<MSG> {
388 typedef MSG param_type;
389 static void Write(Message* m, const param_type& p) {
390 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
392 static bool Read(const Message* m, PickleIterator* iter,
393 param_type* r) {
394 const char *data;
395 int data_size = 0;
396 bool result = m->ReadData(iter, &data, &data_size);
397 if (result && data_size == sizeof(MSG)) {
398 memcpy(r, data, sizeof(MSG));
399 } else {
400 result = false;
401 NOTREACHED();
404 return result;
406 static void Log(const param_type& p, std::string* l) {
407 l->append("<MSG>");
410 #endif // defined(OS_WIN)
412 template <>
413 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
414 typedef base::DictionaryValue param_type;
415 static void Write(Message* m, const param_type& p);
416 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
417 static void Log(const param_type& p, std::string* l);
420 template <>
421 struct IPC_EXPORT ParamTraits<base::ListValue> {
422 typedef base::ListValue param_type;
423 static void Write(Message* m, const param_type& p);
424 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
425 static void Log(const param_type& p, std::string* l);
428 template <>
429 struct ParamTraits<std::string> {
430 typedef std::string param_type;
431 static void Write(Message* m, const param_type& p) {
432 m->WriteString(p);
434 static bool Read(const Message* m, PickleIterator* iter,
435 param_type* r) {
436 return m->ReadString(iter, r);
438 static void Log(const param_type& p, std::string* l) {
439 l->append(p);
443 template<typename CharType>
444 static void LogBytes(const std::vector<CharType>& data, std::string* out) {
445 #if defined(OS_WIN)
446 // Windows has a GUI for logging, which can handle arbitrary binary data.
447 for (size_t i = 0; i < data.size(); ++i)
448 out->push_back(data[i]);
449 #else
450 // On POSIX, we log to stdout, which we assume can display ASCII.
451 static const size_t kMaxBytesToLog = 100;
452 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
453 if (isprint(data[i]))
454 out->push_back(data[i]);
455 else
456 out->append(StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
458 if (data.size() > kMaxBytesToLog) {
459 out->append(
460 StringPrintf(" and %u more bytes",
461 static_cast<unsigned>(data.size() - kMaxBytesToLog)));
463 #endif
466 template <>
467 struct ParamTraits<std::vector<unsigned char> > {
468 typedef std::vector<unsigned char> param_type;
469 static void Write(Message* m, const param_type& p) {
470 if (p.empty()) {
471 m->WriteData(NULL, 0);
472 } else {
473 m->WriteData(reinterpret_cast<const char*>(&p.front()),
474 static_cast<int>(p.size()));
477 static bool Read(const Message* m, PickleIterator* iter,
478 param_type* r) {
479 const char *data;
480 int data_size = 0;
481 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
482 return false;
483 r->resize(data_size);
484 if (data_size)
485 memcpy(&r->front(), data, data_size);
486 return true;
488 static void Log(const param_type& p, std::string* l) {
489 LogBytes(p, l);
493 template <>
494 struct ParamTraits<std::vector<char> > {
495 typedef std::vector<char> param_type;
496 static void Write(Message* m, const param_type& p) {
497 if (p.empty()) {
498 m->WriteData(NULL, 0);
499 } else {
500 m->WriteData(&p.front(), static_cast<int>(p.size()));
503 static bool Read(const Message* m, PickleIterator* iter,
504 param_type* r) {
505 const char *data;
506 int data_size = 0;
507 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
508 return false;
509 r->resize(data_size);
510 if (data_size)
511 memcpy(&r->front(), data, data_size);
512 return true;
514 static void Log(const param_type& p, std::string* l) {
515 LogBytes(p, l);
519 template <>
520 struct ParamTraits<std::vector<bool> > {
521 typedef std::vector<bool> param_type;
522 static void Write(Message* m, const param_type& p) {
523 WriteParam(m, static_cast<int>(p.size()));
524 for (size_t i = 0; i < p.size(); i++)
525 WriteParam(m, p[i]);
527 static bool Read(const Message* m, PickleIterator* iter,
528 param_type* r) {
529 int size;
530 // ReadLength() checks for < 0 itself.
531 if (!m->ReadLength(iter, &size))
532 return false;
533 r->resize(size);
534 for (int i = 0; i < size; i++) {
535 bool value;
536 if (!ReadParam(m, iter, &value))
537 return false;
538 (*r)[i] = value;
540 return true;
542 static void Log(const param_type& p, std::string* l) {
543 for (size_t i = 0; i < p.size(); ++i) {
544 if (i != 0)
545 l->append(" ");
546 LogParam((p[i]), l);
551 template <class P>
552 struct ParamTraits<std::vector<P> > {
553 typedef std::vector<P> param_type;
554 static void Write(Message* m, const param_type& p) {
555 WriteParam(m, static_cast<int>(p.size()));
556 for (size_t i = 0; i < p.size(); i++)
557 WriteParam(m, p[i]);
559 static bool Read(const Message* m, PickleIterator* iter,
560 param_type* r) {
561 int size;
562 // ReadLength() checks for < 0 itself.
563 if (!m->ReadLength(iter, &size))
564 return false;
565 // Resizing beforehand is not safe, see BUG 1006367 for details.
566 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
567 return false;
568 r->resize(size);
569 for (int i = 0; i < size; i++) {
570 if (!ReadParam(m, iter, &(*r)[i]))
571 return false;
573 return true;
575 static void Log(const param_type& p, std::string* l) {
576 for (size_t i = 0; i < p.size(); ++i) {
577 if (i != 0)
578 l->append(" ");
579 LogParam((p[i]), l);
584 template <class P>
585 struct ParamTraits<std::set<P> > {
586 typedef std::set<P> param_type;
587 static void Write(Message* m, const param_type& p) {
588 WriteParam(m, static_cast<int>(p.size()));
589 typename param_type::const_iterator iter;
590 for (iter = p.begin(); iter != p.end(); ++iter)
591 WriteParam(m, *iter);
593 static bool Read(const Message* m, PickleIterator* iter,
594 param_type* r) {
595 int size;
596 if (!m->ReadLength(iter, &size))
597 return false;
598 for (int i = 0; i < size; ++i) {
599 P item;
600 if (!ReadParam(m, iter, &item))
601 return false;
602 r->insert(item);
604 return true;
606 static void Log(const param_type& p, std::string* l) {
607 l->append("<std::set>");
612 template <class K, class V>
613 struct ParamTraits<std::map<K, V> > {
614 typedef std::map<K, V> param_type;
615 static void Write(Message* m, const param_type& p) {
616 WriteParam(m, static_cast<int>(p.size()));
617 typename param_type::const_iterator iter;
618 for (iter = p.begin(); iter != p.end(); ++iter) {
619 WriteParam(m, iter->first);
620 WriteParam(m, iter->second);
623 static bool Read(const Message* m, PickleIterator* iter,
624 param_type* r) {
625 int size;
626 if (!ReadParam(m, iter, &size) || size < 0)
627 return false;
628 for (int i = 0; i < size; ++i) {
629 K k;
630 if (!ReadParam(m, iter, &k))
631 return false;
632 V& value = (*r)[k];
633 if (!ReadParam(m, iter, &value))
634 return false;
636 return true;
638 static void Log(const param_type& p, std::string* l) {
639 l->append("<std::map>");
644 template <>
645 struct ParamTraits<std::wstring> {
646 typedef std::wstring param_type;
647 static void Write(Message* m, const param_type& p) {
648 m->WriteWString(p);
650 static bool Read(const Message* m, PickleIterator* iter,
651 param_type* r) {
652 return m->ReadWString(iter, r);
654 IPC_EXPORT static void Log(const param_type& p, std::string* l);
657 template <class A, class B>
658 struct ParamTraits<std::pair<A, B> > {
659 typedef std::pair<A, B> param_type;
660 static void Write(Message* m, const param_type& p) {
661 WriteParam(m, p.first);
662 WriteParam(m, p.second);
664 static bool Read(const Message* m, PickleIterator* iter,
665 param_type* r) {
666 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
668 static void Log(const param_type& p, std::string* l) {
669 l->append("(");
670 LogParam(p.first, l);
671 l->append(", ");
672 LogParam(p.second, l);
673 l->append(")");
677 template <>
678 struct IPC_EXPORT ParamTraits<NullableString16> {
679 typedef NullableString16 param_type;
680 static void Write(Message* m, const param_type& p);
681 static bool Read(const Message* m, PickleIterator* iter,
682 param_type* r);
683 static void Log(const param_type& p, std::string* l);
686 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
687 // need this trait.
688 #if !defined(WCHAR_T_IS_UTF16)
689 template <>
690 struct ParamTraits<string16> {
691 typedef string16 param_type;
692 static void Write(Message* m, const param_type& p) {
693 m->WriteString16(p);
695 static bool Read(const Message* m, PickleIterator* iter,
696 param_type* r) {
697 return m->ReadString16(iter, r);
699 IPC_EXPORT static void Log(const param_type& p, std::string* l);
701 #endif
703 // and, a few more useful types...
704 #if defined(OS_WIN)
705 template <>
706 struct ParamTraits<HANDLE> {
707 typedef HANDLE param_type;
708 static void Write(Message* m, const param_type& p) {
709 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
710 // bit systems.
711 m->WriteUInt32(reinterpret_cast<uint32>(p));
713 static bool Read(const Message* m, PickleIterator* iter,
714 param_type* r) {
715 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
716 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
718 static void Log(const param_type& p, std::string* l) {
719 l->append(StringPrintf("0x%X", p));
723 template <>
724 struct ParamTraits<HCURSOR> {
725 typedef HCURSOR param_type;
726 static void Write(Message* m, const param_type& p) {
727 m->WriteUInt32(reinterpret_cast<uint32>(p));
729 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
730 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
731 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
733 static void Log(const param_type& p, std::string* l) {
734 l->append(StringPrintf("0x%X", p));
738 template <>
739 struct ParamTraits<HACCEL> {
740 typedef HACCEL param_type;
741 static void Write(Message* m, const param_type& p) {
742 m->WriteUInt32(reinterpret_cast<uint32>(p));
744 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
745 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
746 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
750 template <>
751 struct ParamTraits<POINT> {
752 typedef POINT param_type;
753 static void Write(Message* m, const param_type& p) {
754 m->WriteInt(p.x);
755 m->WriteInt(p.y);
757 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
758 int x, y;
759 if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
760 return false;
761 r->x = x;
762 r->y = y;
763 return true;
765 static void Log(const param_type& p, std::string* l) {
766 l->append(StringPrintf("(%d, %d)", p.x, p.y));
769 #endif // defined(OS_WIN)
771 template <>
772 struct IPC_EXPORT ParamTraits<FilePath> {
773 typedef FilePath param_type;
774 static void Write(Message* m, const param_type& p);
775 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
776 static void Log(const param_type& p, std::string* l);
779 #if defined(OS_POSIX)
780 // FileDescriptors may be serialised over IPC channels on POSIX. On the
781 // receiving side, the FileDescriptor is a valid duplicate of the file
782 // descriptor which was transmitted: *it is not just a copy of the integer like
783 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
784 // this case, the receiving end will see a value of -1. *Zero is a valid file
785 // descriptor*.
787 // The received file descriptor will have the |auto_close| flag set to true. The
788 // code which handles the message is responsible for taking ownership of it.
789 // File descriptors are OS resources and must be closed when no longer needed.
791 // When sending a file descriptor, the file descriptor must be valid at the time
792 // of transmission. Since transmission is not synchronous, one should consider
793 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
794 // flag, which causes the file descriptor to be closed after writing.
795 template<>
796 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
797 typedef base::FileDescriptor param_type;
798 static void Write(Message* m, const param_type& p);
799 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
800 static void Log(const param_type& p, std::string* l);
802 #endif // defined(OS_POSIX)
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, PickleIterator* iter, param_type* r);
812 static void Log(const param_type& p, std::string* l);
815 #if defined(OS_WIN)
816 template <>
817 struct ParamTraits<XFORM> {
818 typedef XFORM param_type;
819 static void Write(Message* m, const param_type& p) {
820 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
822 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
823 const char *data;
824 int data_size = 0;
825 bool result = m->ReadData(iter, &data, &data_size);
826 if (result && data_size == sizeof(XFORM)) {
827 memcpy(r, data, sizeof(XFORM));
828 } else {
829 result = false;
830 NOTREACHED();
833 return result;
835 static void Log(const param_type& p, std::string* l) {
836 l->append("<XFORM>");
839 #endif // defined(OS_WIN)
841 struct IPC_EXPORT LogData {
842 LogData();
843 ~LogData();
845 std::string channel;
846 int32 routing_id;
847 uint32 type; // "User-defined" message type, from ipc_message.h.
848 std::string flags;
849 int64 sent; // Time that the message was sent (i.e. at Send()).
850 int64 receive; // Time before it was dispatched (i.e. before calling
851 // OnMessageReceived).
852 int64 dispatch; // Time after it was dispatched (i.e. after calling
853 // OnMessageReceived).
854 std::string message_name;
855 std::string params;
858 template <>
859 struct IPC_EXPORT ParamTraits<LogData> {
860 typedef LogData param_type;
861 static void Write(Message* m, const param_type& p);
862 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
863 static void Log(const param_type& p, std::string* l) {
864 // Doesn't make sense to implement this!
868 template <>
869 struct ParamTraits<Message> {
870 static void Write(Message* m, const Message& p) {
871 DCHECK(p.size() <= INT_MAX);
872 int message_size = static_cast<int>(p.size());
873 m->WriteInt(message_size);
874 m->WriteData(reinterpret_cast<const char*>(p.data()), message_size);
876 static bool Read(const Message* m, PickleIterator* iter, Message* r) {
877 int size;
878 if (!m->ReadInt(iter, &size))
879 return false;
880 const char* data;
881 if (!m->ReadData(iter, &data, &size))
882 return false;
883 *r = Message(data, size);
884 return true;
886 static void Log(const Message& p, std::string* l) {
887 l->append("<IPC::Message>");
891 template <>
892 struct ParamTraits<Tuple0> {
893 typedef Tuple0 param_type;
894 static void Write(Message* m, const param_type& p) {
896 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
897 return true;
899 static void Log(const param_type& p, std::string* l) {
903 template <class A>
904 struct ParamTraits< Tuple1<A> > {
905 typedef Tuple1<A> param_type;
906 static void Write(Message* m, const param_type& p) {
907 WriteParam(m, p.a);
909 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
910 return ReadParam(m, iter, &r->a);
912 static void Log(const param_type& p, std::string* l) {
913 LogParam(p.a, l);
917 template <class A, class B>
918 struct ParamTraits< Tuple2<A, B> > {
919 typedef Tuple2<A, B> param_type;
920 static void Write(Message* m, const param_type& p) {
921 WriteParam(m, p.a);
922 WriteParam(m, p.b);
924 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
925 return (ReadParam(m, iter, &r->a) &&
926 ReadParam(m, iter, &r->b));
928 static void Log(const param_type& p, std::string* l) {
929 LogParam(p.a, l);
930 l->append(", ");
931 LogParam(p.b, l);
935 template <class A, class B, class C>
936 struct ParamTraits< Tuple3<A, B, C> > {
937 typedef Tuple3<A, B, C> param_type;
938 static void Write(Message* m, const param_type& p) {
939 WriteParam(m, p.a);
940 WriteParam(m, p.b);
941 WriteParam(m, p.c);
943 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
944 return (ReadParam(m, iter, &r->a) &&
945 ReadParam(m, iter, &r->b) &&
946 ReadParam(m, iter, &r->c));
948 static void Log(const param_type& p, std::string* l) {
949 LogParam(p.a, l);
950 l->append(", ");
951 LogParam(p.b, l);
952 l->append(", ");
953 LogParam(p.c, l);
957 template <class A, class B, class C, class D>
958 struct ParamTraits< Tuple4<A, B, C, D> > {
959 typedef Tuple4<A, B, C, D> param_type;
960 static void Write(Message* m, const param_type& p) {
961 WriteParam(m, p.a);
962 WriteParam(m, p.b);
963 WriteParam(m, p.c);
964 WriteParam(m, p.d);
966 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
967 return (ReadParam(m, iter, &r->a) &&
968 ReadParam(m, iter, &r->b) &&
969 ReadParam(m, iter, &r->c) &&
970 ReadParam(m, iter, &r->d));
972 static void Log(const param_type& p, std::string* l) {
973 LogParam(p.a, l);
974 l->append(", ");
975 LogParam(p.b, l);
976 l->append(", ");
977 LogParam(p.c, l);
978 l->append(", ");
979 LogParam(p.d, l);
983 template <class A, class B, class C, class D, class E>
984 struct ParamTraits< Tuple5<A, B, C, D, E> > {
985 typedef Tuple5<A, B, C, D, E> param_type;
986 static void Write(Message* m, const param_type& p) {
987 WriteParam(m, p.a);
988 WriteParam(m, p.b);
989 WriteParam(m, p.c);
990 WriteParam(m, p.d);
991 WriteParam(m, p.e);
993 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
994 return (ReadParam(m, iter, &r->a) &&
995 ReadParam(m, iter, &r->b) &&
996 ReadParam(m, iter, &r->c) &&
997 ReadParam(m, iter, &r->d) &&
998 ReadParam(m, iter, &r->e));
1000 static void Log(const param_type& p, std::string* l) {
1001 LogParam(p.a, l);
1002 l->append(", ");
1003 LogParam(p.b, l);
1004 l->append(", ");
1005 LogParam(p.c, l);
1006 l->append(", ");
1007 LogParam(p.d, l);
1008 l->append(", ");
1009 LogParam(p.e, l);
1013 //-----------------------------------------------------------------------------
1014 // Generic message subclasses
1016 // Used for asynchronous messages.
1017 template <class ParamType>
1018 class MessageSchema {
1019 public:
1020 typedef ParamType Param;
1021 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
1023 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
1024 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
1027 // defined in ipc_logging.cc
1028 IPC_EXPORT void GenerateLogData(const std::string& channel,
1029 const Message& message,
1030 LogData* data, bool get_params);
1033 #if defined(IPC_MESSAGE_LOG_ENABLED)
1034 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
1035 const std::string& output_params = msg->output_params();
1036 if (!l->empty() && !output_params.empty())
1037 l->append(", ");
1039 l->append(output_params);
1042 template <class ReplyParamType>
1043 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1044 const Message* msg) {
1045 if (msg->received_time() != 0) {
1046 std::string output_params;
1047 LogParam(reply_params, &output_params);
1048 msg->set_output_params(output_params);
1052 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
1053 if (msg->sent_time()) {
1054 // Don't log the sync message after dispatch, as we don't have the
1055 // output parameters at that point. Instead, save its data and log it
1056 // with the outgoing reply message when it's sent.
1057 LogData* data = new LogData;
1058 GenerateLogData("", *msg, data, true);
1059 msg->set_dont_log();
1060 reply->set_sync_log_data(data);
1063 #else
1064 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
1066 template <class ReplyParamType>
1067 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1068 const Message* msg) {}
1070 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
1071 #endif
1073 // This class assumes that its template argument is a RefTuple (a Tuple with
1074 // reference elements). This would go into ipc_message_utils_impl.h, but it is
1075 // also used by chrome_frame.
1076 template <class RefTuple>
1077 class ParamDeserializer : public MessageReplyDeserializer {
1078 public:
1079 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
1081 bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
1082 return ReadParam(&msg, &iter, &out_);
1085 RefTuple out_;
1088 // Used for synchronous messages.
1089 template <class SendParamType, class ReplyParamType>
1090 class SyncMessageSchema {
1091 public:
1092 typedef SendParamType SendParam;
1093 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
1094 typedef ReplyParamType ReplyParam;
1096 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
1097 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
1098 static bool ReadReplyParam(
1099 const Message* msg,
1100 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
1102 template<class T, class S, class Method>
1103 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
1104 const Message* msg, T* obj, S* sender,
1105 Method func) {
1106 Message* reply = SyncMessage::GenerateReply(msg);
1107 if (ok) {
1108 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
1109 DispatchToMethod(obj, func, send_params, &reply_params);
1110 WriteParam(reply, reply_params);
1111 LogReplyParamsToMessage(reply_params, msg);
1112 } else {
1113 NOTREACHED() << "Error deserializing message " << msg->type();
1114 reply->set_reply_error();
1116 sender->Send(reply);
1117 return ok;
1120 template<class T, class Method>
1121 static bool DispatchDelayReplyWithSendParams(bool ok,
1122 const SendParam& send_params,
1123 const Message* msg, T* obj,
1124 Method func) {
1125 Message* reply = SyncMessage::GenerateReply(msg);
1126 if (ok) {
1127 Tuple1<Message&> t = MakeRefTuple(*reply);
1128 ConnectMessageAndReply(msg, reply);
1129 DispatchToMethod(obj, func, send_params, &t);
1130 } else {
1131 NOTREACHED() << "Error deserializing message " << msg->type();
1132 reply->set_reply_error();
1133 obj->Send(reply);
1135 return ok;
1138 template<typename TA>
1139 static void WriteReplyParams(Message* reply, TA a) {
1140 ReplyParam p(a);
1141 WriteParam(reply, p);
1144 template<typename TA, typename TB>
1145 static void WriteReplyParams(Message* reply, TA a, TB b) {
1146 ReplyParam p(a, b);
1147 WriteParam(reply, p);
1150 template<typename TA, typename TB, typename TC>
1151 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
1152 ReplyParam p(a, b, c);
1153 WriteParam(reply, p);
1156 template<typename TA, typename TB, typename TC, typename TD>
1157 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
1158 ReplyParam p(a, b, c, d);
1159 WriteParam(reply, p);
1162 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1163 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
1164 ReplyParam p(a, b, c, d, e);
1165 WriteParam(reply, p);
1169 //-----------------------------------------------------------------------------
1171 } // namespace IPC
1173 #endif // IPC_IPC_MESSAGE_UTILS_H_