ash: Extend launcher first button to include leading inset.
[chromium-blink-merge.git] / ipc / ipc_message_utils.h
blob9e259f1150f8ee35e9dd8a4aafec154d8ddfb82c
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 BrowserPluginMsgStart,
105 LastIPCMsgStart // Must come last.
108 class FilePath;
109 class NullableString16;
111 namespace base {
112 class DictionaryValue;
113 class ListValue;
114 class Time;
115 class TimeDelta;
116 class TimeTicks;
117 struct FileDescriptor;
120 namespace IPC {
122 struct ChannelHandle;
124 //-----------------------------------------------------------------------------
125 // An iterator class for reading the fields contained within a Message.
127 class MessageIterator {
128 public:
129 explicit MessageIterator(const Message& m) : iter_(m) {
131 int NextInt() const {
132 int val = -1;
133 if (!iter_.ReadInt(&val))
134 NOTREACHED();
135 return val;
137 const std::string NextString() const {
138 std::string val;
139 if (!iter_.ReadString(&val))
140 NOTREACHED();
141 return val;
143 const std::wstring NextWString() const {
144 std::wstring val;
145 if (!iter_.ReadWString(&val))
146 NOTREACHED();
147 return val;
149 void NextData(const char** data, int* length) const {
150 if (!iter_.ReadData(data, length)) {
151 NOTREACHED();
154 private:
155 mutable PickleIterator iter_;
158 //-----------------------------------------------------------------------------
159 // A dummy struct to place first just to allow leading commas for all
160 // members in the macro-generated constructor initializer lists.
161 struct NoParams {
164 //-----------------------------------------------------------------------------
165 // ParamTraits specializations, etc.
167 template <class P>
168 static inline void WriteParam(Message* m, const P& p) {
169 typedef typename SimilarTypeTraits<P>::Type Type;
170 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
173 template <class P>
174 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m,
175 PickleIterator* iter,
176 P* p) {
177 typedef typename SimilarTypeTraits<P>::Type Type;
178 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
181 template <class P>
182 static inline void LogParam(const P& p, std::string* l) {
183 typedef typename SimilarTypeTraits<P>::Type Type;
184 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
187 template <>
188 struct ParamTraits<bool> {
189 typedef bool param_type;
190 static void Write(Message* m, const param_type& p) {
191 m->WriteBool(p);
193 static bool Read(const Message* m, PickleIterator* iter,
194 param_type* r) {
195 return m->ReadBool(iter, r);
197 static void Log(const param_type& p, std::string* l) {
198 l->append(p ? "true" : "false");
202 template <>
203 struct ParamTraits<int> {
204 typedef int param_type;
205 static void Write(Message* m, const param_type& p) {
206 m->WriteInt(p);
208 static bool Read(const Message* m, PickleIterator* iter,
209 param_type* r) {
210 return m->ReadInt(iter, r);
212 IPC_EXPORT static void Log(const param_type& p, std::string* l);
215 template <>
216 struct ParamTraits<unsigned int> {
217 typedef unsigned int param_type;
218 static void Write(Message* m, const param_type& p) {
219 m->WriteInt(p);
221 static bool Read(const Message* m, PickleIterator* iter,
222 param_type* r) {
223 return m->ReadInt(iter, reinterpret_cast<int*>(r));
225 IPC_EXPORT static void Log(const param_type& p, std::string* l);
228 template <>
229 struct ParamTraits<long> {
230 typedef long param_type;
231 static void Write(Message* m, const param_type& p) {
232 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
234 static bool Read(const Message* m, PickleIterator* iter,
235 param_type* r) {
236 return m->ReadLong(iter, r);
238 IPC_EXPORT static void Log(const param_type& p, std::string* l);
241 template <>
242 struct ParamTraits<unsigned long> {
243 typedef unsigned long param_type;
244 static void Write(Message* m, const param_type& p) {
245 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p);
247 static bool Read(const Message* m, PickleIterator* iter,
248 param_type* r) {
249 return m->ReadLong(iter, reinterpret_cast<long*>(r));
251 IPC_EXPORT static void Log(const param_type& p, std::string* l);
254 template <>
255 struct ParamTraits<long long> {
256 typedef long long param_type;
257 static void Write(Message* m, const param_type& p) {
258 m->WriteInt64(static_cast<int64>(p));
260 static bool Read(const Message* m, PickleIterator* iter,
261 param_type* r) {
262 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
264 IPC_EXPORT static void Log(const param_type& p, std::string* l);
267 template <>
268 struct ParamTraits<unsigned long long> {
269 typedef unsigned long long param_type;
270 static void Write(Message* m, const param_type& p) {
271 m->WriteInt64(p);
273 static bool Read(const Message* m, PickleIterator* iter,
274 param_type* r) {
275 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
277 IPC_EXPORT static void Log(const param_type& p, std::string* l);
280 template <>
281 struct IPC_EXPORT ParamTraits<unsigned short> {
282 typedef unsigned short param_type;
283 static void Write(Message* m, const param_type& p);
284 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
285 static void Log(const param_type& p, std::string* l);
288 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
289 // should be sure to check the sanity of these values after receiving them over
290 // IPC.
291 template <>
292 struct ParamTraits<float> {
293 typedef float param_type;
294 static void Write(Message* m, const param_type& p) {
295 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
297 static bool Read(const Message* m, PickleIterator* iter,
298 param_type* r) {
299 const char *data;
300 int data_size;
301 if (!m->ReadData(iter, &data, &data_size) ||
302 data_size != sizeof(param_type)) {
303 NOTREACHED();
304 return false;
306 memcpy(r, data, sizeof(param_type));
307 return true;
309 static void Log(const param_type& p, std::string* l) {
310 l->append(StringPrintf("%e", p));
314 template <>
315 struct ParamTraits<double> {
316 typedef double param_type;
317 static void Write(Message* m, const param_type& p) {
318 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
320 static bool Read(const Message* m, PickleIterator* iter,
321 param_type* r) {
322 const char *data;
323 int data_size;
324 if (!m->ReadData(iter, &data, &data_size) ||
325 data_size != sizeof(param_type)) {
326 NOTREACHED();
327 return false;
329 memcpy(r, data, sizeof(param_type));
330 return true;
332 static void Log(const param_type& p, std::string* l) {
333 l->append(StringPrintf("%e", p));
337 template <>
338 struct IPC_EXPORT ParamTraits<base::Time> {
339 typedef base::Time param_type;
340 static void Write(Message* m, const param_type& p);
341 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
342 static void Log(const param_type& p, std::string* l);
345 template <>
346 struct IPC_EXPORT ParamTraits<base::TimeDelta> {
347 typedef base::TimeDelta param_type;
348 static void Write(Message* m, const param_type& p);
349 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
350 static void Log(const param_type& p, std::string* l);
353 template <>
354 struct IPC_EXPORT ParamTraits<base::TimeTicks> {
355 typedef base::TimeTicks param_type;
356 static void Write(Message* m, const param_type& p);
357 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
358 static void Log(const param_type& p, std::string* l);
361 #if defined(OS_WIN)
362 template <>
363 struct ParamTraits<LOGFONT> {
364 typedef LOGFONT param_type;
365 static void Write(Message* m, const param_type& p) {
366 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
368 static bool Read(const Message* m, PickleIterator* iter,
369 param_type* r) {
370 const char *data;
371 int data_size = 0;
372 bool result = m->ReadData(iter, &data, &data_size);
373 if (result && data_size == sizeof(LOGFONT)) {
374 memcpy(r, data, sizeof(LOGFONT));
375 } else {
376 result = false;
377 NOTREACHED();
380 return result;
382 static void Log(const param_type& p, std::string* l) {
383 l->append(StringPrintf("<LOGFONT>"));
387 template <>
388 struct ParamTraits<MSG> {
389 typedef MSG param_type;
390 static void Write(Message* m, const param_type& p) {
391 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
393 static bool Read(const Message* m, PickleIterator* iter,
394 param_type* r) {
395 const char *data;
396 int data_size = 0;
397 bool result = m->ReadData(iter, &data, &data_size);
398 if (result && data_size == sizeof(MSG)) {
399 memcpy(r, data, sizeof(MSG));
400 } else {
401 result = false;
402 NOTREACHED();
405 return result;
407 static void Log(const param_type& p, std::string* l) {
408 l->append("<MSG>");
411 #endif // defined(OS_WIN)
413 template <>
414 struct IPC_EXPORT ParamTraits<base::DictionaryValue> {
415 typedef base::DictionaryValue param_type;
416 static void Write(Message* m, const param_type& p);
417 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
418 static void Log(const param_type& p, std::string* l);
421 template <>
422 struct IPC_EXPORT ParamTraits<base::ListValue> {
423 typedef base::ListValue param_type;
424 static void Write(Message* m, const param_type& p);
425 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
426 static void Log(const param_type& p, std::string* l);
429 template <>
430 struct ParamTraits<std::string> {
431 typedef std::string param_type;
432 static void Write(Message* m, const param_type& p) {
433 m->WriteString(p);
435 static bool Read(const Message* m, PickleIterator* iter,
436 param_type* r) {
437 return m->ReadString(iter, r);
439 static void Log(const param_type& p, std::string* l) {
440 l->append(p);
444 template<typename CharType>
445 static void LogBytes(const std::vector<CharType>& data, std::string* out) {
446 #if defined(OS_WIN)
447 // Windows has a GUI for logging, which can handle arbitrary binary data.
448 for (size_t i = 0; i < data.size(); ++i)
449 out->push_back(data[i]);
450 #else
451 // On POSIX, we log to stdout, which we assume can display ASCII.
452 static const size_t kMaxBytesToLog = 100;
453 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
454 if (isprint(data[i]))
455 out->push_back(data[i]);
456 else
457 out->append(StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
459 if (data.size() > kMaxBytesToLog) {
460 out->append(
461 StringPrintf(" and %u more bytes",
462 static_cast<unsigned>(data.size() - kMaxBytesToLog)));
464 #endif
467 template <>
468 struct ParamTraits<std::vector<unsigned char> > {
469 typedef std::vector<unsigned char> param_type;
470 static void Write(Message* m, const param_type& p) {
471 if (p.empty()) {
472 m->WriteData(NULL, 0);
473 } else {
474 m->WriteData(reinterpret_cast<const char*>(&p.front()),
475 static_cast<int>(p.size()));
478 static bool Read(const Message* m, PickleIterator* iter,
479 param_type* r) {
480 const char *data;
481 int data_size = 0;
482 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
483 return false;
484 r->resize(data_size);
485 if (data_size)
486 memcpy(&r->front(), data, data_size);
487 return true;
489 static void Log(const param_type& p, std::string* l) {
490 LogBytes(p, l);
494 template <>
495 struct ParamTraits<std::vector<char> > {
496 typedef std::vector<char> param_type;
497 static void Write(Message* m, const param_type& p) {
498 if (p.empty()) {
499 m->WriteData(NULL, 0);
500 } else {
501 m->WriteData(&p.front(), static_cast<int>(p.size()));
504 static bool Read(const Message* m, PickleIterator* iter,
505 param_type* r) {
506 const char *data;
507 int data_size = 0;
508 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
509 return false;
510 r->resize(data_size);
511 if (data_size)
512 memcpy(&r->front(), data, data_size);
513 return true;
515 static void Log(const param_type& p, std::string* l) {
516 LogBytes(p, l);
520 template <>
521 struct ParamTraits<std::vector<bool> > {
522 typedef std::vector<bool> param_type;
523 static void Write(Message* m, const param_type& p) {
524 WriteParam(m, static_cast<int>(p.size()));
525 for (size_t i = 0; i < p.size(); i++)
526 WriteParam(m, p[i]);
528 static bool Read(const Message* m, PickleIterator* iter,
529 param_type* r) {
530 int size;
531 // ReadLength() checks for < 0 itself.
532 if (!m->ReadLength(iter, &size))
533 return false;
534 r->resize(size);
535 for (int i = 0; i < size; i++) {
536 bool value;
537 if (!ReadParam(m, iter, &value))
538 return false;
539 (*r)[i] = value;
541 return true;
543 static void Log(const param_type& p, std::string* l) {
544 for (size_t i = 0; i < p.size(); ++i) {
545 if (i != 0)
546 l->append(" ");
547 LogParam((p[i]), l);
552 template <class P>
553 struct ParamTraits<std::vector<P> > {
554 typedef std::vector<P> param_type;
555 static void Write(Message* m, const param_type& p) {
556 WriteParam(m, static_cast<int>(p.size()));
557 for (size_t i = 0; i < p.size(); i++)
558 WriteParam(m, p[i]);
560 static bool Read(const Message* m, PickleIterator* iter,
561 param_type* r) {
562 int size;
563 // ReadLength() checks for < 0 itself.
564 if (!m->ReadLength(iter, &size))
565 return false;
566 // Resizing beforehand is not safe, see BUG 1006367 for details.
567 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
568 return false;
569 r->resize(size);
570 for (int i = 0; i < size; i++) {
571 if (!ReadParam(m, iter, &(*r)[i]))
572 return false;
574 return true;
576 static void Log(const param_type& p, std::string* l) {
577 for (size_t i = 0; i < p.size(); ++i) {
578 if (i != 0)
579 l->append(" ");
580 LogParam((p[i]), l);
585 template <class P>
586 struct ParamTraits<std::set<P> > {
587 typedef std::set<P> param_type;
588 static void Write(Message* m, const param_type& p) {
589 WriteParam(m, static_cast<int>(p.size()));
590 typename param_type::const_iterator iter;
591 for (iter = p.begin(); iter != p.end(); ++iter)
592 WriteParam(m, *iter);
594 static bool Read(const Message* m, PickleIterator* iter,
595 param_type* r) {
596 int size;
597 if (!m->ReadLength(iter, &size))
598 return false;
599 for (int i = 0; i < size; ++i) {
600 P item;
601 if (!ReadParam(m, iter, &item))
602 return false;
603 r->insert(item);
605 return true;
607 static void Log(const param_type& p, std::string* l) {
608 l->append("<std::set>");
613 template <class K, class V>
614 struct ParamTraits<std::map<K, V> > {
615 typedef std::map<K, V> param_type;
616 static void Write(Message* m, const param_type& p) {
617 WriteParam(m, static_cast<int>(p.size()));
618 typename param_type::const_iterator iter;
619 for (iter = p.begin(); iter != p.end(); ++iter) {
620 WriteParam(m, iter->first);
621 WriteParam(m, iter->second);
624 static bool Read(const Message* m, PickleIterator* iter,
625 param_type* r) {
626 int size;
627 if (!ReadParam(m, iter, &size) || size < 0)
628 return false;
629 for (int i = 0; i < size; ++i) {
630 K k;
631 if (!ReadParam(m, iter, &k))
632 return false;
633 V& value = (*r)[k];
634 if (!ReadParam(m, iter, &value))
635 return false;
637 return true;
639 static void Log(const param_type& p, std::string* l) {
640 l->append("<std::map>");
645 template <>
646 struct ParamTraits<std::wstring> {
647 typedef std::wstring param_type;
648 static void Write(Message* m, const param_type& p) {
649 m->WriteWString(p);
651 static bool Read(const Message* m, PickleIterator* iter,
652 param_type* r) {
653 return m->ReadWString(iter, r);
655 IPC_EXPORT static void Log(const param_type& p, std::string* l);
658 template <class A, class B>
659 struct ParamTraits<std::pair<A, B> > {
660 typedef std::pair<A, B> param_type;
661 static void Write(Message* m, const param_type& p) {
662 WriteParam(m, p.first);
663 WriteParam(m, p.second);
665 static bool Read(const Message* m, PickleIterator* iter,
666 param_type* r) {
667 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
669 static void Log(const param_type& p, std::string* l) {
670 l->append("(");
671 LogParam(p.first, l);
672 l->append(", ");
673 LogParam(p.second, l);
674 l->append(")");
678 template <>
679 struct IPC_EXPORT ParamTraits<NullableString16> {
680 typedef NullableString16 param_type;
681 static void Write(Message* m, const param_type& p);
682 static bool Read(const Message* m, PickleIterator* iter,
683 param_type* r);
684 static void Log(const param_type& p, std::string* l);
687 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
688 // need this trait.
689 #if !defined(WCHAR_T_IS_UTF16)
690 template <>
691 struct ParamTraits<string16> {
692 typedef string16 param_type;
693 static void Write(Message* m, const param_type& p) {
694 m->WriteString16(p);
696 static bool Read(const Message* m, PickleIterator* iter,
697 param_type* r) {
698 return m->ReadString16(iter, r);
700 IPC_EXPORT static void Log(const param_type& p, std::string* l);
702 #endif
704 // and, a few more useful types...
705 #if defined(OS_WIN)
706 template <>
707 struct ParamTraits<HANDLE> {
708 typedef HANDLE param_type;
709 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
710 // bit systems.
711 static void Write(Message* m, const param_type& p) {
712 m->WriteUInt32(reinterpret_cast<uint32>(p));
714 static bool Read(const Message* m, PickleIterator* iter,
715 param_type* r) {
716 uint32 temp;
717 if (!m->ReadUInt32(iter, &temp))
718 return false;
719 *r = reinterpret_cast<HANDLE>(temp);
720 return true;
722 static void Log(const param_type& p, std::string* l) {
723 l->append(StringPrintf("0x%X", p));
727 template <>
728 struct ParamTraits<HCURSOR> {
729 typedef HCURSOR param_type;
730 static void Write(Message* m, const param_type& p) {
731 m->WriteUInt32(reinterpret_cast<uint32>(p));
733 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
734 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
735 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
737 static void Log(const param_type& p, std::string* l) {
738 l->append(StringPrintf("0x%X", p));
742 template <>
743 struct ParamTraits<HACCEL> {
744 typedef HACCEL param_type;
745 static void Write(Message* m, const param_type& p) {
746 m->WriteUInt32(reinterpret_cast<uint32>(p));
748 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
749 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
750 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
754 template <>
755 struct ParamTraits<POINT> {
756 typedef POINT param_type;
757 static void Write(Message* m, const param_type& p) {
758 m->WriteInt(p.x);
759 m->WriteInt(p.y);
761 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
762 int x, y;
763 if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
764 return false;
765 r->x = x;
766 r->y = y;
767 return true;
769 static void Log(const param_type& p, std::string* l) {
770 l->append(StringPrintf("(%d, %d)", p.x, p.y));
773 #endif // defined(OS_WIN)
775 template <>
776 struct IPC_EXPORT ParamTraits<FilePath> {
777 typedef FilePath param_type;
778 static void Write(Message* m, const param_type& p);
779 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
780 static void Log(const param_type& p, std::string* l);
783 #if defined(OS_POSIX)
784 // FileDescriptors may be serialised over IPC channels on POSIX. On the
785 // receiving side, the FileDescriptor is a valid duplicate of the file
786 // descriptor which was transmitted: *it is not just a copy of the integer like
787 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
788 // this case, the receiving end will see a value of -1. *Zero is a valid file
789 // descriptor*.
791 // The received file descriptor will have the |auto_close| flag set to true. The
792 // code which handles the message is responsible for taking ownership of it.
793 // File descriptors are OS resources and must be closed when no longer needed.
795 // When sending a file descriptor, the file descriptor must be valid at the time
796 // of transmission. Since transmission is not synchronous, one should consider
797 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
798 // flag, which causes the file descriptor to be closed after writing.
799 template<>
800 struct IPC_EXPORT ParamTraits<base::FileDescriptor> {
801 typedef base::FileDescriptor param_type;
802 static void Write(Message* m, const param_type& p);
803 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
804 static void Log(const param_type& p, std::string* l);
806 #endif // defined(OS_POSIX)
808 // A ChannelHandle is basically a platform-inspecific wrapper around the
809 // fact that IPC endpoints are handled specially on POSIX. See above comments
810 // on FileDescriptor for more background.
811 template<>
812 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> {
813 typedef ChannelHandle param_type;
814 static void Write(Message* m, const param_type& p);
815 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
816 static void Log(const param_type& p, std::string* l);
819 #if defined(OS_WIN)
820 template <>
821 struct ParamTraits<XFORM> {
822 typedef XFORM param_type;
823 static void Write(Message* m, const param_type& p) {
824 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
826 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
827 const char *data;
828 int data_size = 0;
829 bool result = m->ReadData(iter, &data, &data_size);
830 if (result && data_size == sizeof(XFORM)) {
831 memcpy(r, data, sizeof(XFORM));
832 } else {
833 result = false;
834 NOTREACHED();
837 return result;
839 static void Log(const param_type& p, std::string* l) {
840 l->append("<XFORM>");
843 #endif // defined(OS_WIN)
845 struct IPC_EXPORT LogData {
846 LogData();
847 ~LogData();
849 std::string channel;
850 int32 routing_id;
851 uint32 type; // "User-defined" message type, from ipc_message.h.
852 std::string flags;
853 int64 sent; // Time that the message was sent (i.e. at Send()).
854 int64 receive; // Time before it was dispatched (i.e. before calling
855 // OnMessageReceived).
856 int64 dispatch; // Time after it was dispatched (i.e. after calling
857 // OnMessageReceived).
858 std::string message_name;
859 std::string params;
862 template <>
863 struct IPC_EXPORT ParamTraits<LogData> {
864 typedef LogData param_type;
865 static void Write(Message* m, const param_type& p);
866 static bool Read(const Message* m, PickleIterator* iter, param_type* r);
867 static void Log(const param_type& p, std::string* l) {
868 // Doesn't make sense to implement this!
872 template <>
873 struct ParamTraits<Message> {
874 static void Write(Message* m, const Message& p) {
875 DCHECK(p.size() <= INT_MAX);
876 int message_size = static_cast<int>(p.size());
877 m->WriteInt(message_size);
878 m->WriteData(reinterpret_cast<const char*>(p.data()), message_size);
880 static bool Read(const Message* m, PickleIterator* iter, Message* r) {
881 int size;
882 if (!m->ReadInt(iter, &size))
883 return false;
884 const char* data;
885 if (!m->ReadData(iter, &data, &size))
886 return false;
887 *r = Message(data, size);
888 return true;
890 static void Log(const Message& p, std::string* l) {
891 l->append("<IPC::Message>");
895 template <>
896 struct ParamTraits<Tuple0> {
897 typedef Tuple0 param_type;
898 static void Write(Message* m, const param_type& p) {
900 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
901 return true;
903 static void Log(const param_type& p, std::string* l) {
907 template <class A>
908 struct ParamTraits< Tuple1<A> > {
909 typedef Tuple1<A> param_type;
910 static void Write(Message* m, const param_type& p) {
911 WriteParam(m, p.a);
913 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
914 return ReadParam(m, iter, &r->a);
916 static void Log(const param_type& p, std::string* l) {
917 LogParam(p.a, l);
921 template <class A, class B>
922 struct ParamTraits< Tuple2<A, B> > {
923 typedef Tuple2<A, B> param_type;
924 static void Write(Message* m, const param_type& p) {
925 WriteParam(m, p.a);
926 WriteParam(m, p.b);
928 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
929 return (ReadParam(m, iter, &r->a) &&
930 ReadParam(m, iter, &r->b));
932 static void Log(const param_type& p, std::string* l) {
933 LogParam(p.a, l);
934 l->append(", ");
935 LogParam(p.b, l);
939 template <class A, class B, class C>
940 struct ParamTraits< Tuple3<A, B, C> > {
941 typedef Tuple3<A, B, C> param_type;
942 static void Write(Message* m, const param_type& p) {
943 WriteParam(m, p.a);
944 WriteParam(m, p.b);
945 WriteParam(m, p.c);
947 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
948 return (ReadParam(m, iter, &r->a) &&
949 ReadParam(m, iter, &r->b) &&
950 ReadParam(m, iter, &r->c));
952 static void Log(const param_type& p, std::string* l) {
953 LogParam(p.a, l);
954 l->append(", ");
955 LogParam(p.b, l);
956 l->append(", ");
957 LogParam(p.c, l);
961 template <class A, class B, class C, class D>
962 struct ParamTraits< Tuple4<A, B, C, D> > {
963 typedef Tuple4<A, B, C, D> param_type;
964 static void Write(Message* m, const param_type& p) {
965 WriteParam(m, p.a);
966 WriteParam(m, p.b);
967 WriteParam(m, p.c);
968 WriteParam(m, p.d);
970 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
971 return (ReadParam(m, iter, &r->a) &&
972 ReadParam(m, iter, &r->b) &&
973 ReadParam(m, iter, &r->c) &&
974 ReadParam(m, iter, &r->d));
976 static void Log(const param_type& p, std::string* l) {
977 LogParam(p.a, l);
978 l->append(", ");
979 LogParam(p.b, l);
980 l->append(", ");
981 LogParam(p.c, l);
982 l->append(", ");
983 LogParam(p.d, l);
987 template <class A, class B, class C, class D, class E>
988 struct ParamTraits< Tuple5<A, B, C, D, E> > {
989 typedef Tuple5<A, B, C, D, E> param_type;
990 static void Write(Message* m, const param_type& p) {
991 WriteParam(m, p.a);
992 WriteParam(m, p.b);
993 WriteParam(m, p.c);
994 WriteParam(m, p.d);
995 WriteParam(m, p.e);
997 static bool Read(const Message* m, PickleIterator* iter, param_type* r) {
998 return (ReadParam(m, iter, &r->a) &&
999 ReadParam(m, iter, &r->b) &&
1000 ReadParam(m, iter, &r->c) &&
1001 ReadParam(m, iter, &r->d) &&
1002 ReadParam(m, iter, &r->e));
1004 static void Log(const param_type& p, std::string* l) {
1005 LogParam(p.a, l);
1006 l->append(", ");
1007 LogParam(p.b, l);
1008 l->append(", ");
1009 LogParam(p.c, l);
1010 l->append(", ");
1011 LogParam(p.d, l);
1012 l->append(", ");
1013 LogParam(p.e, l);
1017 //-----------------------------------------------------------------------------
1018 // Generic message subclasses
1020 // Used for asynchronous messages.
1021 template <class ParamType>
1022 class MessageSchema {
1023 public:
1024 typedef ParamType Param;
1025 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
1027 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE;
1028 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
1031 // defined in ipc_logging.cc
1032 IPC_EXPORT void GenerateLogData(const std::string& channel,
1033 const Message& message,
1034 LogData* data, bool get_params);
1037 #if defined(IPC_MESSAGE_LOG_ENABLED)
1038 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
1039 const std::string& output_params = msg->output_params();
1040 if (!l->empty() && !output_params.empty())
1041 l->append(", ");
1043 l->append(output_params);
1046 template <class ReplyParamType>
1047 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1048 const Message* msg) {
1049 if (msg->received_time() != 0) {
1050 std::string output_params;
1051 LogParam(reply_params, &output_params);
1052 msg->set_output_params(output_params);
1056 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
1057 if (msg->sent_time()) {
1058 // Don't log the sync message after dispatch, as we don't have the
1059 // output parameters at that point. Instead, save its data and log it
1060 // with the outgoing reply message when it's sent.
1061 LogData* data = new LogData;
1062 GenerateLogData("", *msg, data, true);
1063 msg->set_dont_log();
1064 reply->set_sync_log_data(data);
1067 #else
1068 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
1070 template <class ReplyParamType>
1071 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1072 const Message* msg) {}
1074 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
1075 #endif
1077 // This class assumes that its template argument is a RefTuple (a Tuple with
1078 // reference elements). This would go into ipc_message_utils_impl.h, but it is
1079 // also used by chrome_frame.
1080 template <class RefTuple>
1081 class ParamDeserializer : public MessageReplyDeserializer {
1082 public:
1083 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
1085 bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) {
1086 return ReadParam(&msg, &iter, &out_);
1089 RefTuple out_;
1092 // Used for synchronous messages.
1093 template <class SendParamType, class ReplyParamType>
1094 class SyncMessageSchema {
1095 public:
1096 typedef SendParamType SendParam;
1097 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
1098 typedef ReplyParamType ReplyParam;
1100 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE;
1101 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
1102 static bool ReadReplyParam(
1103 const Message* msg,
1104 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
1106 template<class T, class S, class Method>
1107 static bool DispatchWithSendParams(bool ok, const SendParam& send_params,
1108 const Message* msg, T* obj, S* sender,
1109 Method func) {
1110 Message* reply = SyncMessage::GenerateReply(msg);
1111 if (ok) {
1112 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
1113 DispatchToMethod(obj, func, send_params, &reply_params);
1114 WriteParam(reply, reply_params);
1115 LogReplyParamsToMessage(reply_params, msg);
1116 } else {
1117 NOTREACHED() << "Error deserializing message " << msg->type();
1118 reply->set_reply_error();
1120 sender->Send(reply);
1121 return ok;
1124 template<class T, class Method>
1125 static bool DispatchDelayReplyWithSendParams(bool ok,
1126 const SendParam& send_params,
1127 const Message* msg, T* obj,
1128 Method func) {
1129 Message* reply = SyncMessage::GenerateReply(msg);
1130 if (ok) {
1131 Tuple1<Message&> t = MakeRefTuple(*reply);
1132 ConnectMessageAndReply(msg, reply);
1133 DispatchToMethod(obj, func, send_params, &t);
1134 } else {
1135 NOTREACHED() << "Error deserializing message " << msg->type();
1136 reply->set_reply_error();
1137 obj->Send(reply);
1139 return ok;
1142 template<typename TA>
1143 static void WriteReplyParams(Message* reply, TA a) {
1144 ReplyParam p(a);
1145 WriteParam(reply, p);
1148 template<typename TA, typename TB>
1149 static void WriteReplyParams(Message* reply, TA a, TB b) {
1150 ReplyParam p(a, b);
1151 WriteParam(reply, p);
1154 template<typename TA, typename TB, typename TC>
1155 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
1156 ReplyParam p(a, b, c);
1157 WriteParam(reply, p);
1160 template<typename TA, typename TB, typename TC, typename TD>
1161 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
1162 ReplyParam p(a, b, c, d);
1163 WriteParam(reply, p);
1166 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1167 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
1168 ReplyParam p(a, b, c, d, e);
1169 WriteParam(reply, p);
1173 //-----------------------------------------------------------------------------
1175 } // namespace IPC
1177 #endif // IPC_IPC_MESSAGE_UTILS_H_