Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(342)

Side by Side Diff: chrome/common/ipc_message_utils.h

Issue 155905: Separates ipc code from common (http://crbug.com/16829) (Closed)
Patch Set: Fixes reference to 'common_message_traits' it's actually 'common_param_traits' Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/common/ipc_message_unittest.cc ('k') | chrome/common/ipc_message_utils.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #ifndef CHROME_COMMON_IPC_MESSAGE_UTILS_H_
6 #define CHROME_COMMON_IPC_MESSAGE_UTILS_H_
7
8 #include <string>
9 #include <vector>
10 #include <map>
11
12 #include "base/file_path.h"
13 #include "base/format_macros.h"
14 #include "base/gfx/native_widget_types.h"
15 #include "base/string16.h"
16 #include "base/string_util.h"
17 #include "base/tuple.h"
18 #if defined(OS_POSIX)
19 #include "chrome/common/file_descriptor_set_posix.h"
20 #endif
21 #include "chrome/common/ipc_channel_handle.h"
22 #include "chrome/common/ipc_sync_message.h"
23 #include "chrome/common/thumbnail_score.h"
24 #include "chrome/common/transport_dib.h"
25 #include "net/url_request/url_request_status.h"
26 #include "webkit/glue/webcursor.h"
27 #include "webkit/glue/window_open_disposition.h"
28
29 // Forward declarations.
30 class GURL;
31 class SkBitmap;
32 class DictionaryValue;
33 class ListValue;
34
35 namespace gfx {
36 class Point;
37 class Rect;
38 class Size;
39 } // namespace gfx
40
41 namespace webkit_glue {
42 struct WebApplicationInfo;
43 } // namespace webkit_glue
44
45 // Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
46 // base. Messages have unique IDs across channels in order for the IPC logging
47 // code to figure out the message class from its ID.
48 enum IPCMessageStart {
49 // By using a start value of 0 for automation messages, we keep backward
50 // compatibility with old builds.
51 AutomationMsgStart = 0,
52 ViewMsgStart,
53 ViewHostMsgStart,
54 PluginProcessMsgStart,
55 PluginProcessHostMsgStart,
56 PluginMsgStart,
57 PluginHostMsgStart,
58 NPObjectMsgStart,
59 TestMsgStart,
60 DevToolsAgentMsgStart,
61 DevToolsClientMsgStart,
62 WorkerProcessMsgStart,
63 WorkerProcessHostMsgStart,
64 WorkerMsgStart,
65 WorkerHostMsgStart,
66 // NOTE: When you add a new message class, also update
67 // IPCStatusView::IPCStatusView to ensure logging works.
68 // NOTE: this enum is used by IPC_MESSAGE_MACRO to generate a unique message
69 // id. Only 4 bits are used for the message type, so if this enum needs more
70 // than 16 entries, that code needs to be updated.
71 LastMsgIndex
72 };
73
74 COMPILE_ASSERT(LastMsgIndex <= 16, need_to_update_IPC_MESSAGE_MACRO);
75
76 namespace IPC {
77
78 //-----------------------------------------------------------------------------
79 // An iterator class for reading the fields contained within a Message.
80
81 class MessageIterator {
82 public:
83 explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
84 }
85 int NextInt() const {
86 int val;
87 if (!msg_.ReadInt(&iter_, &val))
88 NOTREACHED();
89 return val;
90 }
91 intptr_t NextIntPtr() const {
92 intptr_t val;
93 if (!msg_.ReadIntPtr(&iter_, &val))
94 NOTREACHED();
95 return val;
96 }
97 const std::string NextString() const {
98 std::string val;
99 if (!msg_.ReadString(&iter_, &val))
100 NOTREACHED();
101 return val;
102 }
103 const std::wstring NextWString() const {
104 std::wstring val;
105 if (!msg_.ReadWString(&iter_, &val))
106 NOTREACHED();
107 return val;
108 }
109 const void NextData(const char** data, int* length) const {
110 if (!msg_.ReadData(&iter_, data, length)) {
111 NOTREACHED();
112 }
113 }
114 private:
115 const Message& msg_;
116 mutable void* iter_;
117 };
118
119 //-----------------------------------------------------------------------------
120 // ParamTraits specializations, etc.
121
122 template <class P> struct ParamTraits {};
123
124 template <class P>
125 static inline void WriteParam(Message* m, const P& p) {
126 ParamTraits<P>::Write(m, p);
127 }
128
129 template <class P>
130 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
131 P* p) {
132 return ParamTraits<P>::Read(m, iter, p);
133 }
134
135 template <class P>
136 static inline void LogParam(const P& p, std::wstring* l) {
137 ParamTraits<P>::Log(p, l);
138 }
139
140 template <>
141 struct ParamTraits<bool> {
142 typedef bool param_type;
143 static void Write(Message* m, const param_type& p) {
144 m->WriteBool(p);
145 }
146 static bool Read(const Message* m, void** iter, param_type* r) {
147 return m->ReadBool(iter, r);
148 }
149 static void Log(const param_type& p, std::wstring* l) {
150 l->append(p ? L"true" : L"false");
151 }
152 };
153
154 template <>
155 struct ParamTraits<int> {
156 typedef int param_type;
157 static void Write(Message* m, const param_type& p) {
158 m->WriteInt(p);
159 }
160 static bool Read(const Message* m, void** iter, param_type* r) {
161 return m->ReadInt(iter, r);
162 }
163 static void Log(const param_type& p, std::wstring* l) {
164 l->append(StringPrintf(L"%d", p));
165 }
166 };
167
168 template <>
169 struct ParamTraits<long> {
170 typedef long param_type;
171 static void Write(Message* m, const param_type& p) {
172 m->WriteLong(p);
173 }
174 static bool Read(const Message* m, void** iter, param_type* r) {
175 return m->ReadLong(iter, r);
176 }
177 static void Log(const param_type& p, std::wstring* l) {
178 l->append(StringPrintf(L"%l", p));
179 }
180 };
181
182 #if defined(OS_LINUX) || defined(OS_WIN)
183 // On Linux, unsigned long is used for serializing X window ids.
184 // On Windows, it's used for serializing process ids.
185 // On Mac, it conflicts with some other definition.
186 template <>
187 struct ParamTraits<unsigned long> {
188 typedef unsigned long param_type;
189 static void Write(Message* m, const param_type& p) {
190 m->WriteLong(p);
191 }
192 static bool Read(const Message* m, void** iter, param_type* r) {
193 long read_output;
194 if (!m->ReadLong(iter, &read_output))
195 return false;
196 *r = static_cast<unsigned long>(read_output);
197 return true;
198 }
199 static void Log(const param_type& p, std::wstring* l) {
200 l->append(StringPrintf(L"%ul", p));
201 }
202 };
203 #endif
204
205 template <>
206 struct ParamTraits<size_t> {
207 typedef size_t param_type;
208 static void Write(Message* m, const param_type& p) {
209 m->WriteSize(p);
210 }
211 static bool Read(const Message* m, void** iter, param_type* r) {
212 return m->ReadSize(iter, r);
213 }
214 static void Log(const param_type& p, std::wstring* l) {
215 l->append(StringPrintf(L"%u", p));
216 }
217 };
218
219 #if defined(OS_MACOSX)
220 // On Linux size_t & uint32 can be the same type.
221 // TODO(playmobil): Fix compilation if this is not the case.
222 template <>
223 struct ParamTraits<uint32> {
224 typedef uint32 param_type;
225 static void Write(Message* m, const param_type& p) {
226 m->WriteUInt32(p);
227 }
228 static bool Read(const Message* m, void** iter, param_type* r) {
229 return m->ReadUInt32(iter, r);
230 }
231 static void Log(const param_type& p, std::wstring* l) {
232 l->append(StringPrintf(L"%u", p));
233 }
234 };
235 #endif // defined(OS_MACOSX)
236
237 template <>
238 struct ParamTraits<int64> {
239 typedef int64 param_type;
240 static void Write(Message* m, const param_type& p) {
241 m->WriteInt64(p);
242 }
243 static bool Read(const Message* m, void** iter, param_type* r) {
244 return m->ReadInt64(iter, r);
245 }
246 static void Log(const param_type& p, std::wstring* l) {
247 l->append(StringPrintf(L"%" WidePRId64, p));
248 }
249 };
250
251 template <>
252 struct ParamTraits<uint64> {
253 typedef uint64 param_type;
254 static void Write(Message* m, const param_type& p) {
255 m->WriteInt64(static_cast<int64>(p));
256 }
257 static bool Read(const Message* m, void** iter, param_type* r) {
258 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
259 }
260 static void Log(const param_type& p, std::wstring* l) {
261 l->append(StringPrintf(L"%" WidePRId64, p));
262 }
263 };
264
265 template <>
266 struct ParamTraits<double> {
267 typedef double param_type;
268 static void Write(Message* m, const param_type& p) {
269 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
270 }
271 static bool Read(const Message* m, void** iter, param_type* r) {
272 const char *data;
273 int data_size = 0;
274 bool result = m->ReadData(iter, &data, &data_size);
275 if (result && data_size == sizeof(param_type)) {
276 memcpy(r, data, sizeof(param_type));
277 } else {
278 result = false;
279 NOTREACHED();
280 }
281
282 return result;
283 }
284 static void Log(const param_type& p, std::wstring* l) {
285 l->append(StringPrintf(L"e", p));
286 }
287 };
288
289 template <>
290 struct ParamTraits<wchar_t> {
291 typedef wchar_t param_type;
292 static void Write(Message* m, const param_type& p) {
293 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
294 }
295 static bool Read(const Message* m, void** iter, param_type* r) {
296 const char *data;
297 int data_size = 0;
298 bool result = m->ReadData(iter, &data, &data_size);
299 if (result && data_size == sizeof(param_type)) {
300 memcpy(r, data, sizeof(param_type));
301 } else {
302 result = false;
303 NOTREACHED();
304 }
305
306 return result;
307 }
308 static void Log(const param_type& p, std::wstring* l) {
309 l->append(StringPrintf(L"%lc", p));
310 }
311 };
312
313 template <>
314 struct ParamTraits<base::Time> {
315 typedef base::Time param_type;
316 static void Write(Message* m, const param_type& p) {
317 ParamTraits<int64>::Write(m, p.ToInternalValue());
318 }
319 static bool Read(const Message* m, void** iter, param_type* r) {
320 int64 value;
321 if (!ParamTraits<int64>::Read(m, iter, &value))
322 return false;
323 *r = base::Time::FromInternalValue(value);
324 return true;
325 }
326 static void Log(const param_type& p, std::wstring* l) {
327 ParamTraits<int64>::Log(p.ToInternalValue(), l);
328 }
329 };
330
331 #if defined(OS_WIN)
332 template <>
333 struct ParamTraits<LOGFONT> {
334 typedef LOGFONT param_type;
335 static void Write(Message* m, const param_type& p) {
336 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
337 }
338 static bool Read(const Message* m, void** iter, param_type* r) {
339 const char *data;
340 int data_size = 0;
341 bool result = m->ReadData(iter, &data, &data_size);
342 if (result && data_size == sizeof(LOGFONT)) {
343 memcpy(r, data, sizeof(LOGFONT));
344 } else {
345 result = false;
346 NOTREACHED();
347 }
348
349 return result;
350 }
351 static void Log(const param_type& p, std::wstring* l) {
352 l->append(StringPrintf(L"<LOGFONT>"));
353 }
354 };
355
356 template <>
357 struct ParamTraits<MSG> {
358 typedef MSG param_type;
359 static void Write(Message* m, const param_type& p) {
360 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
361 }
362 static bool Read(const Message* m, void** iter, param_type* r) {
363 const char *data;
364 int data_size = 0;
365 bool result = m->ReadData(iter, &data, &data_size);
366 if (result && data_size == sizeof(MSG)) {
367 memcpy(r, data, sizeof(MSG));
368 } else {
369 result = false;
370 NOTREACHED();
371 }
372
373 return result;
374 }
375 };
376 #endif // defined(OS_WIN)
377
378 template <>
379 struct ParamTraits<SkBitmap> {
380 typedef SkBitmap param_type;
381 static void Write(Message* m, const param_type& p);
382
383 // Note: This function expects parameter |r| to be of type &SkBitmap since
384 // r->SetConfig() and r->SetPixels() are called.
385 static bool Read(const Message* m, void** iter, param_type* r);
386
387 static void Log(const param_type& p, std::wstring* l);
388 };
389
390 template <>
391 struct ParamTraits<DictionaryValue> {
392 typedef DictionaryValue param_type;
393 static void Write(Message* m, const param_type& p);
394 static bool Read(const Message* m, void** iter, param_type* r);
395 static void Log(const param_type& p, std::wstring* l);
396 };
397
398 template <>
399 struct ParamTraits<ListValue> {
400 typedef ListValue param_type;
401 static void Write(Message* m, const param_type& p);
402 static bool Read(const Message* m, void** iter, param_type* r);
403 static void Log(const param_type& p, std::wstring* l);
404 };
405
406 template <>
407 struct ParamTraits<std::string> {
408 typedef std::string param_type;
409 static void Write(Message* m, const param_type& p) {
410 m->WriteString(p);
411 }
412 static bool Read(const Message* m, void** iter, param_type* r) {
413 return m->ReadString(iter, r);
414 }
415 static void Log(const param_type& p, std::wstring* l) {
416 l->append(UTF8ToWide(p));
417 }
418 };
419
420 template <>
421 struct ParamTraits<std::vector<unsigned char> > {
422 typedef std::vector<unsigned char> param_type;
423 static void Write(Message* m, const param_type& p) {
424 if (p.size() == 0) {
425 m->WriteData(NULL, 0);
426 } else {
427 m->WriteData(reinterpret_cast<const char*>(&p.front()),
428 static_cast<int>(p.size()));
429 }
430 }
431 static bool Read(const Message* m, void** iter, param_type* r) {
432 const char *data;
433 int data_size = 0;
434 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
435 return false;
436 r->resize(data_size);
437 if (data_size)
438 memcpy(&r->front(), data, data_size);
439 return true;
440 }
441 static void Log(const param_type& p, std::wstring* l) {
442 for (size_t i = 0; i < p.size(); ++i)
443 l->push_back(p[i]);
444 }
445 };
446
447 template <>
448 struct ParamTraits<std::vector<char> > {
449 typedef std::vector<char> param_type;
450 static void Write(Message* m, const param_type& p) {
451 if (p.size() == 0) {
452 m->WriteData(NULL, 0);
453 } else {
454 m->WriteData(&p.front(), static_cast<int>(p.size()));
455 }
456 }
457 static bool Read(const Message* m, void** iter, param_type* r) {
458 const char *data;
459 int data_size = 0;
460 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
461 return false;
462 r->resize(data_size);
463 if (data_size)
464 memcpy(&r->front(), data, data_size);
465 return true;
466 }
467 static void Log(const param_type& p, std::wstring* l) {
468 for (size_t i = 0; i < p.size(); ++i)
469 l->push_back(p[i]);
470 }
471 };
472
473 template <class P>
474 struct ParamTraits<std::vector<P> > {
475 typedef std::vector<P> param_type;
476 static void Write(Message* m, const param_type& p) {
477 WriteParam(m, static_cast<int>(p.size()));
478 for (size_t i = 0; i < p.size(); i++)
479 WriteParam(m, p[i]);
480 }
481 static bool Read(const Message* m, void** iter, param_type* r) {
482 int size;
483 if (!m->ReadLength(iter, &size))
484 return false;
485 // Resizing beforehand is not safe, see BUG 1006367 for details.
486 if (m->IteratorHasRoomFor(*iter, size * sizeof(P))) {
487 r->resize(size);
488 for (int i = 0; i < size; i++) {
489 if (!ReadParam(m, iter, &(*r)[i]))
490 return false;
491 }
492 } else {
493 for (int i = 0; i < size; i++) {
494 P element;
495 if (!ReadParam(m, iter, &element))
496 return false;
497 r->push_back(element);
498 }
499 }
500 return true;
501 }
502 static void Log(const param_type& p, std::wstring* l) {
503 for (size_t i = 0; i < p.size(); ++i) {
504 if (i != 0)
505 l->append(L" ");
506
507 LogParam((p[i]), l);
508 }
509 }
510 };
511
512 template <class K, class V>
513 struct ParamTraits<std::map<K, V> > {
514 typedef std::map<K, V> param_type;
515 static void Write(Message* m, const param_type& p) {
516 WriteParam(m, static_cast<int>(p.size()));
517 typename param_type::const_iterator iter;
518 for (iter = p.begin(); iter != p.end(); ++iter) {
519 WriteParam(m, iter->first);
520 WriteParam(m, iter->second);
521 }
522 }
523 static bool Read(const Message* m, void** iter, param_type* r) {
524 int size;
525 if (!ReadParam(m, iter, &size) || size < 0)
526 return false;
527 for (int i = 0; i < size; ++i) {
528 K k;
529 if (!ReadParam(m, iter, &k))
530 return false;
531 V& value = (*r)[k];
532 if (!ReadParam(m, iter, &value))
533 return false;
534 }
535 return true;
536 }
537 static void Log(const param_type& p, std::wstring* l) {
538 l->append(L"<std::map>");
539 }
540 };
541
542
543 template <>
544 struct ParamTraits<std::wstring> {
545 typedef std::wstring param_type;
546 static void Write(Message* m, const param_type& p) {
547 m->WriteWString(p);
548 }
549 static bool Read(const Message* m, void** iter, param_type* r) {
550 return m->ReadWString(iter, r);
551 }
552 static void Log(const param_type& p, std::wstring* l) {
553 l->append(p);
554 }
555 };
556
557 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
558 // need this trait.
559 #if !defined(WCHAR_T_IS_UTF16)
560 template <>
561 struct ParamTraits<string16> {
562 typedef string16 param_type;
563 static void Write(Message* m, const param_type& p) {
564 m->WriteString16(p);
565 }
566 static bool Read(const Message* m, void** iter, param_type* r) {
567 return m->ReadString16(iter, r);
568 }
569 static void Log(const param_type& p, std::wstring* l) {
570 l->append(UTF16ToWide(p));
571 }
572 };
573 #endif
574
575 template <>
576 struct ParamTraits<GURL> {
577 typedef GURL param_type;
578 static void Write(Message* m, const param_type& p);
579 static bool Read(const Message* m, void** iter, param_type* p);
580 static void Log(const param_type& p, std::wstring* l);
581 };
582
583 // and, a few more useful types...
584 #if defined(OS_WIN)
585 template <>
586 struct ParamTraits<HANDLE> {
587 typedef HANDLE param_type;
588 static void Write(Message* m, const param_type& p) {
589 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
590 }
591 static bool Read(const Message* m, void** iter, param_type* r) {
592 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
593 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
594 }
595 static void Log(const param_type& p, std::wstring* l) {
596 l->append(StringPrintf(L"0x%X", p));
597 }
598 };
599
600 template <>
601 struct ParamTraits<HCURSOR> {
602 typedef HCURSOR param_type;
603 static void Write(Message* m, const param_type& p) {
604 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
605 }
606 static bool Read(const Message* m, void** iter, param_type* r) {
607 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
608 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
609 }
610 static void Log(const param_type& p, std::wstring* l) {
611 l->append(StringPrintf(L"0x%X", p));
612 }
613 };
614
615 template <>
616 struct ParamTraits<HACCEL> {
617 typedef HACCEL param_type;
618 static void Write(Message* m, const param_type& p) {
619 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
620 }
621 static bool Read(const Message* m, void** iter, param_type* r) {
622 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
623 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
624 }
625 };
626
627 template <>
628 struct ParamTraits<POINT> {
629 typedef POINT param_type;
630 static void Write(Message* m, const param_type& p) {
631 m->WriteInt(p.x);
632 m->WriteInt(p.y);
633 }
634 static bool Read(const Message* m, void** iter, param_type* r) {
635 int x, y;
636 if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
637 return false;
638 r->x = x;
639 r->y = y;
640 return true;
641 }
642 static void Log(const param_type& p, std::wstring* l) {
643 l->append(StringPrintf(L"(%d, %d)", p.x, p.y));
644 }
645 };
646 #endif // defined(OS_WIN)
647
648 template <>
649 struct ParamTraits<FilePath> {
650 typedef FilePath param_type;
651 static void Write(Message* m, const param_type& p) {
652 ParamTraits<FilePath::StringType>::Write(m, p.value());
653 }
654 static bool Read(const Message* m, void** iter, param_type* r) {
655 FilePath::StringType value;
656 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
657 return false;
658 *r = FilePath(value);
659 return true;
660 }
661 static void Log(const param_type& p, std::wstring* l) {
662 ParamTraits<FilePath::StringType>::Log(p.value(), l);
663 }
664 };
665
666 template <>
667 struct ParamTraits<gfx::Point> {
668 typedef gfx::Point param_type;
669 static void Write(Message* m, const param_type& p);
670 static bool Read(const Message* m, void** iter, param_type* r);
671 static void Log(const param_type& p, std::wstring* l);
672 };
673
674 template <>
675 struct ParamTraits<gfx::Rect> {
676 typedef gfx::Rect param_type;
677 static void Write(Message* m, const param_type& p);
678 static bool Read(const Message* m, void** iter, param_type* r);
679 static void Log(const param_type& p, std::wstring* l);
680 };
681
682 template <>
683 struct ParamTraits<gfx::Size> {
684 typedef gfx::Size param_type;
685 static void Write(Message* m, const param_type& p);
686 static bool Read(const Message* m, void** iter, param_type* r);
687 static void Log(const param_type& p, std::wstring* l);
688 };
689
690 template <>
691 struct ParamTraits<gfx::NativeWindow> {
692 typedef gfx::NativeWindow param_type;
693 static void Write(Message* m, const param_type& p) {
694 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
695 }
696 static bool Read(const Message* m, void** iter, param_type* r) {
697 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
698 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
699 }
700 static void Log(const param_type& p, std::wstring* l) {
701 l->append(StringPrintf(L"0x%X", p));
702 }
703 };
704
705 #if defined(OS_POSIX)
706 // FileDescriptors may be serialised over IPC channels on POSIX. On the
707 // receiving side, the FileDescriptor is a valid duplicate of the file
708 // descriptor which was transmitted: *it is not just a copy of the integer like
709 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
710 // this case, the receiving end will see a value of -1. *Zero is a valid file
711 // descriptor*.
712 //
713 // The received file descriptor will have the |auto_close| flag set to true. The
714 // code which handles the message is responsible for taking ownership of it.
715 // File descriptors are OS resources and must be closed when no longer needed.
716 //
717 // When sending a file descriptor, the file descriptor must be valid at the time
718 // of transmission. Since transmission is not synchronous, one should consider
719 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
720 // flag, which causes the file descriptor to be closed after writing.
721 template<>
722 struct ParamTraits<base::FileDescriptor> {
723 typedef base::FileDescriptor param_type;
724 static void Write(Message* m, const param_type& p) {
725 const bool valid = p.fd >= 0;
726 WriteParam(m, valid);
727
728 if (valid) {
729 if (!m->WriteFileDescriptor(p))
730 NOTREACHED();
731 }
732 }
733 static bool Read(const Message* m, void** iter, param_type* r) {
734 bool valid;
735 if (!ReadParam(m, iter, &valid))
736 return false;
737
738 if (!valid) {
739 r->fd = -1;
740 r->auto_close = false;
741 return true;
742 }
743
744 return m->ReadFileDescriptor(iter, r);
745 }
746 static void Log(const param_type& p, std::wstring* l) {
747 if (p.auto_close) {
748 l->append(StringPrintf(L"FD(%d auto-close)", p.fd));
749 } else {
750 l->append(StringPrintf(L"FD(%d)", p.fd));
751 }
752 }
753 };
754 #endif // defined(OS_POSIX)
755
756 // A ChannelHandle is basically a platform-inspecific wrapper around the
757 // fact that IPC endpoints are handled specially on POSIX. See above comments
758 // on FileDescriptor for more background.
759 template<>
760 struct ParamTraits<IPC::ChannelHandle> {
761 typedef ChannelHandle param_type;
762 static void Write(Message* m, const param_type& p) {
763 WriteParam(m, p.name);
764 #if defined(OS_POSIX)
765 WriteParam(m, p.socket);
766 #endif
767 }
768 static bool Read(const Message* m, void** iter, param_type* r) {
769 return ReadParam(m, iter, &r->name)
770 #if defined(OS_POSIX)
771 && ReadParam(m, iter, &r->socket)
772 #endif
773 ;
774 }
775 static void Log(const param_type& p, std::wstring* l) {
776 l->append(ASCIIToWide(StringPrintf("ChannelHandle(%s", p.name.c_str())));
777 #if defined(OS_POSIX)
778 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
779 #endif
780 l->append(L")");
781 }
782 };
783
784 template<>
785 struct ParamTraits<ThumbnailScore> {
786 typedef ThumbnailScore param_type;
787 static void Write(Message* m, const param_type& p) {
788 IPC::ParamTraits<double>::Write(m, p.boring_score);
789 IPC::ParamTraits<bool>::Write(m, p.good_clipping);
790 IPC::ParamTraits<bool>::Write(m, p.at_top);
791 IPC::ParamTraits<base::Time>::Write(m, p.time_at_snapshot);
792 }
793 static bool Read(const Message* m, void** iter, param_type* r) {
794 double boring_score;
795 bool good_clipping, at_top;
796 base::Time time_at_snapshot;
797 if (!IPC::ParamTraits<double>::Read(m, iter, &boring_score) ||
798 !IPC::ParamTraits<bool>::Read(m, iter, &good_clipping) ||
799 !IPC::ParamTraits<bool>::Read(m, iter, &at_top) ||
800 !IPC::ParamTraits<base::Time>::Read(m, iter, &time_at_snapshot))
801 return false;
802
803 r->boring_score = boring_score;
804 r->good_clipping = good_clipping;
805 r->at_top = at_top;
806 r->time_at_snapshot = time_at_snapshot;
807 return true;
808 }
809 static void Log(const param_type& p, std::wstring* l) {
810 l->append(StringPrintf(L"(%f, %d, %d)",
811 p.boring_score, p.good_clipping, p.at_top));
812 }
813 };
814
815 template <>
816 struct ParamTraits<WindowOpenDisposition> {
817 typedef WindowOpenDisposition param_type;
818 static void Write(Message* m, const param_type& p) {
819 m->WriteInt(p);
820 }
821 static bool Read(const Message* m, void** iter, param_type* r) {
822 int temp;
823 bool res = m->ReadInt(iter, &temp);
824 *r = static_cast<WindowOpenDisposition>(temp);
825 return res;
826 }
827 static void Log(const param_type& p, std::wstring* l) {
828 l->append(StringPrintf(L"%d", p));
829 }
830 };
831
832 #if defined(OS_WIN)
833 template <>
834 struct ParamTraits<XFORM> {
835 typedef XFORM param_type;
836 static void Write(Message* m, const param_type& p) {
837 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
838 }
839 static bool Read(const Message* m, void** iter, param_type* r) {
840 const char *data;
841 int data_size = 0;
842 bool result = m->ReadData(iter, &data, &data_size);
843 if (result && data_size == sizeof(XFORM)) {
844 memcpy(r, data, sizeof(XFORM));
845 } else {
846 result = false;
847 NOTREACHED();
848 }
849
850 return result;
851 }
852 static void Log(const param_type& p, std::wstring* l) {
853 l->append(L"<XFORM>");
854 }
855 };
856 #endif // defined(OS_WIN)
857
858 template <>
859 struct ParamTraits<WebCursor> {
860 typedef WebCursor param_type;
861 static void Write(Message* m, const param_type& p) {
862 p.Serialize(m);
863 }
864 static bool Read(const Message* m, void** iter, param_type* r) {
865 return r->Deserialize(m, iter);
866 }
867 static void Log(const param_type& p, std::wstring* l) {
868 l->append(L"<WebCursor>");
869 }
870 };
871
872 struct LogData {
873 std::string channel;
874 int32 routing_id;
875 uint16 type;
876 std::wstring flags;
877 int64 sent; // Time that the message was sent (i.e. at Send()).
878 int64 receive; // Time before it was dispatched (i.e. before calling
879 // OnMessageReceived).
880 int64 dispatch; // Time after it was dispatched (i.e. after calling
881 // OnMessageReceived).
882 std::wstring message_name;
883 std::wstring params;
884 };
885
886 template <>
887 struct ParamTraits<LogData> {
888 typedef LogData param_type;
889 static void Write(Message* m, const param_type& p) {
890 WriteParam(m, p.channel);
891 WriteParam(m, p.routing_id);
892 WriteParam(m, static_cast<int>(p.type));
893 WriteParam(m, p.flags);
894 WriteParam(m, p.sent);
895 WriteParam(m, p.receive);
896 WriteParam(m, p.dispatch);
897 WriteParam(m, p.params);
898 }
899 static bool Read(const Message* m, void** iter, param_type* r) {
900 int type;
901 bool result =
902 ReadParam(m, iter, &r->channel) &&
903 ReadParam(m, iter, &r->routing_id);
904 ReadParam(m, iter, &type) &&
905 ReadParam(m, iter, &r->flags) &&
906 ReadParam(m, iter, &r->sent) &&
907 ReadParam(m, iter, &r->receive) &&
908 ReadParam(m, iter, &r->dispatch) &&
909 ReadParam(m, iter, &r->params);
910 r->type = static_cast<uint16>(type);
911 return result;
912 }
913 static void Log(const param_type& p, std::wstring* l) {
914 // Doesn't make sense to implement this!
915 }
916 };
917
918
919 template <>
920 struct ParamTraits<webkit_glue::WebApplicationInfo> {
921 typedef webkit_glue::WebApplicationInfo param_type;
922 static void Write(Message* m, const param_type& p);
923 static bool Read(const Message* m, void** iter, param_type* r);
924 static void Log(const param_type& p, std::wstring* l);
925 };
926
927
928 #if defined(OS_WIN)
929 template<>
930 struct ParamTraits<TransportDIB::Id> {
931 typedef TransportDIB::Id param_type;
932 static void Write(Message* m, const param_type& p) {
933 WriteParam(m, p.handle);
934 WriteParam(m, p.sequence_num);
935 }
936 static bool Read(const Message* m, void** iter, param_type* r) {
937 return (ReadParam(m, iter, &r->handle) &&
938 ReadParam(m, iter, &r->sequence_num));
939 }
940 static void Log(const param_type& p, std::wstring* l) {
941 l->append(L"TransportDIB(");
942 LogParam(p.handle, l);
943 l->append(L", ");
944 LogParam(p.sequence_num, l);
945 l->append(L")");
946 }
947 };
948 #endif
949
950 // Traits for URLRequestStatus
951 template <>
952 struct ParamTraits<URLRequestStatus> {
953 typedef URLRequestStatus param_type;
954 static void Write(Message* m, const param_type& p) {
955 WriteParam(m, static_cast<int>(p.status()));
956 WriteParam(m, p.os_error());
957 }
958 static bool Read(const Message* m, void** iter, param_type* r) {
959 int status, os_error;
960 if (!ReadParam(m, iter, &status) ||
961 !ReadParam(m, iter, &os_error))
962 return false;
963 r->set_status(static_cast<URLRequestStatus::Status>(status));
964 r->set_os_error(os_error);
965 return true;
966 }
967 static void Log(const param_type& p, std::wstring* l) {
968 std::wstring status;
969 switch (p.status()) {
970 case URLRequestStatus::SUCCESS:
971 status = L"SUCCESS";
972 break;
973 case URLRequestStatus::IO_PENDING:
974 status = L"IO_PENDING ";
975 break;
976 case URLRequestStatus::HANDLED_EXTERNALLY:
977 status = L"HANDLED_EXTERNALLY";
978 break;
979 case URLRequestStatus::CANCELED:
980 status = L"CANCELED";
981 break;
982 case URLRequestStatus::FAILED:
983 status = L"FAILED";
984 break;
985 default:
986 status = L"UNKNOWN";
987 break;
988 }
989 if (p.status() == URLRequestStatus::FAILED)
990 l->append(L"(");
991
992 LogParam(status, l);
993
994 if (p.status() == URLRequestStatus::FAILED) {
995 l->append(L", ");
996 LogParam(p.os_error(), l);
997 l->append(L")");
998 }
999 }
1000 };
1001
1002 template <>
1003 struct ParamTraits<Message> {
1004 static void Write(Message* m, const Message& p) {
1005 m->WriteInt(p.size());
1006 m->WriteData(reinterpret_cast<const char*>(p.data()), p.size());
1007 }
1008 static bool Read(const Message* m, void** iter, Message* r) {
1009 int size;
1010 if (!m->ReadInt(iter, &size))
1011 return false;
1012 const char* data;
1013 if (!m->ReadData(iter, &data, &size))
1014 return false;
1015 *r = Message(data, size);
1016 return true;
1017 }
1018 static void Log(const Message& p, std::wstring* l) {
1019 l->append(L"<IPC::Message>");
1020 }
1021 };
1022
1023 template <>
1024 struct ParamTraits<Tuple0> {
1025 typedef Tuple0 param_type;
1026 static void Write(Message* m, const param_type& p) {
1027 }
1028 static bool Read(const Message* m, void** iter, param_type* r) {
1029 return true;
1030 }
1031 static void Log(const param_type& p, std::wstring* l) {
1032 }
1033 };
1034
1035 template <class A>
1036 struct ParamTraits< Tuple1<A> > {
1037 typedef Tuple1<A> param_type;
1038 static void Write(Message* m, const param_type& p) {
1039 WriteParam(m, p.a);
1040 }
1041 static bool Read(const Message* m, void** iter, param_type* r) {
1042 return ReadParam(m, iter, &r->a);
1043 }
1044 static void Log(const param_type& p, std::wstring* l) {
1045 LogParam(p.a, l);
1046 }
1047 };
1048
1049 template <class A, class B>
1050 struct ParamTraits< Tuple2<A, B> > {
1051 typedef Tuple2<A, B> param_type;
1052 static void Write(Message* m, const param_type& p) {
1053 WriteParam(m, p.a);
1054 WriteParam(m, p.b);
1055 }
1056 static bool Read(const Message* m, void** iter, param_type* r) {
1057 return (ReadParam(m, iter, &r->a) &&
1058 ReadParam(m, iter, &r->b));
1059 }
1060 static void Log(const param_type& p, std::wstring* l) {
1061 LogParam(p.a, l);
1062 l->append(L", ");
1063 LogParam(p.b, l);
1064 }
1065 };
1066
1067 template <class A, class B, class C>
1068 struct ParamTraits< Tuple3<A, B, C> > {
1069 typedef Tuple3<A, B, C> param_type;
1070 static void Write(Message* m, const param_type& p) {
1071 WriteParam(m, p.a);
1072 WriteParam(m, p.b);
1073 WriteParam(m, p.c);
1074 }
1075 static bool Read(const Message* m, void** iter, param_type* r) {
1076 return (ReadParam(m, iter, &r->a) &&
1077 ReadParam(m, iter, &r->b) &&
1078 ReadParam(m, iter, &r->c));
1079 }
1080 static void Log(const param_type& p, std::wstring* l) {
1081 LogParam(p.a, l);
1082 l->append(L", ");
1083 LogParam(p.b, l);
1084 l->append(L", ");
1085 LogParam(p.c, l);
1086 }
1087 };
1088
1089 template <class A, class B, class C, class D>
1090 struct ParamTraits< Tuple4<A, B, C, D> > {
1091 typedef Tuple4<A, B, C, D> param_type;
1092 static void Write(Message* m, const param_type& p) {
1093 WriteParam(m, p.a);
1094 WriteParam(m, p.b);
1095 WriteParam(m, p.c);
1096 WriteParam(m, p.d);
1097 }
1098 static bool Read(const Message* m, void** iter, param_type* r) {
1099 return (ReadParam(m, iter, &r->a) &&
1100 ReadParam(m, iter, &r->b) &&
1101 ReadParam(m, iter, &r->c) &&
1102 ReadParam(m, iter, &r->d));
1103 }
1104 static void Log(const param_type& p, std::wstring* l) {
1105 LogParam(p.a, l);
1106 l->append(L", ");
1107 LogParam(p.b, l);
1108 l->append(L", ");
1109 LogParam(p.c, l);
1110 l->append(L", ");
1111 LogParam(p.d, l);
1112 }
1113 };
1114
1115 template <class A, class B, class C, class D, class E>
1116 struct ParamTraits< Tuple5<A, B, C, D, E> > {
1117 typedef Tuple5<A, B, C, D, E> param_type;
1118 static void Write(Message* m, const param_type& p) {
1119 WriteParam(m, p.a);
1120 WriteParam(m, p.b);
1121 WriteParam(m, p.c);
1122 WriteParam(m, p.d);
1123 WriteParam(m, p.e);
1124 }
1125 static bool Read(const Message* m, void** iter, param_type* r) {
1126 return (ReadParam(m, iter, &r->a) &&
1127 ReadParam(m, iter, &r->b) &&
1128 ReadParam(m, iter, &r->c) &&
1129 ReadParam(m, iter, &r->d) &&
1130 ReadParam(m, iter, &r->e));
1131 }
1132 static void Log(const param_type& p, std::wstring* l) {
1133 LogParam(p.a, l);
1134 l->append(L", ");
1135 LogParam(p.b, l);
1136 l->append(L", ");
1137 LogParam(p.c, l);
1138 l->append(L", ");
1139 LogParam(p.d, l);
1140 l->append(L", ");
1141 LogParam(p.e, l);
1142 }
1143 };
1144
1145 //-----------------------------------------------------------------------------
1146 // Generic message subclasses
1147
1148 // Used for asynchronous messages.
1149 template <class ParamType>
1150 class MessageWithTuple : public Message {
1151 public:
1152 typedef ParamType Param;
1153 typedef typename ParamType::ParamTuple RefParam;
1154
1155 MessageWithTuple(int32 routing_id, uint16 type, const RefParam& p)
1156 : Message(routing_id, type, PRIORITY_NORMAL) {
1157 WriteParam(this, p);
1158 }
1159
1160 static bool Read(const Message* msg, Param* p) {
1161 void* iter = NULL;
1162 if (ReadParam(msg, &iter, p))
1163 return true;
1164 NOTREACHED() << "Error deserializing message " << msg->type();
1165 return false;
1166 }
1167
1168 // Generic dispatcher. Should cover most cases.
1169 template<class T, class Method>
1170 static bool Dispatch(const Message* msg, T* obj, Method func) {
1171 Param p;
1172 if (Read(msg, &p)) {
1173 DispatchToMethod(obj, func, p);
1174 return true;
1175 }
1176 return false;
1177 }
1178
1179 // The following dispatchers exist for the case where the callback function
1180 // needs the message as well. They assume that "Param" is a type of Tuple
1181 // (except the one arg case, as there is no Tuple1).
1182 template<class T, typename TA>
1183 static bool Dispatch(const Message* msg, T* obj,
1184 void (T::*func)(const Message&, TA)) {
1185 Param p;
1186 if (Read(msg, &p)) {
1187 (obj->*func)(*msg, p.a);
1188 return true;
1189 }
1190 return false;
1191 }
1192
1193 template<class T, typename TA, typename TB>
1194 static bool Dispatch(const Message* msg, T* obj,
1195 void (T::*func)(const Message&, TA, TB)) {
1196 Param p;
1197 if (Read(msg, &p)) {
1198 (obj->*func)(*msg, p.a, p.b);
1199 return true;
1200 }
1201 return false;
1202 }
1203
1204 template<class T, typename TA, typename TB, typename TC>
1205 static bool Dispatch(const Message* msg, T* obj,
1206 void (T::*func)(const Message&, TA, TB, TC)) {
1207 Param p;
1208 if (Read(msg, &p)) {
1209 (obj->*func)(*msg, p.a, p.b, p.c);
1210 return true;
1211 }
1212 return false;
1213 }
1214
1215 template<class T, typename TA, typename TB, typename TC, typename TD>
1216 static bool Dispatch(const Message* msg, T* obj,
1217 void (T::*func)(const Message&, TA, TB, TC, TD)) {
1218 Param p;
1219 if (Read(msg, &p)) {
1220 (obj->*func)(*msg, p.a, p.b, p.c, p.d);
1221 return true;
1222 }
1223 return false;
1224 }
1225
1226 template<class T, typename TA, typename TB, typename TC, typename TD,
1227 typename TE>
1228 static bool Dispatch(const Message* msg, T* obj,
1229 void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
1230 Param p;
1231 if (Read(msg, &p)) {
1232 (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
1233 return true;
1234 }
1235 return false;
1236 }
1237
1238 static void Log(const Message* msg, std::wstring* l) {
1239 Param p;
1240 if (Read(msg, &p))
1241 LogParam(p, l);
1242 }
1243
1244 // Functions used to do manual unpacking. Only used by the automation code,
1245 // these should go away once that code uses SyncChannel.
1246 template<typename TA, typename TB>
1247 static bool Read(const IPC::Message* msg, TA* a, TB* b) {
1248 ParamType params;
1249 if (!Read(msg, &params))
1250 return false;
1251 *a = params.a;
1252 *b = params.b;
1253 return true;
1254 }
1255
1256 template<typename TA, typename TB, typename TC>
1257 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
1258 ParamType params;
1259 if (!Read(msg, &params))
1260 return false;
1261 *a = params.a;
1262 *b = params.b;
1263 *c = params.c;
1264 return true;
1265 }
1266
1267 template<typename TA, typename TB, typename TC, typename TD>
1268 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
1269 ParamType params;
1270 if (!Read(msg, &params))
1271 return false;
1272 *a = params.a;
1273 *b = params.b;
1274 *c = params.c;
1275 *d = params.d;
1276 return true;
1277 }
1278
1279 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1280 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
1281 ParamType params;
1282 if (!Read(msg, &params))
1283 return false;
1284 *a = params.a;
1285 *b = params.b;
1286 *c = params.c;
1287 *d = params.d;
1288 *e = params.e;
1289 return true;
1290 }
1291 };
1292
1293 // This class assumes that its template argument is a RefTuple (a Tuple with
1294 // reference elements).
1295 template <class RefTuple>
1296 class ParamDeserializer : public MessageReplyDeserializer {
1297 public:
1298 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
1299
1300 bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
1301 return ReadParam(&msg, &iter, &out_);
1302 }
1303
1304 RefTuple out_;
1305 };
1306
1307 // defined in ipc_logging.cc
1308 void GenerateLogData(const std::string& channel, const Message& message,
1309 LogData* data);
1310
1311 // Used for synchronous messages.
1312 template <class SendParamType, class ReplyParamType>
1313 class MessageWithReply : public SyncMessage {
1314 public:
1315 typedef SendParamType SendParam;
1316 typedef typename SendParam::ParamTuple RefSendParam;
1317 typedef ReplyParamType ReplyParam;
1318
1319 MessageWithReply(int32 routing_id, uint16 type,
1320 const RefSendParam& send, const ReplyParam& reply)
1321 : SyncMessage(routing_id, type, PRIORITY_NORMAL,
1322 new ParamDeserializer<ReplyParam>(reply)) {
1323 WriteParam(this, send);
1324 }
1325
1326 static void Log(const Message* msg, std::wstring* l) {
1327 if (msg->is_sync()) {
1328 SendParam p;
1329 void* iter = SyncMessage::GetDataIterator(msg);
1330 if (ReadParam(msg, &iter, &p))
1331 LogParam(p, l);
1332
1333 #if defined(IPC_MESSAGE_LOG_ENABLED)
1334 const std::wstring& output_params = msg->output_params();
1335 if (!l->empty() && !output_params.empty())
1336 l->append(L", ");
1337
1338 l->append(output_params);
1339 #endif
1340 } else {
1341 // This is an outgoing reply. Now that we have the output parameters, we
1342 // can finally log the message.
1343 typename ReplyParam::ValueTuple p;
1344 void* iter = SyncMessage::GetDataIterator(msg);
1345 if (ReadParam(msg, &iter, &p))
1346 LogParam(p, l);
1347 }
1348 }
1349
1350 template<class T, class Method>
1351 static bool Dispatch(const Message* msg, T* obj, Method func) {
1352 SendParam send_params;
1353 void* iter = GetDataIterator(msg);
1354 Message* reply = GenerateReply(msg);
1355 bool error;
1356 if (ReadParam(msg, &iter, &send_params)) {
1357 typename ReplyParam::ValueTuple reply_params;
1358 DispatchToMethod(obj, func, send_params, &reply_params);
1359 WriteParam(reply, reply_params);
1360 error = false;
1361 #ifdef IPC_MESSAGE_LOG_ENABLED
1362 if (msg->received_time() != 0) {
1363 std::wstring output_params;
1364 LogParam(reply_params, &output_params);
1365 msg->set_output_params(output_params);
1366 }
1367 #endif
1368 } else {
1369 NOTREACHED() << "Error deserializing message " << msg->type();
1370 reply->set_reply_error();
1371 error = true;
1372 }
1373
1374 obj->Send(reply);
1375 return !error;
1376 }
1377
1378 template<class T, class Method>
1379 static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
1380 SendParam send_params;
1381 void* iter = GetDataIterator(msg);
1382 Message* reply = GenerateReply(msg);
1383 bool error;
1384 if (ReadParam(msg, &iter, &send_params)) {
1385 Tuple1<Message&> t = MakeRefTuple(*reply);
1386
1387 #ifdef IPC_MESSAGE_LOG_ENABLED
1388 if (msg->sent_time()) {
1389 // Don't log the sync message after dispatch, as we don't have the
1390 // output parameters at that point. Instead, save its data and log it
1391 // with the outgoing reply message when it's sent.
1392 LogData* data = new LogData;
1393 GenerateLogData("", *msg, data);
1394 msg->set_dont_log();
1395 reply->set_sync_log_data(data);
1396 }
1397 #endif
1398 DispatchToMethod(obj, func, send_params, &t);
1399 error = false;
1400 } else {
1401 NOTREACHED() << "Error deserializing message " << msg->type();
1402 reply->set_reply_error();
1403 obj->Send(reply);
1404 error = true;
1405 }
1406 return !error;
1407 }
1408
1409 template<typename TA>
1410 static void WriteReplyParams(Message* reply, TA a) {
1411 ReplyParam p(a);
1412 WriteParam(reply, p);
1413 }
1414
1415 template<typename TA, typename TB>
1416 static void WriteReplyParams(Message* reply, TA a, TB b) {
1417 ReplyParam p(a, b);
1418 WriteParam(reply, p);
1419 }
1420
1421 template<typename TA, typename TB, typename TC>
1422 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
1423 ReplyParam p(a, b, c);
1424 WriteParam(reply, p);
1425 }
1426
1427 template<typename TA, typename TB, typename TC, typename TD>
1428 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
1429 ReplyParam p(a, b, c, d);
1430 WriteParam(reply, p);
1431 }
1432
1433 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1434 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
1435 ReplyParam p(a, b, c, d, e);
1436 WriteParam(reply, p);
1437 }
1438 };
1439
1440 //-----------------------------------------------------------------------------
1441
1442 } // namespace IPC
1443
1444 #endif // CHROME_COMMON_IPC_MESSAGE_UTILS_H_
OLDNEW
« no previous file with comments | « chrome/common/ipc_message_unittest.cc ('k') | chrome/common/ipc_message_utils.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698