Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 // Copyright (c) 2006-2008 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 CHROME_COMMON_IPC_MESSAGE_UTILS_H_
6 #define CHROME_COMMON_IPC_MESSAGE_UTILS_H_
8 #include <string>
9 #include <vector>
10 #include <map>
12 #include "base/file_path.h"
13 #include "base/string_util.h"
14 #include "base/string16.h"
15 #include "base/tuple.h"
16 #include "base/time.h"
18 #if defined(OS_POSIX)
19 #include "chrome/common/file_descriptor_set_posix.h"
20 #endif
21 #include "chrome/common/ipc_sync_message.h"
22 #include "chrome/common/transport_dib.h"
24 namespace IPC {
26 //-----------------------------------------------------------------------------
27 // An iterator class for reading the fields contained within a Message.
29 class MessageIterator {
30 public:
31 explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
32 }
33 int NextInt() const {
34 int val;
35 if (!msg_.ReadInt(&iter_, &val))
36 NOTREACHED();
37 return val;
38 }
39 intptr_t NextIntPtr() const {
40 intptr_t val;
41 if (!msg_.ReadIntPtr(&iter_, &val))
42 NOTREACHED();
43 return val;
44 }
45 const std::string NextString() const {
46 std::string val;
47 if (!msg_.ReadString(&iter_, &val))
48 NOTREACHED();
49 return val;
50 }
51 const std::wstring NextWString() const {
52 std::wstring val;
53 if (!msg_.ReadWString(&iter_, &val))
54 NOTREACHED();
55 return val;
56 }
57 const void NextData(const char** data, int* length) const {
58 if (!msg_.ReadData(&iter_, data, length)) {
59 NOTREACHED();
60 }
61 }
62 private:
63 const Message& msg_;
64 mutable void* iter_;
65 };
67 //-----------------------------------------------------------------------------
68 // ParamTraits specializations, etc.
69 //
70 // The full set of types ParamTraits is specialized upon contains *possibly*
71 // repeated types: unsigned long may be uint32_t or size_t, unsigned long long
72 // may be uint64_t or size_t, nsresult may be uint32_t, and so on. You can't
73 // have ParamTraits<unsigned int> *and* ParamTraits<uint32_t> if unsigned int
74 // is uint32_t -- that's multiple definitions, and you can only have one.
75 //
76 // You could use #ifs and macro conditions to avoid duplicates, but they'd be
77 // hairy: heavily dependent upon OS and compiler author choices, forced to
78 // address all conflicts by hand. Happily there's a better way. The basic
79 // idea looks like this, where T -> U represents T inheriting from U:
80 //
81 // class ParamTraits<P>
82 // |
83 // --> class ParamTraits1<P>
84 // |
85 // --> class ParamTraits2<P>
86 // |
87 // --> class ParamTraitsN<P> // or however many levels
88 //
89 // The default specialization of ParamTraits{M}<P> is an empty class that
90 // inherits from ParamTraits{M + 1}<P> (or nothing in the base case).
91 //
92 // Now partition the set of parameter types into sets without duplicates.
93 // Assign each set of types to a level M. Then specialize ParamTraitsM for
94 // each of those types. A reference to ParamTraits<P> will consist of some
95 // number of empty classes inheriting in sequence, ending in a non-empty
96 // ParamTraits{N}<P>. It's okay for the parameter types to be duplicative:
97 // either name of a type will resolve to the same ParamTraits{N}<P>.
98 //
99 // The nice thing is that because templates are instantiated lazily, if we
100 // indeed have uint32_t == unsigned int, say, with the former in level N and
101 // the latter in M > N, ParamTraitsM<unsigned int> won't be created (as long as
102 // nobody uses ParamTraitsM<unsigned int>, but why would you), and no duplicate
103 // code will be compiled or extra symbols generated. It's as efficient at
104 // runtime as manually figuring out and avoiding conflicts by #ifs.
105 //
106 // The scheme we follow below names the various classes according to the types
107 // in them, and the number of ParamTraits levels is larger, but otherwise it's
108 // exactly the above idea.
109 //
111 template <class P> struct ParamTraits;
113 template <class P>
114 static inline void WriteParam(Message* m, const P& p) {
115 ParamTraits<P>::Write(m, p);
116 }
118 template <class P>
119 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
120 P* p) {
121 return ParamTraits<P>::Read(m, iter, p);
122 }
124 template <class P>
125 static inline void LogParam(const P& p, std::wstring* l) {
126 ParamTraits<P>::Log(p, l);
127 }
129 // Fundamental types.
131 template <class P>
132 struct ParamTraitsFundamental {};
134 template <>
135 struct ParamTraitsFundamental<bool> {
136 typedef bool param_type;
137 static void Write(Message* m, const param_type& p) {
138 m->WriteBool(p);
139 }
140 static bool Read(const Message* m, void** iter, param_type* r) {
141 return m->ReadBool(iter, r);
142 }
143 static void Log(const param_type& p, std::wstring* l) {
144 l->append(p ? L"true" : L"false");
145 }
146 };
148 template <>
149 struct ParamTraitsFundamental<int> {
150 typedef int param_type;
151 static void Write(Message* m, const param_type& p) {
152 m->WriteInt(p);
153 }
154 static bool Read(const Message* m, void** iter, param_type* r) {
155 return m->ReadInt(iter, r);
156 }
157 static void Log(const param_type& p, std::wstring* l) {
158 l->append(StringPrintf(L"%d", p));
159 }
160 };
162 template <>
163 struct ParamTraitsFundamental<long> {
164 typedef long param_type;
165 static void Write(Message* m, const param_type& p) {
166 m->WriteLong(p);
167 }
168 static bool Read(const Message* m, void** iter, param_type* r) {
169 return m->ReadLong(iter, r);
170 }
171 static void Log(const param_type& p, std::wstring* l) {
172 l->append(StringPrintf(L"%l", p));
173 }
174 };
176 template <>
177 struct ParamTraitsFundamental<unsigned long> {
178 typedef unsigned long param_type;
179 static void Write(Message* m, const param_type& p) {
180 m->WriteULong(p);
181 }
182 static bool Read(const Message* m, void** iter, param_type* r) {
183 return m->ReadULong(iter, r);
184 }
185 static void Log(const param_type& p, std::wstring* l) {
186 l->append(StringPrintf(L"%ul", p));
187 }
188 };
190 template <>
191 struct ParamTraitsFundamental<long long> {
192 typedef long long param_type;
193 static void Write(Message* m, const param_type& p) {
194 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
195 }
196 static bool Read(const Message* m, void** iter, param_type* r) {
197 const char *data;
198 int data_size = 0;
199 bool result = m->ReadData(iter, &data, &data_size);
200 if (result && data_size == sizeof(param_type)) {
201 memcpy(r, data, sizeof(param_type));
202 } else {
203 result = false;
204 NOTREACHED();
205 }
206 return result;
207 }
208 static void Log(const param_type& p, std::wstring* l) {
209 l->append(StringPrintf(L"%ll", p));
210 }
211 };
213 template <>
214 struct ParamTraitsFundamental<unsigned long long> {
215 typedef unsigned long long param_type;
216 static void Write(Message* m, const param_type& p) {
217 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
218 }
219 static bool Read(const Message* m, void** iter, param_type* r) {
220 const char *data;
221 int data_size = 0;
222 bool result = m->ReadData(iter, &data, &data_size);
223 if (result && data_size == sizeof(param_type)) {
224 memcpy(r, data, sizeof(param_type));
225 } else {
226 result = false;
227 NOTREACHED();
228 }
229 return result;
230 }
231 static void Log(const param_type& p, std::wstring* l) {
232 l->append(StringPrintf(L"%ull", p));
233 }
234 };
236 template <>
237 struct ParamTraitsFundamental<double> {
238 typedef double param_type;
239 static void Write(Message* m, const param_type& p) {
240 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
241 }
242 static bool Read(const Message* m, void** iter, param_type* r) {
243 const char *data;
244 int data_size = 0;
245 bool result = m->ReadData(iter, &data, &data_size);
246 if (result && data_size == sizeof(param_type)) {
247 memcpy(r, data, sizeof(param_type));
248 } else {
249 result = false;
250 NOTREACHED();
251 }
253 return result;
254 }
255 static void Log(const param_type& p, std::wstring* l) {
256 l->append(StringPrintf(L"e", p));
257 }
258 };
260 // Fixed-size <stdint.h> types.
262 template <class P>
263 struct ParamTraitsFixed : ParamTraitsFundamental<P> {};
265 template <>
266 struct ParamTraitsFixed<int16_t> {
267 typedef int16_t param_type;
268 static void Write(Message* m, const param_type& p) {
269 m->WriteInt16(p);
270 }
271 static bool Read(const Message* m, void** iter, param_type* r) {
272 return m->ReadInt16(iter, r);
273 }
274 static void Log(const param_type& p, std::wstring* l) {
275 l->append(StringPrintf(L"%hd", p));
276 }
277 };
279 template <>
280 struct ParamTraitsFixed<uint16_t> {
281 typedef uint16_t param_type;
282 static void Write(Message* m, const param_type& p) {
283 m->WriteUInt16(p);
284 }
285 static bool Read(const Message* m, void** iter, param_type* r) {
286 return m->ReadUInt16(iter, r);
287 }
288 static void Log(const param_type& p, std::wstring* l) {
289 l->append(StringPrintf(L"%hu", p));
290 }
291 };
293 template <>
294 struct ParamTraitsFixed<uint32_t> {
295 typedef uint32_t param_type;
296 static void Write(Message* m, const param_type& p) {
297 m->WriteUInt32(p);
298 }
299 static bool Read(const Message* m, void** iter, param_type* r) {
300 return m->ReadUInt32(iter, r);
301 }
302 static void Log(const param_type& p, std::wstring* l) {
303 l->append(StringPrintf(L"%u", p));
304 }
305 };
307 template <>
308 struct ParamTraitsFixed<int64_t> {
309 typedef int64_t param_type;
310 static void Write(Message* m, const param_type& p) {
311 m->WriteInt64(p);
312 }
313 static bool Read(const Message* m, void** iter, param_type* r) {
314 return m->ReadInt64(iter, r);
315 }
316 static void Log(const param_type& p, std::wstring* l) {
317 l->append(StringPrintf(L"%" PRId64L, p));
318 }
319 };
321 template <>
322 struct ParamTraitsFixed<uint64_t> {
323 typedef uint64_t param_type;
324 static void Write(Message* m, const param_type& p) {
325 m->WriteInt64(static_cast<int64_t>(p));
326 }
327 static bool Read(const Message* m, void** iter, param_type* r) {
328 return m->ReadInt64(iter, reinterpret_cast<int64_t*>(r));
329 }
330 static void Log(const param_type& p, std::wstring* l) {
331 l->append(StringPrintf(L"%" PRIu64L, p));
332 }
333 };
335 // Other standard C types.
337 template <class P>
338 struct ParamTraitsLibC : ParamTraitsFixed<P> {};
340 template <>
341 struct ParamTraitsLibC<size_t> {
342 typedef size_t param_type;
343 static void Write(Message* m, const param_type& p) {
344 m->WriteSize(p);
345 }
346 static bool Read(const Message* m, void** iter, param_type* r) {
347 return m->ReadSize(iter, r);
348 }
349 static void Log(const param_type& p, std::wstring* l) {
350 l->append(StringPrintf(L"%u", p));
351 }
352 };
354 // std::* types.
356 template <class P>
357 struct ParamTraitsStd : ParamTraitsLibC<P> {};
359 template <>
360 struct ParamTraitsStd<std::string> {
361 typedef std::string param_type;
362 static void Write(Message* m, const param_type& p) {
363 m->WriteString(p);
364 }
365 static bool Read(const Message* m, void** iter, param_type* r) {
366 return m->ReadString(iter, r);
367 }
368 static void Log(const param_type& p, std::wstring* l) {
369 l->append(UTF8ToWide(p));
370 }
371 };
373 template <>
374 struct ParamTraitsStd<std::wstring> {
375 typedef std::wstring param_type;
376 static void Write(Message* m, const param_type& p) {
377 m->WriteWString(p);
378 }
379 static bool Read(const Message* m, void** iter, param_type* r) {
380 return m->ReadWString(iter, r);
381 }
382 static void Log(const param_type& p, std::wstring* l) {
383 l->append(p);
384 }
385 };
387 template <>
388 struct ParamTraitsStd<std::vector<unsigned char> > {
389 typedef std::vector<unsigned char> param_type;
390 static void Write(Message* m, const param_type& p) {
391 if (p.size() == 0) {
392 m->WriteData(NULL, 0);
393 } else {
394 m->WriteData(reinterpret_cast<const char*>(&p.front()),
395 static_cast<int>(p.size()));
396 }
397 }
398 static bool Read(const Message* m, void** iter, param_type* r) {
399 const char *data;
400 int data_size = 0;
401 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
402 return false;
403 r->resize(data_size);
404 if (data_size)
405 memcpy(&r->front(), data, data_size);
406 return true;
407 }
408 static void Log(const param_type& p, std::wstring* l) {
409 for (size_t i = 0; i < p.size(); ++i)
410 l->push_back(p[i]);
411 }
412 };
414 template <>
415 struct ParamTraitsStd<std::vector<char> > {
416 typedef std::vector<char> param_type;
417 static void Write(Message* m, const param_type& p) {
418 if (p.size() == 0) {
419 m->WriteData(NULL, 0);
420 } else {
421 m->WriteData(&p.front(), static_cast<int>(p.size()));
422 }
423 }
424 static bool Read(const Message* m, void** iter, param_type* r) {
425 const char *data;
426 int data_size = 0;
427 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
428 return false;
429 r->resize(data_size);
430 if (data_size)
431 memcpy(&r->front(), data, data_size);
432 return true;
433 }
434 static void Log(const param_type& p, std::wstring* l) {
435 for (size_t i = 0; i < p.size(); ++i)
436 l->push_back(p[i]);
437 }
438 };
440 template <class P>
441 struct ParamTraitsStd<std::vector<P> > {
442 typedef std::vector<P> param_type;
443 static void Write(Message* m, const param_type& p) {
444 WriteParam(m, static_cast<int>(p.size()));
445 for (size_t i = 0; i < p.size(); i++)
446 WriteParam(m, p[i]);
447 }
448 static bool Read(const Message* m, void** iter, param_type* r) {
449 int size;
450 if (!m->ReadLength(iter, &size))
451 return false;
452 // Resizing beforehand is not safe, see BUG 1006367 for details.
453 if (m->IteratorHasRoomFor(*iter, size * sizeof(P))) {
454 r->resize(size);
455 for (int i = 0; i < size; i++) {
456 if (!ReadParam(m, iter, &(*r)[i]))
457 return false;
458 }
459 } else {
460 for (int i = 0; i < size; i++) {
461 P element;
462 if (!ReadParam(m, iter, &element))
463 return false;
464 r->push_back(element);
465 }
466 }
467 return true;
468 }
469 static void Log(const param_type& p, std::wstring* l) {
470 for (size_t i = 0; i < p.size(); ++i) {
471 if (i != 0)
472 l->append(L" ");
474 LogParam((p[i]), l);
475 }
476 }
477 };
479 template <class K, class V>
480 struct ParamTraitsStd<std::map<K, V> > {
481 typedef std::map<K, V> param_type;
482 static void Write(Message* m, const param_type& p) {
483 WriteParam(m, static_cast<int>(p.size()));
484 typename param_type::const_iterator iter;
485 for (iter = p.begin(); iter != p.end(); ++iter) {
486 WriteParam(m, iter->first);
487 WriteParam(m, iter->second);
488 }
489 }
490 static bool Read(const Message* m, void** iter, param_type* r) {
491 int size;
492 if (!ReadParam(m, iter, &size) || size < 0)
493 return false;
494 for (int i = 0; i < size; ++i) {
495 K k;
496 if (!ReadParam(m, iter, &k))
497 return false;
498 V& value = (*r)[k];
499 if (!ReadParam(m, iter, &value))
500 return false;
501 }
502 return true;
503 }
504 static void Log(const param_type& p, std::wstring* l) {
505 l->append(L"<std::map>");
506 }
507 };
509 // Windows-specific types.
511 template <class P>
512 struct ParamTraitsWindows : ParamTraitsStd<P> {};
514 #if defined(OS_WIN)
515 template <>
516 struct ParamTraitsWindows<LOGFONT> {
517 typedef LOGFONT param_type;
518 static void Write(Message* m, const param_type& p) {
519 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
520 }
521 static bool Read(const Message* m, void** iter, param_type* r) {
522 const char *data;
523 int data_size = 0;
524 bool result = m->ReadData(iter, &data, &data_size);
525 if (result && data_size == sizeof(LOGFONT)) {
526 memcpy(r, data, sizeof(LOGFONT));
527 } else {
528 result = false;
529 NOTREACHED();
530 }
532 return result;
533 }
534 static void Log(const param_type& p, std::wstring* l) {
535 l->append(StringPrintf(L"<LOGFONT>"));
536 }
537 };
539 template <>
540 struct ParamTraitsWindows<MSG> {
541 typedef MSG param_type;
542 static void Write(Message* m, const param_type& p) {
543 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
544 }
545 static bool Read(const Message* m, void** iter, param_type* r) {
546 const char *data;
547 int data_size = 0;
548 bool result = m->ReadData(iter, &data, &data_size);
549 if (result && data_size == sizeof(MSG)) {
550 memcpy(r, data, sizeof(MSG));
551 } else {
552 result = false;
553 NOTREACHED();
554 }
556 return result;
557 }
558 };
560 template <>
561 struct ParamTraitsWindows<HANDLE> {
562 typedef HANDLE param_type;
563 static void Write(Message* m, const param_type& p) {
564 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
565 }
566 static bool Read(const Message* m, void** iter, param_type* r) {
567 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
568 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
569 }
570 static void Log(const param_type& p, std::wstring* l) {
571 l->append(StringPrintf(L"0x%X", p));
572 }
573 };
575 template <>
576 struct ParamTraitsWindows<HCURSOR> {
577 typedef HCURSOR param_type;
578 static void Write(Message* m, const param_type& p) {
579 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
580 }
581 static bool Read(const Message* m, void** iter, param_type* r) {
582 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
583 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
584 }
585 static void Log(const param_type& p, std::wstring* l) {
586 l->append(StringPrintf(L"0x%X", p));
587 }
588 };
590 template <>
591 struct ParamTraitsWindows<HWND> {
592 typedef HWND param_type;
593 static void Write(Message* m, const param_type& p) {
594 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
595 }
596 static bool Read(const Message* m, void** iter, param_type* r) {
597 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
598 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
599 }
600 static void Log(const param_type& p, std::wstring* l) {
601 l->append(StringPrintf(L"0x%X", p));
602 }
603 };
605 template <>
606 struct ParamTraitsWindows<HACCEL> {
607 typedef HACCEL param_type;
608 static void Write(Message* m, const param_type& p) {
609 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
610 }
611 static bool Read(const Message* m, void** iter, param_type* r) {
612 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
613 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
614 }
615 };
617 template <>
618 struct ParamTraitsWindows<POINT> {
619 typedef POINT param_type;
620 static void Write(Message* m, const param_type& p) {
621 m->WriteInt(p.x);
622 m->WriteInt(p.y);
623 }
624 static bool Read(const Message* m, void** iter, param_type* r) {
625 int x, y;
626 if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
627 return false;
628 r->x = x;
629 r->y = y;
630 return true;
631 }
632 static void Log(const param_type& p, std::wstring* l) {
633 l->append(StringPrintf(L"(%d, %d)", p.x, p.y));
634 }
635 };
637 template <>
638 struct ParamTraitsWindows<XFORM> {
639 typedef XFORM param_type;
640 static void Write(Message* m, const param_type& p) {
641 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
642 }
643 static bool Read(const Message* m, void** iter, param_type* r) {
644 const char *data;
645 int data_size = 0;
646 bool result = m->ReadData(iter, &data, &data_size);
647 if (result && data_size == sizeof(XFORM)) {
648 memcpy(r, data, sizeof(XFORM));
649 } else {
650 result = false;
651 NOTREACHED();
652 }
654 return result;
655 }
656 static void Log(const param_type& p, std::wstring* l) {
657 l->append(L"<XFORM>");
658 }
659 };
660 #endif // defined(OS_WIN)
662 // Various ipc/chromium types.
664 template <class P>
665 struct ParamTraitsIPC : ParamTraitsWindows<P> {};
667 template <>
668 struct ParamTraitsIPC<base::Time> {
669 typedef base::Time param_type;
670 static inline void Write(Message* m, const param_type& p);
671 static inline bool Read(const Message* m, void** iter, param_type* r);
672 static inline void Log(const param_type& p, std::wstring* l);
673 };
675 #if defined(OS_POSIX)
676 // FileDescriptors may be serialised over IPC channels on POSIX. On the
677 // receiving side, the FileDescriptor is a valid duplicate of the file
678 // descriptor which was transmitted: *it is not just a copy of the integer like
679 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
680 // this case, the receiving end will see a value of -1. *Zero is a valid file
681 // descriptor*.
682 //
683 // The received file descriptor will have the |auto_close| flag set to true. The
684 // code which handles the message is responsible for taking ownership of it.
685 // File descriptors are OS resources and must be closed when no longer needed.
686 //
687 // When sending a file descriptor, the file descriptor must be valid at the time
688 // of transmission. Since transmission is not synchronous, one should consider
689 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
690 // flag, which causes the file descriptor to be closed after writing.
691 template<>
692 struct ParamTraitsIPC<base::FileDescriptor> {
693 typedef base::FileDescriptor param_type;
694 static void Write(Message* m, const param_type& p) {
695 const bool valid = p.fd >= 0;
696 WriteParam(m, valid);
698 if (valid) {
699 if (!m->WriteFileDescriptor(p)) {
700 NOTREACHED() << "Too many file descriptors for one message!";
701 }
702 }
703 }
704 static bool Read(const Message* m, void** iter, param_type* r) {
705 bool valid;
706 if (!ReadParam(m, iter, &valid))
707 return false;
709 if (!valid) {
710 r->fd = -1;
711 r->auto_close = false;
712 return true;
713 }
715 return m->ReadFileDescriptor(iter, r);
716 }
717 static void Log(const param_type& p, std::wstring* l) {
718 if (p.auto_close) {
719 l->append(StringPrintf(L"FD(%d auto-close)", p.fd));
720 } else {
721 l->append(StringPrintf(L"FD(%d)", p.fd));
722 }
723 }
724 };
725 #endif // defined(OS_POSIX)
727 template <>
728 struct ParamTraitsIPC<FilePath> {
729 typedef FilePath param_type;
730 static void Write(Message* m, const param_type& p);
731 static bool Read(const Message* m, void** iter, param_type* r);
732 static void Log(const param_type& p, std::wstring* l);
733 };
735 struct LogData {
736 std::wstring channel;
737 int32_t routing_id;
738 uint16_t type;
739 std::wstring flags;
740 int64_t sent; // Time that the message was sent (i.e. at Send()).
741 int64_t receive; // Time before it was dispatched (i.e. before calling
742 // OnMessageReceived).
743 int64_t dispatch; // Time after it was dispatched (i.e. after calling
744 // OnMessageReceived).
745 std::wstring message_name;
746 std::wstring params;
747 };
749 template <>
750 struct ParamTraitsIPC<LogData> {
751 typedef LogData param_type;
752 static void Write(Message* m, const param_type& p) {
753 WriteParam(m, p.channel);
754 WriteParam(m, p.routing_id);
755 WriteParam(m, static_cast<int>(p.type));
756 WriteParam(m, p.flags);
757 WriteParam(m, p.sent);
758 WriteParam(m, p.receive);
759 WriteParam(m, p.dispatch);
760 WriteParam(m, p.params);
761 }
762 static bool Read(const Message* m, void** iter, param_type* r) {
763 int type = 0;
764 bool result =
765 ReadParam(m, iter, &r->channel) &&
766 ReadParam(m, iter, &r->routing_id) &&
767 ReadParam(m, iter, &type) &&
768 ReadParam(m, iter, &r->flags) &&
769 ReadParam(m, iter, &r->sent) &&
770 ReadParam(m, iter, &r->receive) &&
771 ReadParam(m, iter, &r->dispatch) &&
772 ReadParam(m, iter, &r->params);
773 r->type = static_cast<uint16_t>(type);
774 return result;
775 }
776 static void Log(const param_type& p, std::wstring* l) {
777 // Doesn't make sense to implement this!
778 }
779 };
781 #if defined(OS_WIN)
782 template<>
783 struct ParamTraitsIPC<TransportDIB::Id> {
784 typedef TransportDIB::Id param_type;
785 static void Write(Message* m, const param_type& p) {
786 WriteParam(m, p.handle);
787 WriteParam(m, p.sequence_num);
788 }
789 static bool Read(const Message* m, void** iter, param_type* r) {
790 return (ReadParam(m, iter, &r->handle) &&
791 ReadParam(m, iter, &r->sequence_num));
792 }
793 static void Log(const param_type& p, std::wstring* l) {
794 l->append(L"TransportDIB(");
795 LogParam(p.handle, l);
796 l->append(L", ");
797 LogParam(p.sequence_num, l);
798 l->append(L")");
799 }
800 };
801 #endif
803 template <>
804 struct ParamTraitsIPC<Message> {
805 static void Write(Message* m, const Message& p) {
806 m->WriteInt(p.size());
807 m->WriteData(reinterpret_cast<const char*>(p.data()), p.size());
808 }
809 static bool Read(const Message* m, void** iter, Message* r) {
810 int size;
811 if (!m->ReadInt(iter, &size))
812 return false;
813 const char* data;
814 if (!m->ReadData(iter, &data, &size))
815 return false;
816 *r = Message(data, size);
817 return true;
818 }
819 static void Log(const Message& p, std::wstring* l) {
820 l->append(L"<IPC::Message>");
821 }
822 };
824 template <>
825 struct ParamTraitsIPC<Tuple0> {
826 typedef Tuple0 param_type;
827 static void Write(Message* m, const param_type& p) {
828 }
829 static bool Read(const Message* m, void** iter, param_type* r) {
830 return true;
831 }
832 static void Log(const param_type& p, std::wstring* l) {
833 }
834 };
836 template <class A>
837 struct ParamTraitsIPC< Tuple1<A> > {
838 typedef Tuple1<A> param_type;
839 static void Write(Message* m, const param_type& p) {
840 WriteParam(m, p.a);
841 }
842 static bool Read(const Message* m, void** iter, param_type* r) {
843 return ReadParam(m, iter, &r->a);
844 }
845 static void Log(const param_type& p, std::wstring* l) {
846 LogParam(p.a, l);
847 }
848 };
850 template <class A, class B>
851 struct ParamTraitsIPC< Tuple2<A, B> > {
852 typedef Tuple2<A, B> param_type;
853 static void Write(Message* m, const param_type& p) {
854 WriteParam(m, p.a);
855 WriteParam(m, p.b);
856 }
857 static bool Read(const Message* m, void** iter, param_type* r) {
858 return (ReadParam(m, iter, &r->a) &&
859 ReadParam(m, iter, &r->b));
860 }
861 static void Log(const param_type& p, std::wstring* l) {
862 LogParam(p.a, l);
863 l->append(L", ");
864 LogParam(p.b, l);
865 }
866 };
868 template <class A, class B, class C>
869 struct ParamTraitsIPC< Tuple3<A, B, C> > {
870 typedef Tuple3<A, B, C> param_type;
871 static void Write(Message* m, const param_type& p) {
872 WriteParam(m, p.a);
873 WriteParam(m, p.b);
874 WriteParam(m, p.c);
875 }
876 static bool Read(const Message* m, void** iter, param_type* r) {
877 return (ReadParam(m, iter, &r->a) &&
878 ReadParam(m, iter, &r->b) &&
879 ReadParam(m, iter, &r->c));
880 }
881 static void Log(const param_type& p, std::wstring* l) {
882 LogParam(p.a, l);
883 l->append(L", ");
884 LogParam(p.b, l);
885 l->append(L", ");
886 LogParam(p.c, l);
887 }
888 };
890 template <class A, class B, class C, class D>
891 struct ParamTraitsIPC< Tuple4<A, B, C, D> > {
892 typedef Tuple4<A, B, C, D> param_type;
893 static void Write(Message* m, const param_type& p) {
894 WriteParam(m, p.a);
895 WriteParam(m, p.b);
896 WriteParam(m, p.c);
897 WriteParam(m, p.d);
898 }
899 static bool Read(const Message* m, void** iter, param_type* r) {
900 return (ReadParam(m, iter, &r->a) &&
901 ReadParam(m, iter, &r->b) &&
902 ReadParam(m, iter, &r->c) &&
903 ReadParam(m, iter, &r->d));
904 }
905 static void Log(const param_type& p, std::wstring* l) {
906 LogParam(p.a, l);
907 l->append(L", ");
908 LogParam(p.b, l);
909 l->append(L", ");
910 LogParam(p.c, l);
911 l->append(L", ");
912 LogParam(p.d, l);
913 }
914 };
916 template <class A, class B, class C, class D, class E>
917 struct ParamTraitsIPC< Tuple5<A, B, C, D, E> > {
918 typedef Tuple5<A, B, C, D, E> param_type;
919 static void Write(Message* m, const param_type& p) {
920 WriteParam(m, p.a);
921 WriteParam(m, p.b);
922 WriteParam(m, p.c);
923 WriteParam(m, p.d);
924 WriteParam(m, p.e);
925 }
926 static bool Read(const Message* m, void** iter, param_type* r) {
927 return (ReadParam(m, iter, &r->a) &&
928 ReadParam(m, iter, &r->b) &&
929 ReadParam(m, iter, &r->c) &&
930 ReadParam(m, iter, &r->d) &&
931 ReadParam(m, iter, &r->e));
932 }
933 static void Log(const param_type& p, std::wstring* l) {
934 LogParam(p.a, l);
935 l->append(L", ");
936 LogParam(p.b, l);
937 l->append(L", ");
938 LogParam(p.c, l);
939 l->append(L", ");
940 LogParam(p.d, l);
941 l->append(L", ");
942 LogParam(p.e, l);
943 }
944 };
946 template <class A, class B, class C, class D, class E, class F>
947 struct ParamTraitsIPC< Tuple6<A, B, C, D, E, F> > {
948 typedef Tuple6<A, B, C, D, E, F> param_type;
949 static void Write(Message* m, const param_type& p) {
950 WriteParam(m, p.a);
951 WriteParam(m, p.b);
952 WriteParam(m, p.c);
953 WriteParam(m, p.d);
954 WriteParam(m, p.e);
955 WriteParam(m, p.f);
956 }
957 static bool Read(const Message* m, void** iter, param_type* r) {
958 return (ReadParam(m, iter, &r->a) &&
959 ReadParam(m, iter, &r->b) &&
960 ReadParam(m, iter, &r->c) &&
961 ReadParam(m, iter, &r->d) &&
962 ReadParam(m, iter, &r->e) &&
963 ReadParam(m, iter, &r->f));
964 }
965 static void Log(const param_type& p, std::wstring* l) {
966 LogParam(p.a, l);
967 l->append(L", ");
968 LogParam(p.b, l);
969 l->append(L", ");
970 LogParam(p.c, l);
971 l->append(L", ");
972 LogParam(p.d, l);
973 l->append(L", ");
974 LogParam(p.e, l);
975 l->append(L", ");
976 LogParam(p.f, l);
977 }
978 };
980 // Mozilla-specific types.
982 template <class P>
983 struct ParamTraitsMozilla : ParamTraitsIPC<P> {};
985 template <>
986 struct ParamTraitsMozilla<nsresult> {
987 typedef nsresult param_type;
988 static void Write(Message* m, const param_type& p) {
989 m->WriteUInt32(static_cast<uint32_t>(p));
990 }
991 static bool Read(const Message* m, void** iter, param_type* r) {
992 return m->ReadUInt32(iter, reinterpret_cast<uint32_t*>(r));
993 }
994 static void Log(const param_type& p, std::wstring* l) {
995 l->append(StringPrintf(L"%u", static_cast<uint32_t>(p)));
996 }
997 };
999 // Finally, ParamTraits itself.
1001 template <class P> struct ParamTraits : ParamTraitsMozilla<P> {};
1003 // Now go back and define inlines dependent upon various ParamTraits<P>.
1004 inline void
1005 ParamTraitsIPC<base::Time>::Write(Message* m, const param_type& p) {
1006 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
1007 }
1008 inline bool
1009 ParamTraitsIPC<base::Time>::Read(const Message* m, void** iter, param_type* r) {
1010 int64_t value;
1011 if (!ParamTraits<int64_t>::Read(m, iter, &value))
1012 return false;
1013 *r = base::Time::FromInternalValue(value);
1014 return true;
1015 }
1016 inline void
1017 ParamTraitsIPC<base::Time>::Log(const param_type& p, std::wstring* l) {
1018 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
1019 }
1021 inline void
1022 ParamTraitsIPC<FilePath>::Write(Message* m, const param_type& p) {
1023 ParamTraits<FilePath::StringType>::Write(m, p.value());
1024 }
1025 inline bool
1026 ParamTraitsIPC<FilePath>::Read(const Message* m, void** iter, param_type* r) {
1027 FilePath::StringType value;
1028 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
1029 return false;
1030 *r = FilePath(value);
1031 return true;
1032 }
1033 inline void
1034 ParamTraitsIPC<FilePath>::Log(const param_type& p, std::wstring* l) {
1035 ParamTraits<FilePath::StringType>::Log(p.value(), l);
1036 }
1038 //-----------------------------------------------------------------------------
1039 // Generic message subclasses
1041 // Used for asynchronous messages.
1042 template <class ParamType>
1043 class MessageWithTuple : public Message {
1044 public:
1045 typedef ParamType Param;
1047 MessageWithTuple(int32_t routing_id, uint16_t type, const Param& p)
1048 : Message(routing_id, type, PRIORITY_NORMAL) {
1049 WriteParam(this, p);
1050 }
1052 static bool Read(const Message* msg, Param* p) {
1053 void* iter = NULL;
1054 bool rv = ReadParam(msg, &iter, p);
1055 DCHECK(rv) << "Error deserializing message " << msg->type();
1056 return rv;
1057 }
1059 // Generic dispatcher. Should cover most cases.
1060 template<class T, class Method>
1061 static bool Dispatch(const Message* msg, T* obj, Method func) {
1062 Param p;
1063 if (Read(msg, &p)) {
1064 DispatchToMethod(obj, func, p);
1065 return true;
1066 }
1067 return false;
1068 }
1070 // The following dispatchers exist for the case where the callback function
1071 // needs the message as well. They assume that "Param" is a type of Tuple
1072 // (except the one arg case, as there is no Tuple1).
1073 template<class T, typename TA>
1074 static bool Dispatch(const Message* msg, T* obj,
1075 void (T::*func)(const Message&, TA)) {
1076 Param p;
1077 if (Read(msg, &p)) {
1078 (obj->*func)(*msg, p);
1079 return true;
1080 }
1081 return false;
1082 }
1084 template<class T, typename TA, typename TB>
1085 static bool Dispatch(const Message* msg, T* obj,
1086 void (T::*func)(const Message&, TA, TB)) {
1087 Param p;
1088 if (Read(msg, &p)) {
1089 (obj->*func)(*msg, p.a, p.b);
1090 return true;
1091 }
1092 return false;
1093 }
1095 template<class T, typename TA, typename TB, typename TC>
1096 static bool Dispatch(const Message* msg, T* obj,
1097 void (T::*func)(const Message&, TA, TB, TC)) {
1098 Param p;
1099 if (Read(msg, &p)) {
1100 (obj->*func)(*msg, p.a, p.b, p.c);
1101 return true;
1102 }
1103 return false;
1104 }
1106 template<class T, typename TA, typename TB, typename TC, typename TD>
1107 static bool Dispatch(const Message* msg, T* obj,
1108 void (T::*func)(const Message&, TA, TB, TC, TD)) {
1109 Param p;
1110 if (Read(msg, &p)) {
1111 (obj->*func)(*msg, p.a, p.b, p.c, p.d);
1112 return true;
1113 }
1114 return false;
1115 }
1117 template<class T, typename TA, typename TB, typename TC, typename TD,
1118 typename TE>
1119 static bool Dispatch(const Message* msg, T* obj,
1120 void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
1121 Param p;
1122 if (Read(msg, &p)) {
1123 (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
1124 return true;
1125 }
1126 return false;
1127 }
1129 static void Log(const Message* msg, std::wstring* l) {
1130 Param p;
1131 if (Read(msg, &p))
1132 LogParam(p, l);
1133 }
1135 // Functions used to do manual unpacking. Only used by the automation code,
1136 // these should go away once that code uses SyncChannel.
1137 template<typename TA, typename TB>
1138 static bool Read(const IPC::Message* msg, TA* a, TB* b) {
1139 ParamType params;
1140 if (!Read(msg, ¶ms))
1141 return false;
1142 *a = params.a;
1143 *b = params.b;
1144 return true;
1145 }
1147 template<typename TA, typename TB, typename TC>
1148 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
1149 ParamType params;
1150 if (!Read(msg, ¶ms))
1151 return false;
1152 *a = params.a;
1153 *b = params.b;
1154 *c = params.c;
1155 return true;
1156 }
1158 template<typename TA, typename TB, typename TC, typename TD>
1159 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
1160 ParamType params;
1161 if (!Read(msg, ¶ms))
1162 return false;
1163 *a = params.a;
1164 *b = params.b;
1165 *c = params.c;
1166 *d = params.d;
1167 return true;
1168 }
1170 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1171 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
1172 ParamType params;
1173 if (!Read(msg, ¶ms))
1174 return false;
1175 *a = params.a;
1176 *b = params.b;
1177 *c = params.c;
1178 *d = params.d;
1179 *e = params.e;
1180 return true;
1181 }
1182 };
1184 // This class assumes that its template argument is a RefTuple (a Tuple with
1185 // reference elements).
1186 template <class RefTuple>
1187 class ParamDeserializer : public MessageReplyDeserializer {
1188 public:
1189 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
1191 bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
1192 return ReadParam(&msg, &iter, &out_);
1193 }
1195 RefTuple out_;
1196 };
1198 // defined in ipc_logging.cc
1199 void GenerateLogData(const std::wstring& channel, const Message& message,
1200 LogData* data);
1202 // Used for synchronous messages.
1203 template <class SendParamType, class ReplyParamType>
1204 class MessageWithReply : public SyncMessage {
1205 public:
1206 typedef SendParamType SendParam;
1207 typedef ReplyParamType ReplyParam;
1209 MessageWithReply(int32_t routing_id, uint16_t type,
1210 const SendParam& send, const ReplyParam& reply)
1211 : SyncMessage(routing_id, type, PRIORITY_NORMAL,
1212 new ParamDeserializer<ReplyParam>(reply)) {
1213 WriteParam(this, send);
1214 }
1216 static void Log(const Message* msg, std::wstring* l) {
1217 if (msg->is_sync()) {
1218 SendParam p;
1219 void* iter = SyncMessage::GetDataIterator(msg);
1220 if (ReadParam(msg, &iter, &p))
1221 LogParam(p, l);
1223 #if defined(IPC_MESSAGE_LOG_ENABLED)
1224 const std::wstring& output_params = msg->output_params();
1225 if (!l->empty() && !output_params.empty())
1226 l->append(L", ");
1228 l->append(output_params);
1229 #endif
1230 } else {
1231 // This is an outgoing reply. Now that we have the output parameters, we
1232 // can finally log the message.
1233 typename ReplyParam::ValueTuple p;
1234 void* iter = SyncMessage::GetDataIterator(msg);
1235 if (ReadParam(msg, &iter, &p))
1236 LogParam(p, l);
1237 }
1238 }
1240 template<class T, class Method>
1241 static bool Dispatch(const Message* msg, T* obj, Method func) {
1242 SendParam send_params;
1243 void* iter = GetDataIterator(msg);
1244 Message* reply = GenerateReply(msg);
1245 bool error;
1246 if (ReadParam(msg, &iter, &send_params)) {
1247 typename ReplyParam::ValueTuple reply_params;
1248 DispatchToMethod(obj, func, send_params, &reply_params);
1249 WriteParam(reply, reply_params);
1250 error = false;
1251 #ifdef IPC_MESSAGE_LOG_ENABLED
1252 if (msg->received_time() != 0) {
1253 std::wstring output_params;
1254 LogParam(reply_params, &output_params);
1255 msg->set_output_params(output_params);
1256 }
1257 #endif
1258 } else {
1259 NOTREACHED() << "Error deserializing message " << msg->type();
1260 reply->set_reply_error();
1261 error = true;
1262 }
1264 obj->Send(reply);
1265 return !error;
1266 }
1268 template<class T, class Method>
1269 static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
1270 SendParam send_params;
1271 void* iter = GetDataIterator(msg);
1272 Message* reply = GenerateReply(msg);
1273 bool error;
1274 if (ReadParam(msg, &iter, &send_params)) {
1275 Tuple1<Message&> t = MakeRefTuple(*reply);
1277 #ifdef IPC_MESSAGE_LOG_ENABLED
1278 if (msg->sent_time()) {
1279 // Don't log the sync message after dispatch, as we don't have the
1280 // output parameters at that point. Instead, save its data and log it
1281 // with the outgoing reply message when it's sent.
1282 LogData* data = new LogData;
1283 GenerateLogData(L"", *msg, data);
1284 msg->set_dont_log();
1285 reply->set_sync_log_data(data);
1286 }
1287 #endif
1288 DispatchToMethod(obj, func, send_params, &t);
1289 error = false;
1290 } else {
1291 NOTREACHED() << "Error deserializing message " << msg->type();
1292 reply->set_reply_error();
1293 obj->Send(reply);
1294 error = true;
1295 }
1296 return !error;
1297 }
1299 template<typename TA>
1300 static void WriteReplyParams(Message* reply, TA a) {
1301 ReplyParam p(a);
1302 WriteParam(reply, p);
1303 }
1305 template<typename TA, typename TB>
1306 static void WriteReplyParams(Message* reply, TA a, TB b) {
1307 ReplyParam p(a, b);
1308 WriteParam(reply, p);
1309 }
1311 template<typename TA, typename TB, typename TC>
1312 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
1313 ReplyParam p(a, b, c);
1314 WriteParam(reply, p);
1315 }
1317 template<typename TA, typename TB, typename TC, typename TD>
1318 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
1319 ReplyParam p(a, b, c, d);
1320 WriteParam(reply, p);
1321 }
1323 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1324 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
1325 ReplyParam p(a, b, c, d, e);
1326 WriteParam(reply, p);
1327 }
1328 };
1330 //-----------------------------------------------------------------------------
1332 } // namespace IPC
1334 #endif // CHROME_COMMON_IPC_MESSAGE_UTILS_H_