blob: 0da59c4b2c171ddee8910c0f5f1664da734d91c6 [file] [log] [blame]
[email protected]225c8f52010-02-05 22:23:201// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]946d1b22009-07-22 23:57:215#ifndef IPC_IPC_MESSAGE_UTILS_H_
6#define IPC_IPC_MESSAGE_UTILS_H_
[email protected]32b76ef2010-07-26 23:08:247#pragma once
initial.commit09911bf2008-07-26 23:55:298
[email protected]379e7a52010-03-09 00:38:419#include <algorithm>
initial.commit09911bf2008-07-26 23:55:2910#include <string>
11#include <vector>
12#include <map>
[email protected]96da6962010-05-13 19:10:3413#include <set>
initial.commit09911bf2008-07-26 23:55:2914
[email protected]690a99c2009-01-06 16:48:4515#include "base/file_path.h"
[email protected]dce5df52009-06-29 17:58:2516#include "base/format_macros.h"
[email protected]15bf8712009-08-27 00:55:0217#include "base/nullable_string16.h"
[email protected]eb47a132009-03-04 00:39:5618#include "base/string16.h"
[email protected]528c56d2010-07-30 19:28:4419#include "base/string_number_conversions.h"
[email protected]dce5df52009-06-29 17:58:2520#include "base/string_util.h"
[email protected]379e7a52010-03-09 00:38:4121#include "base/utf_string_conversions.h"
[email protected]946d1b22009-07-22 23:57:2122#include "base/time.h"
initial.commit09911bf2008-07-26 23:55:2923#include "base/tuple.h"
[email protected]946d1b22009-07-22 23:57:2124#include "base/values.h"
[email protected]526776c2009-02-07 00:39:2625#if defined(OS_POSIX)
[email protected]946d1b22009-07-22 23:57:2126#include "ipc/file_descriptor_set_posix.h"
[email protected]526776c2009-02-07 00:39:2627#endif
[email protected]946d1b22009-07-22 23:57:2128#include "ipc/ipc_channel_handle.h"
29#include "ipc/ipc_sync_message.h"
[email protected]82e5ee82009-04-03 02:29:4530
[email protected]f91cb992009-02-04 20:10:1231// Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
32// base. Messages have unique IDs across channels in order for the IPC logging
33// code to figure out the message class from its ID.
34enum IPCMessageStart {
35 // By using a start value of 0 for automation messages, we keep backward
36 // compatibility with old builds.
37 AutomationMsgStart = 0,
38 ViewMsgStart,
39 ViewHostMsgStart,
40 PluginProcessMsgStart,
41 PluginProcessHostMsgStart,
42 PluginMsgStart,
43 PluginHostMsgStart,
[email protected]96da6962010-05-13 19:10:3444 ProfileImportProcessMsgStart,
45 ProfileImportProcessHostMsgStart,
[email protected]f91cb992009-02-04 20:10:1246 NPObjectMsgStart,
47 TestMsgStart,
[email protected]503683f2009-02-26 09:13:0148 DevToolsAgentMsgStart,
49 DevToolsClientMsgStart,
[email protected]eb47a132009-03-04 00:39:5650 WorkerProcessMsgStart,
51 WorkerProcessHostMsgStart,
52 WorkerMsgStart,
53 WorkerHostMsgStart,
[email protected]d032f492009-09-29 00:33:4654 NaClProcessMsgStart,
[email protected]246a70452010-03-05 21:53:5055 GpuCommandBufferMsgStart,
[email protected]60f14392009-12-15 20:46:3256 UtilityMsgStart,
57 UtilityHostMsgStart,
[email protected]c0fc0942010-01-13 00:55:3758 GpuMsgStart,
59 GpuHostMsgStart,
[email protected]246a70452010-03-05 21:53:5060 GpuChannelMsgStart,
[email protected]38fe1962010-07-31 07:57:0061 ServiceMsgStart,
62 ServiceHostMsgStart,
[email protected]f91cb992009-02-04 20:10:1263 // NOTE: When you add a new message class, also update
64 // IPCStatusView::IPCStatusView to ensure logging works.
[email protected]f91cb992009-02-04 20:10:1265 LastMsgIndex
66};
67
initial.commit09911bf2008-07-26 23:55:2968namespace IPC {
69
initial.commit09911bf2008-07-26 23:55:2970//-----------------------------------------------------------------------------
71// An iterator class for reading the fields contained within a Message.
72
73class MessageIterator {
74 public:
[email protected]e1981f432008-08-12 15:22:1375 explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
initial.commit09911bf2008-07-26 23:55:2976 }
77 int NextInt() const {
[email protected]9422b7dc2009-12-30 20:09:0278 int val = -1;
initial.commit09911bf2008-07-26 23:55:2979 if (!msg_.ReadInt(&iter_, &val))
80 NOTREACHED();
81 return val;
82 }
initial.commit09911bf2008-07-26 23:55:2983 const std::string NextString() const {
84 std::string val;
85 if (!msg_.ReadString(&iter_, &val))
86 NOTREACHED();
87 return val;
88 }
89 const std::wstring NextWString() const {
90 std::wstring val;
91 if (!msg_.ReadWString(&iter_, &val))
92 NOTREACHED();
93 return val;
94 }
[email protected]225c8f52010-02-05 22:23:2095 void NextData(const char** data, int* length) const {
initial.commit09911bf2008-07-26 23:55:2996 if (!msg_.ReadData(&iter_, data, length)) {
97 NOTREACHED();
98 }
99 }
100 private:
101 const Message& msg_;
102 mutable void* iter_;
103};
104
105//-----------------------------------------------------------------------------
[email protected]7d5c3ac2009-02-04 08:58:19106// ParamTraits specializations, etc.
107
[email protected]7b291f92009-08-14 05:43:53108template <class P> struct ParamTraits {
109};
110
111template <class P>
112struct SimilarTypeTraits {
113 typedef P Type;
114};
[email protected]7d5c3ac2009-02-04 08:58:19115
116template <class P>
117static inline void WriteParam(Message* m, const P& p) {
[email protected]7b291f92009-08-14 05:43:53118 typedef typename SimilarTypeTraits<P>::Type Type;
[email protected]46ce5b562010-06-16 18:39:53119 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
[email protected]7d5c3ac2009-02-04 08:58:19120}
121
122template <class P>
[email protected]1e86aa62009-04-24 21:22:33123static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
124 P* p) {
[email protected]7b291f92009-08-14 05:43:53125 typedef typename SimilarTypeTraits<P>::Type Type;
126 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
[email protected]7d5c3ac2009-02-04 08:58:19127}
128
129template <class P>
130static inline void LogParam(const P& p, std::wstring* l) {
[email protected]7b291f92009-08-14 05:43:53131 typedef typename SimilarTypeTraits<P>::Type Type;
[email protected]46ce5b562010-06-16 18:39:53132 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
[email protected]7d5c3ac2009-02-04 08:58:19133}
134
135template <>
136struct ParamTraits<bool> {
137 typedef bool param_type;
138 static void Write(Message* m, const param_type& p) {
139 m->WriteBool(p);
140 }
141 static bool Read(const Message* m, void** iter, param_type* r) {
142 return m->ReadBool(iter, r);
143 }
144 static void Log(const param_type& p, std::wstring* l) {
145 l->append(p ? L"true" : L"false");
146 }
147};
148
149template <>
150struct ParamTraits<int> {
151 typedef int param_type;
152 static void Write(Message* m, const param_type& p) {
153 m->WriteInt(p);
154 }
155 static bool Read(const Message* m, void** iter, param_type* r) {
156 return m->ReadInt(iter, r);
157 }
158 static void Log(const param_type& p, std::wstring* l) {
159 l->append(StringPrintf(L"%d", p));
160 }
161};
162
163template <>
[email protected]63263f92009-07-28 19:35:08164struct ParamTraits<unsigned int> {
165 typedef unsigned int param_type;
166 static void Write(Message* m, const param_type& p) {
167 m->WriteInt(p);
168 }
169 static bool Read(const Message* m, void** iter, param_type* r) {
170 return m->ReadInt(iter, reinterpret_cast<int*>(r));
171 }
172 static void Log(const param_type& p, std::wstring* l) {
173 l->append(StringPrintf(L"%d", p));
174 }
175};
176
177template <>
[email protected]7d5c3ac2009-02-04 08:58:19178struct ParamTraits<long> {
179 typedef long param_type;
180 static void Write(Message* m, const param_type& p) {
181 m->WriteLong(p);
182 }
183 static bool Read(const Message* m, void** iter, param_type* r) {
184 return m->ReadLong(iter, r);
185 }
186 static void Log(const param_type& p, std::wstring* l) {
[email protected]63263f92009-07-28 19:35:08187 l->append(StringPrintf(L"%ld", p));
[email protected]7d5c3ac2009-02-04 08:58:19188 }
189};
190
[email protected]140c3032009-06-26 18:22:54191template <>
192struct ParamTraits<unsigned long> {
193 typedef unsigned long param_type;
194 static void Write(Message* m, const param_type& p) {
195 m->WriteLong(p);
196 }
197 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]63263f92009-07-28 19:35:08198 return m->ReadLong(iter, reinterpret_cast<long*>(r));
[email protected]140c3032009-06-26 18:22:54199 }
200 static void Log(const param_type& p, std::wstring* l) {
[email protected]63263f92009-07-28 19:35:08201 l->append(StringPrintf(L"%lu", p));
[email protected]7d5c3ac2009-02-04 08:58:19202 }
203};
204
205template <>
[email protected]63263f92009-07-28 19:35:08206struct ParamTraits<long long> {
207 typedef long long param_type;
[email protected]7d5c3ac2009-02-04 08:58:19208 static void Write(Message* m, const param_type& p) {
209 m->WriteInt64(static_cast<int64>(p));
210 }
211 static bool Read(const Message* m, void** iter, param_type* r) {
212 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
213 }
214 static void Log(const param_type& p, std::wstring* l) {
[email protected]528c56d2010-07-30 19:28:44215 l->append(UTF8ToWide(base::Int64ToString(static_cast<int64>(p))));
[email protected]63263f92009-07-28 19:35:08216 }
217};
218
219template <>
220struct ParamTraits<unsigned long long> {
221 typedef unsigned long long param_type;
222 static void Write(Message* m, const param_type& p) {
223 m->WriteInt64(p);
224 }
225 static bool Read(const Message* m, void** iter, param_type* r) {
226 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
227 }
228 static void Log(const param_type& p, std::wstring* l) {
[email protected]528c56d2010-07-30 19:28:44229 l->append(UTF8ToWide(base::Uint64ToString(p)));
[email protected]7d5c3ac2009-02-04 08:58:19230 }
231};
232
[email protected]20199662010-06-17 03:29:26233// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
234// should be sure to check the sanity of these values after receiving them over
235// IPC.
236template <>
237struct ParamTraits<float> {
238 typedef float 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;
245 if (!m->ReadData(iter, &data, &data_size) ||
246 data_size != sizeof(param_type)) {
247 NOTREACHED();
248 return false;
249 }
250 memcpy(r, data, sizeof(param_type));
251 return true;
252 }
253 static void Log(const param_type& p, std::wstring* l) {
254 l->append(StringPrintf(L"e", p));
255 }
256};
257
[email protected]7d5c3ac2009-02-04 08:58:19258template <>
259struct ParamTraits<double> {
260 typedef double param_type;
261 static void Write(Message* m, const param_type& p) {
262 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
263 }
264 static bool Read(const Message* m, void** iter, param_type* r) {
265 const char *data;
[email protected]20199662010-06-17 03:29:26266 int data_size;
267 if (!m->ReadData(iter, &data, &data_size) ||
268 data_size != sizeof(param_type)) {
[email protected]7d5c3ac2009-02-04 08:58:19269 NOTREACHED();
[email protected]20199662010-06-17 03:29:26270 return false;
[email protected]7d5c3ac2009-02-04 08:58:19271 }
[email protected]20199662010-06-17 03:29:26272 memcpy(r, data, sizeof(param_type));
273 return true;
[email protected]7d5c3ac2009-02-04 08:58:19274 }
275 static void Log(const param_type& p, std::wstring* l) {
276 l->append(StringPrintf(L"e", p));
277 }
278};
279
280template <>
281struct ParamTraits<wchar_t> {
282 typedef wchar_t param_type;
283 static void Write(Message* m, const param_type& p) {
284 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
285 }
286 static bool Read(const Message* m, void** iter, param_type* r) {
287 const char *data;
288 int data_size = 0;
289 bool result = m->ReadData(iter, &data, &data_size);
290 if (result && data_size == sizeof(param_type)) {
291 memcpy(r, data, sizeof(param_type));
292 } else {
293 result = false;
294 NOTREACHED();
295 }
296
297 return result;
298 }
299 static void Log(const param_type& p, std::wstring* l) {
300 l->append(StringPrintf(L"%lc", p));
301 }
302};
303
304template <>
305struct ParamTraits<base::Time> {
306 typedef base::Time param_type;
307 static void Write(Message* m, const param_type& p) {
308 ParamTraits<int64>::Write(m, p.ToInternalValue());
309 }
310 static bool Read(const Message* m, void** iter, param_type* r) {
311 int64 value;
312 if (!ParamTraits<int64>::Read(m, iter, &value))
313 return false;
314 *r = base::Time::FromInternalValue(value);
315 return true;
316 }
317 static void Log(const param_type& p, std::wstring* l) {
318 ParamTraits<int64>::Log(p.ToInternalValue(), l);
319 }
320};
321
322#if defined(OS_WIN)
323template <>
324struct ParamTraits<LOGFONT> {
325 typedef LOGFONT param_type;
326 static void Write(Message* m, const param_type& p) {
327 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
328 }
329 static bool Read(const Message* m, void** iter, param_type* r) {
330 const char *data;
331 int data_size = 0;
332 bool result = m->ReadData(iter, &data, &data_size);
333 if (result && data_size == sizeof(LOGFONT)) {
334 memcpy(r, data, sizeof(LOGFONT));
335 } else {
336 result = false;
337 NOTREACHED();
338 }
339
340 return result;
341 }
342 static void Log(const param_type& p, std::wstring* l) {
343 l->append(StringPrintf(L"<LOGFONT>"));
344 }
345};
346
347template <>
348struct ParamTraits<MSG> {
349 typedef MSG param_type;
350 static void Write(Message* m, const param_type& p) {
351 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
352 }
353 static bool Read(const Message* m, void** iter, param_type* r) {
354 const char *data;
355 int data_size = 0;
356 bool result = m->ReadData(iter, &data, &data_size);
357 if (result && data_size == sizeof(MSG)) {
358 memcpy(r, data, sizeof(MSG));
359 } else {
360 result = false;
361 NOTREACHED();
362 }
363
364 return result;
365 }
366};
367#endif // defined(OS_WIN)
368
369template <>
[email protected]584f2b22009-05-21 01:01:59370struct ParamTraits<DictionaryValue> {
371 typedef DictionaryValue param_type;
372 static void Write(Message* m, const param_type& p);
373 static bool Read(const Message* m, void** iter, param_type* r);
374 static void Log(const param_type& p, std::wstring* l);
375};
376
377template <>
378struct ParamTraits<ListValue> {
379 typedef ListValue param_type;
380 static void Write(Message* m, const param_type& p);
381 static bool Read(const Message* m, void** iter, param_type* r);
382 static void Log(const param_type& p, std::wstring* l);
383};
384
385template <>
[email protected]7d5c3ac2009-02-04 08:58:19386struct ParamTraits<std::string> {
387 typedef std::string param_type;
388 static void Write(Message* m, const param_type& p) {
389 m->WriteString(p);
390 }
391 static bool Read(const Message* m, void** iter, param_type* r) {
392 return m->ReadString(iter, r);
393 }
394 static void Log(const param_type& p, std::wstring* l) {
395 l->append(UTF8ToWide(p));
396 }
397};
398
[email protected]3dd7a7a2009-07-27 21:09:07399template<typename CharType>
400static void LogBytes(const std::vector<CharType>& data, std::wstring* out) {
401#if defined(OS_WIN)
402 // Windows has a GUI for logging, which can handle arbitrary binary data.
403 for (size_t i = 0; i < data.size(); ++i)
404 out->push_back(data[i]);
405#else
406 // On POSIX, we log to stdout, which we assume can display ASCII.
407 static const size_t kMaxBytesToLog = 100;
408 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
409 if (isprint(data[i]))
410 out->push_back(data[i]);
411 else
412 out->append(StringPrintf(L"[%02X]", static_cast<unsigned char>(data[i])));
413 }
414 if (data.size() > kMaxBytesToLog) {
415 out->append(
416 StringPrintf(L" and %u more bytes",
417 static_cast<unsigned>(data.size() - kMaxBytesToLog)));
418 }
419#endif
420}
421
[email protected]7d5c3ac2009-02-04 08:58:19422template <>
423struct ParamTraits<std::vector<unsigned char> > {
424 typedef std::vector<unsigned char> param_type;
425 static void Write(Message* m, const param_type& p) {
426 if (p.size() == 0) {
427 m->WriteData(NULL, 0);
428 } else {
429 m->WriteData(reinterpret_cast<const char*>(&p.front()),
430 static_cast<int>(p.size()));
431 }
432 }
433 static bool Read(const Message* m, void** iter, param_type* r) {
434 const char *data;
435 int data_size = 0;
436 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
437 return false;
438 r->resize(data_size);
439 if (data_size)
440 memcpy(&r->front(), data, data_size);
441 return true;
442 }
443 static void Log(const param_type& p, std::wstring* l) {
[email protected]3dd7a7a2009-07-27 21:09:07444 LogBytes(p, l);
[email protected]7d5c3ac2009-02-04 08:58:19445 }
446};
447
448template <>
449struct ParamTraits<std::vector<char> > {
450 typedef std::vector<char> param_type;
451 static void Write(Message* m, const param_type& p) {
452 if (p.size() == 0) {
453 m->WriteData(NULL, 0);
454 } else {
455 m->WriteData(&p.front(), static_cast<int>(p.size()));
456 }
457 }
458 static bool Read(const Message* m, void** iter, param_type* r) {
459 const char *data;
460 int data_size = 0;
461 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
462 return false;
463 r->resize(data_size);
464 if (data_size)
465 memcpy(&r->front(), data, data_size);
466 return true;
467 }
468 static void Log(const param_type& p, std::wstring* l) {
[email protected]3dd7a7a2009-07-27 21:09:07469 LogBytes(p, l);
[email protected]7d5c3ac2009-02-04 08:58:19470 }
471};
472
473template <class P>
474struct 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;
[email protected]86440f52009-12-31 05:17:23483 // ReadLength() checks for < 0 itself.
[email protected]7d5c3ac2009-02-04 08:58:19484 if (!m->ReadLength(iter, &size))
485 return false;
486 // Resizing beforehand is not safe, see BUG 1006367 for details.
[email protected]86440f52009-12-31 05:17:23487 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
488 return false;
489 r->resize(size);
490 for (int i = 0; i < size; i++) {
491 if (!ReadParam(m, iter, &(*r)[i]))
492 return false;
[email protected]7d5c3ac2009-02-04 08:58:19493 }
494 return true;
495 }
496 static void Log(const param_type& p, std::wstring* l) {
497 for (size_t i = 0; i < p.size(); ++i) {
498 if (i != 0)
499 l->append(L" ");
[email protected]7d5c3ac2009-02-04 08:58:19500 LogParam((p[i]), l);
501 }
502 }
503};
504
[email protected]96da6962010-05-13 19:10:34505template <class P>
506struct ParamTraits<std::set<P> > {
507 typedef std::set<P> param_type;
508 static void Write(Message* m, const param_type& p) {
509 WriteParam(m, static_cast<int>(p.size()));
510 typename param_type::const_iterator iter;
511 for (iter = p.begin(); iter != p.end(); ++iter)
512 WriteParam(m, *iter);
513 }
514 static bool Read(const Message* m, void** iter, param_type* r) {
515 int size;
516 if (!m->ReadLength(iter, &size))
517 return false;
518 for (int i = 0; i < size; ++i) {
519 P item;
520 if (!ReadParam(m, iter, &item))
521 return false;
522 r->insert(item);
523 }
524 return true;
525 }
526 static void Log(const param_type& p, std::wstring* l) {
527 l->append(L"<std::set>");
528 }
529};
530
531
[email protected]7d5c3ac2009-02-04 08:58:19532template <class K, class V>
533struct ParamTraits<std::map<K, V> > {
534 typedef std::map<K, V> param_type;
535 static void Write(Message* m, const param_type& p) {
536 WriteParam(m, static_cast<int>(p.size()));
537 typename param_type::const_iterator iter;
538 for (iter = p.begin(); iter != p.end(); ++iter) {
539 WriteParam(m, iter->first);
540 WriteParam(m, iter->second);
541 }
542 }
543 static bool Read(const Message* m, void** iter, param_type* r) {
544 int size;
545 if (!ReadParam(m, iter, &size) || size < 0)
546 return false;
547 for (int i = 0; i < size; ++i) {
548 K k;
549 if (!ReadParam(m, iter, &k))
550 return false;
551 V& value = (*r)[k];
552 if (!ReadParam(m, iter, &value))
553 return false;
554 }
555 return true;
556 }
557 static void Log(const param_type& p, std::wstring* l) {
558 l->append(L"<std::map>");
559 }
560};
561
[email protected]eb47a132009-03-04 00:39:56562
[email protected]7d5c3ac2009-02-04 08:58:19563template <>
564struct ParamTraits<std::wstring> {
565 typedef std::wstring param_type;
566 static void Write(Message* m, const param_type& p) {
567 m->WriteWString(p);
568 }
569 static bool Read(const Message* m, void** iter, param_type* r) {
570 return m->ReadWString(iter, r);
571 }
572 static void Log(const param_type& p, std::wstring* l) {
573 l->append(p);
574 }
575};
576
[email protected]a5da6d612009-08-04 02:00:56577template <class A, class B>
578struct ParamTraits<std::pair<A, B> > {
579 typedef std::pair<A, B> param_type;
580 static void Write(Message* m, const param_type& p) {
581 WriteParam(m, p.first);
582 WriteParam(m, p.second);
583 }
584 static bool Read(const Message* m, void** iter, param_type* r) {
585 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
586 }
587 static void Log(const param_type& p, std::wstring* l) {
588 l->append(L"(");
589 LogParam(p.first, l);
590 l->append(L", ");
591 LogParam(p.second, l);
592 l->append(L")");
593 }
594};
595
[email protected]15bf8712009-08-27 00:55:02596template <>
597struct ParamTraits<NullableString16> {
598 typedef NullableString16 param_type;
599 static void Write(Message* m, const param_type& p) {
600 WriteParam(m, p.string());
601 WriteParam(m, p.is_null());
602 }
603 static bool Read(const Message* m, void** iter, param_type* r) {
604 string16 string;
605 if (!ReadParam(m, iter, &string))
606 return false;
607 bool is_null;
608 if (!ReadParam(m, iter, &is_null))
609 return false;
610 *r = NullableString16(string, is_null);
611 return true;
612 }
613 static void Log(const param_type& p, std::wstring* l) {
614 l->append(L"(");
615 LogParam(p.string(), l);
616 l->append(L", ");
617 LogParam(p.is_null(), l);
618 l->append(L")");
619 }
620};
621
[email protected]eb47a132009-03-04 00:39:56622// If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
623// need this trait.
624#if !defined(WCHAR_T_IS_UTF16)
[email protected]eb47a132009-03-04 00:39:56625template <>
626struct ParamTraits<string16> {
627 typedef string16 param_type;
628 static void Write(Message* m, const param_type& p) {
[email protected]3a2a5d22009-03-04 03:36:36629 m->WriteString16(p);
[email protected]eb47a132009-03-04 00:39:56630 }
631 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]3a2a5d22009-03-04 03:36:36632 return m->ReadString16(iter, r);
[email protected]eb47a132009-03-04 00:39:56633 }
634 static void Log(const param_type& p, std::wstring* l) {
635 l->append(UTF16ToWide(p));
636 }
637};
[email protected]eb47a132009-03-04 00:39:56638#endif
639
[email protected]7d5c3ac2009-02-04 08:58:19640// and, a few more useful types...
641#if defined(OS_WIN)
642template <>
643struct ParamTraits<HANDLE> {
644 typedef HANDLE param_type;
645 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35646 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
647 // bit systems.
648 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19649 }
650 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35651 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
652 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19653 }
654 static void Log(const param_type& p, std::wstring* l) {
655 l->append(StringPrintf(L"0x%X", p));
656 }
657};
658
659template <>
660struct ParamTraits<HCURSOR> {
661 typedef HCURSOR param_type;
662 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35663 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19664 }
665 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35666 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
667 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19668 }
669 static void Log(const param_type& p, std::wstring* l) {
670 l->append(StringPrintf(L"0x%X", p));
671 }
672};
673
674template <>
[email protected]7d5c3ac2009-02-04 08:58:19675struct ParamTraits<HACCEL> {
676 typedef HACCEL param_type;
677 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35678 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19679 }
680 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35681 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
682 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19683 }
684};
685
686template <>
687struct ParamTraits<POINT> {
688 typedef POINT param_type;
689 static void Write(Message* m, const param_type& p) {
690 m->WriteInt(p.x);
691 m->WriteInt(p.y);
692 }
693 static bool Read(const Message* m, void** iter, param_type* r) {
694 int x, y;
695 if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
696 return false;
697 r->x = x;
698 r->y = y;
699 return true;
700 }
701 static void Log(const param_type& p, std::wstring* l) {
702 l->append(StringPrintf(L"(%d, %d)", p.x, p.y));
703 }
704};
705#endif // defined(OS_WIN)
706
707template <>
708struct ParamTraits<FilePath> {
709 typedef FilePath param_type;
710 static void Write(Message* m, const param_type& p) {
711 ParamTraits<FilePath::StringType>::Write(m, p.value());
712 }
713 static bool Read(const Message* m, void** iter, param_type* r) {
714 FilePath::StringType value;
715 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
716 return false;
717 *r = FilePath(value);
718 return true;
719 }
720 static void Log(const param_type& p, std::wstring* l) {
721 ParamTraits<FilePath::StringType>::Log(p.value(), l);
722 }
723};
724
[email protected]526776c2009-02-07 00:39:26725#if defined(OS_POSIX)
[email protected]2749885f2009-03-05 21:40:11726// FileDescriptors may be serialised over IPC channels on POSIX. On the
727// receiving side, the FileDescriptor is a valid duplicate of the file
728// descriptor which was transmitted: *it is not just a copy of the integer like
729// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
730// this case, the receiving end will see a value of -1. *Zero is a valid file
731// descriptor*.
732//
733// The received file descriptor will have the |auto_close| flag set to true. The
734// code which handles the message is responsible for taking ownership of it.
735// File descriptors are OS resources and must be closed when no longer needed.
736//
737// When sending a file descriptor, the file descriptor must be valid at the time
738// of transmission. Since transmission is not synchronous, one should consider
739// dup()ing any file descriptors to be transmitted and setting the |auto_close|
740// flag, which causes the file descriptor to be closed after writing.
[email protected]526776c2009-02-07 00:39:26741template<>
[email protected]5fe733de2009-02-11 18:59:20742struct ParamTraits<base::FileDescriptor> {
743 typedef base::FileDescriptor param_type;
[email protected]526776c2009-02-07 00:39:26744 static void Write(Message* m, const param_type& p) {
[email protected]2749885f2009-03-05 21:40:11745 const bool valid = p.fd >= 0;
746 WriteParam(m, valid);
747
748 if (valid) {
749 if (!m->WriteFileDescriptor(p))
750 NOTREACHED();
751 }
[email protected]526776c2009-02-07 00:39:26752 }
753 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]2749885f2009-03-05 21:40:11754 bool valid;
755 if (!ReadParam(m, iter, &valid))
756 return false;
757
758 if (!valid) {
759 r->fd = -1;
760 r->auto_close = false;
761 return true;
762 }
763
[email protected]7135bb042009-02-12 04:05:28764 return m->ReadFileDescriptor(iter, r);
[email protected]526776c2009-02-07 00:39:26765 }
766 static void Log(const param_type& p, std::wstring* l) {
767 if (p.auto_close) {
[email protected]7135bb042009-02-12 04:05:28768 l->append(StringPrintf(L"FD(%d auto-close)", p.fd));
[email protected]526776c2009-02-07 00:39:26769 } else {
[email protected]7135bb042009-02-12 04:05:28770 l->append(StringPrintf(L"FD(%d)", p.fd));
[email protected]526776c2009-02-07 00:39:26771 }
772 }
773};
[email protected]379e7a52010-03-09 00:38:41774#endif // defined(OS_POSIX)
[email protected]526776c2009-02-07 00:39:26775
[email protected]d2e884d2009-06-22 20:37:52776// A ChannelHandle is basically a platform-inspecific wrapper around the
777// fact that IPC endpoints are handled specially on POSIX. See above comments
778// on FileDescriptor for more background.
779template<>
780struct ParamTraits<IPC::ChannelHandle> {
781 typedef ChannelHandle param_type;
782 static void Write(Message* m, const param_type& p) {
783 WriteParam(m, p.name);
784#if defined(OS_POSIX)
785 WriteParam(m, p.socket);
786#endif
787 }
788 static bool Read(const Message* m, void** iter, param_type* r) {
789 return ReadParam(m, iter, &r->name)
790#if defined(OS_POSIX)
791 && ReadParam(m, iter, &r->socket)
792#endif
793 ;
794 }
795 static void Log(const param_type& p, std::wstring* l) {
[email protected]e9abf8d2009-07-10 22:41:00796 l->append(ASCIIToWide(StringPrintf("ChannelHandle(%s", p.name.c_str())));
[email protected]d2e884d2009-06-22 20:37:52797#if defined(OS_POSIX)
798 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
799#endif
800 l->append(L")");
801 }
802};
803
[email protected]7d5c3ac2009-02-04 08:58:19804#if defined(OS_WIN)
805template <>
806struct ParamTraits<XFORM> {
807 typedef XFORM param_type;
808 static void Write(Message* m, const param_type& p) {
809 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
810 }
811 static bool Read(const Message* m, void** iter, param_type* r) {
812 const char *data;
813 int data_size = 0;
814 bool result = m->ReadData(iter, &data, &data_size);
815 if (result && data_size == sizeof(XFORM)) {
816 memcpy(r, data, sizeof(XFORM));
817 } else {
818 result = false;
819 NOTREACHED();
820 }
821
822 return result;
823 }
824 static void Log(const param_type& p, std::wstring* l) {
825 l->append(L"<XFORM>");
826 }
827};
828#endif // defined(OS_WIN)
829
[email protected]7d5c3ac2009-02-04 08:58:19830struct LogData {
[email protected]9a3a293b2009-06-04 22:28:16831 std::string channel;
[email protected]8bef70e2009-04-14 19:11:24832 int32 routing_id;
[email protected]168ae922009-12-04 18:08:45833 uint32 type; // "User-defined" message type, from ipc_message.h.
[email protected]7d5c3ac2009-02-04 08:58:19834 std::wstring flags;
835 int64 sent; // Time that the message was sent (i.e. at Send()).
836 int64 receive; // Time before it was dispatched (i.e. before calling
837 // OnMessageReceived).
838 int64 dispatch; // Time after it was dispatched (i.e. after calling
839 // OnMessageReceived).
[email protected]e707d5e62009-02-12 04:00:08840 std::wstring message_name;
[email protected]7d5c3ac2009-02-04 08:58:19841 std::wstring params;
842};
843
844template <>
845struct ParamTraits<LogData> {
846 typedef LogData param_type;
847 static void Write(Message* m, const param_type& p) {
848 WriteParam(m, p.channel);
[email protected]8bef70e2009-04-14 19:11:24849 WriteParam(m, p.routing_id);
[email protected]7d5c3ac2009-02-04 08:58:19850 WriteParam(m, static_cast<int>(p.type));
851 WriteParam(m, p.flags);
852 WriteParam(m, p.sent);
853 WriteParam(m, p.receive);
854 WriteParam(m, p.dispatch);
855 WriteParam(m, p.params);
856 }
857 static bool Read(const Message* m, void** iter, param_type* r) {
858 int type;
859 bool result =
860 ReadParam(m, iter, &r->channel) &&
[email protected]25af92052010-03-26 22:21:17861 ReadParam(m, iter, &r->routing_id) &&
[email protected]7d5c3ac2009-02-04 08:58:19862 ReadParam(m, iter, &type) &&
863 ReadParam(m, iter, &r->flags) &&
864 ReadParam(m, iter, &r->sent) &&
865 ReadParam(m, iter, &r->receive) &&
866 ReadParam(m, iter, &r->dispatch) &&
867 ReadParam(m, iter, &r->params);
868 r->type = static_cast<uint16>(type);
869 return result;
870 }
871 static void Log(const param_type& p, std::wstring* l) {
872 // Doesn't make sense to implement this!
873 }
874};
875
[email protected]eb47a132009-03-04 00:39:56876template <>
[email protected]503683f2009-02-26 09:13:01877struct ParamTraits<Message> {
878 static void Write(Message* m, const Message& p) {
879 m->WriteInt(p.size());
880 m->WriteData(reinterpret_cast<const char*>(p.data()), p.size());
881 }
882 static bool Read(const Message* m, void** iter, Message* r) {
883 int size;
884 if (!m->ReadInt(iter, &size))
885 return false;
886 const char* data;
887 if (!m->ReadData(iter, &data, &size))
888 return false;
889 *r = Message(data, size);
890 return true;
891 }
892 static void Log(const Message& p, std::wstring* l) {
893 l->append(L"<IPC::Message>");
894 }
895};
896
897template <>
[email protected]7d5c3ac2009-02-04 08:58:19898struct ParamTraits<Tuple0> {
899 typedef Tuple0 param_type;
900 static void Write(Message* m, const param_type& p) {
901 }
902 static bool Read(const Message* m, void** iter, param_type* r) {
903 return true;
904 }
905 static void Log(const param_type& p, std::wstring* l) {
906 }
907};
908
909template <class A>
910struct ParamTraits< Tuple1<A> > {
911 typedef Tuple1<A> param_type;
912 static void Write(Message* m, const param_type& p) {
913 WriteParam(m, p.a);
914 }
915 static bool Read(const Message* m, void** iter, param_type* r) {
916 return ReadParam(m, iter, &r->a);
917 }
918 static void Log(const param_type& p, std::wstring* l) {
919 LogParam(p.a, l);
920 }
921};
922
923template <class A, class B>
924struct ParamTraits< Tuple2<A, B> > {
925 typedef Tuple2<A, B> param_type;
926 static void Write(Message* m, const param_type& p) {
927 WriteParam(m, p.a);
928 WriteParam(m, p.b);
929 }
930 static bool Read(const Message* m, void** iter, param_type* r) {
931 return (ReadParam(m, iter, &r->a) &&
932 ReadParam(m, iter, &r->b));
933 }
934 static void Log(const param_type& p, std::wstring* l) {
935 LogParam(p.a, l);
936 l->append(L", ");
937 LogParam(p.b, l);
938 }
939};
940
941template <class A, class B, class C>
942struct ParamTraits< Tuple3<A, B, C> > {
943 typedef Tuple3<A, B, C> param_type;
944 static void Write(Message* m, const param_type& p) {
945 WriteParam(m, p.a);
946 WriteParam(m, p.b);
947 WriteParam(m, p.c);
948 }
949 static bool Read(const Message* m, void** iter, param_type* r) {
950 return (ReadParam(m, iter, &r->a) &&
951 ReadParam(m, iter, &r->b) &&
952 ReadParam(m, iter, &r->c));
953 }
954 static void Log(const param_type& p, std::wstring* l) {
955 LogParam(p.a, l);
956 l->append(L", ");
957 LogParam(p.b, l);
958 l->append(L", ");
959 LogParam(p.c, l);
960 }
961};
962
963template <class A, class B, class C, class D>
964struct ParamTraits< Tuple4<A, B, C, D> > {
965 typedef Tuple4<A, B, C, D> param_type;
966 static void Write(Message* m, const param_type& p) {
967 WriteParam(m, p.a);
968 WriteParam(m, p.b);
969 WriteParam(m, p.c);
970 WriteParam(m, p.d);
971 }
972 static bool Read(const Message* m, void** iter, param_type* r) {
973 return (ReadParam(m, iter, &r->a) &&
974 ReadParam(m, iter, &r->b) &&
975 ReadParam(m, iter, &r->c) &&
976 ReadParam(m, iter, &r->d));
977 }
978 static void Log(const param_type& p, std::wstring* l) {
979 LogParam(p.a, l);
980 l->append(L", ");
981 LogParam(p.b, l);
982 l->append(L", ");
983 LogParam(p.c, l);
984 l->append(L", ");
985 LogParam(p.d, l);
986 }
987};
988
989template <class A, class B, class C, class D, class E>
990struct ParamTraits< Tuple5<A, B, C, D, E> > {
991 typedef Tuple5<A, B, C, D, E> param_type;
992 static void Write(Message* m, const param_type& p) {
993 WriteParam(m, p.a);
994 WriteParam(m, p.b);
995 WriteParam(m, p.c);
996 WriteParam(m, p.d);
997 WriteParam(m, p.e);
998 }
999 static bool Read(const Message* m, void** iter, param_type* r) {
1000 return (ReadParam(m, iter, &r->a) &&
1001 ReadParam(m, iter, &r->b) &&
1002 ReadParam(m, iter, &r->c) &&
1003 ReadParam(m, iter, &r->d) &&
1004 ReadParam(m, iter, &r->e));
1005 }
1006 static void Log(const param_type& p, std::wstring* l) {
1007 LogParam(p.a, l);
1008 l->append(L", ");
1009 LogParam(p.b, l);
1010 l->append(L", ");
1011 LogParam(p.c, l);
1012 l->append(L", ");
1013 LogParam(p.d, l);
1014 l->append(L", ");
1015 LogParam(p.e, l);
1016 }
1017};
1018
[email protected]7d5c3ac2009-02-04 08:58:191019//-----------------------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:291020// Generic message subclasses
1021
1022// Used for asynchronous messages.
[email protected]81a34412009-01-05 19:17:241023template <class ParamType>
initial.commit09911bf2008-07-26 23:55:291024class MessageWithTuple : public Message {
1025 public:
[email protected]81a34412009-01-05 19:17:241026 typedef ParamType Param;
[email protected]c2fe31542009-05-20 18:24:141027 typedef typename ParamType::ParamTuple RefParam;
[email protected]81a34412009-01-05 19:17:241028
[email protected]168ae922009-12-04 18:08:451029 MessageWithTuple(int32 routing_id, uint32 type, const RefParam& p)
initial.commit09911bf2008-07-26 23:55:291030 : Message(routing_id, type, PRIORITY_NORMAL) {
1031 WriteParam(this, p);
1032 }
1033
[email protected]7d5c3ac2009-02-04 08:58:191034 static bool Read(const Message* msg, Param* p) {
initial.commit09911bf2008-07-26 23:55:291035 void* iter = NULL;
[email protected]3b8463962009-07-16 06:27:381036 if (ReadParam(msg, &iter, p))
1037 return true;
1038 NOTREACHED() << "Error deserializing message " << msg->type();
1039 return false;
initial.commit09911bf2008-07-26 23:55:291040 }
1041
1042 // Generic dispatcher. Should cover most cases.
1043 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191044 static bool Dispatch(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291045 Param p;
1046 if (Read(msg, &p)) {
1047 DispatchToMethod(obj, func, p);
1048 return true;
1049 }
1050 return false;
1051 }
1052
1053 // The following dispatchers exist for the case where the callback function
1054 // needs the message as well. They assume that "Param" is a type of Tuple
1055 // (except the one arg case, as there is no Tuple1).
1056 template<class T, typename TA>
[email protected]7d5c3ac2009-02-04 08:58:191057 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291058 void (T::*func)(const Message&, TA)) {
1059 Param p;
1060 if (Read(msg, &p)) {
[email protected]c2fe31542009-05-20 18:24:141061 (obj->*func)(*msg, p.a);
initial.commit09911bf2008-07-26 23:55:291062 return true;
1063 }
1064 return false;
1065 }
1066
1067 template<class T, typename TA, typename TB>
[email protected]7d5c3ac2009-02-04 08:58:191068 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291069 void (T::*func)(const Message&, TA, TB)) {
1070 Param p;
1071 if (Read(msg, &p)) {
1072 (obj->*func)(*msg, p.a, p.b);
1073 return true;
1074 }
1075 return false;
1076 }
1077
1078 template<class T, typename TA, typename TB, typename TC>
[email protected]7d5c3ac2009-02-04 08:58:191079 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291080 void (T::*func)(const Message&, TA, TB, TC)) {
1081 Param p;
1082 if (Read(msg, &p)) {
1083 (obj->*func)(*msg, p.a, p.b, p.c);
1084 return true;
1085 }
1086 return false;
1087 }
1088
1089 template<class T, typename TA, typename TB, typename TC, typename TD>
[email protected]7d5c3ac2009-02-04 08:58:191090 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291091 void (T::*func)(const Message&, TA, TB, TC, TD)) {
1092 Param p;
1093 if (Read(msg, &p)) {
1094 (obj->*func)(*msg, p.a, p.b, p.c, p.d);
1095 return true;
1096 }
1097 return false;
1098 }
1099
1100 template<class T, typename TA, typename TB, typename TC, typename TD,
1101 typename TE>
[email protected]7d5c3ac2009-02-04 08:58:191102 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291103 void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
1104 Param p;
1105 if (Read(msg, &p)) {
1106 (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
1107 return true;
1108 }
1109 return false;
1110 }
1111
[email protected]7d5c3ac2009-02-04 08:58:191112 static void Log(const Message* msg, std::wstring* l) {
initial.commit09911bf2008-07-26 23:55:291113 Param p;
1114 if (Read(msg, &p))
1115 LogParam(p, l);
1116 }
[email protected]deb57402009-02-06 01:35:301117
1118 // Functions used to do manual unpacking. Only used by the automation code,
1119 // these should go away once that code uses SyncChannel.
1120 template<typename TA, typename TB>
1121 static bool Read(const IPC::Message* msg, TA* a, TB* b) {
1122 ParamType params;
1123 if (!Read(msg, &params))
1124 return false;
1125 *a = params.a;
1126 *b = params.b;
1127 return true;
1128 }
1129
1130 template<typename TA, typename TB, typename TC>
1131 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
1132 ParamType params;
1133 if (!Read(msg, &params))
1134 return false;
1135 *a = params.a;
1136 *b = params.b;
1137 *c = params.c;
1138 return true;
1139 }
1140
1141 template<typename TA, typename TB, typename TC, typename TD>
1142 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
1143 ParamType params;
1144 if (!Read(msg, &params))
1145 return false;
1146 *a = params.a;
1147 *b = params.b;
1148 *c = params.c;
1149 *d = params.d;
1150 return true;
1151 }
1152
1153 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1154 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
1155 ParamType params;
1156 if (!Read(msg, &params))
1157 return false;
1158 *a = params.a;
1159 *b = params.b;
1160 *c = params.c;
1161 *d = params.d;
1162 *e = params.e;
1163 return true;
1164 }
initial.commit09911bf2008-07-26 23:55:291165};
1166
1167// This class assumes that its template argument is a RefTuple (a Tuple with
1168// reference elements).
1169template <class RefTuple>
1170class ParamDeserializer : public MessageReplyDeserializer {
1171 public:
[email protected]e1981f432008-08-12 15:22:131172 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
initial.commit09911bf2008-07-26 23:55:291173
1174 bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
1175 return ReadParam(&msg, &iter, &out_);
1176 }
1177
1178 RefTuple out_;
1179};
1180
1181// defined in ipc_logging.cc
[email protected]9a3a293b2009-06-04 22:28:161182void GenerateLogData(const std::string& channel, const Message& message,
initial.commit09911bf2008-07-26 23:55:291183 LogData* data);
1184
1185// Used for synchronous messages.
[email protected]75e5a872009-04-02 23:56:111186template <class SendParamType, class ReplyParamType>
initial.commit09911bf2008-07-26 23:55:291187class MessageWithReply : public SyncMessage {
1188 public:
[email protected]75e5a872009-04-02 23:56:111189 typedef SendParamType SendParam;
[email protected]c2fe31542009-05-20 18:24:141190 typedef typename SendParam::ParamTuple RefSendParam;
[email protected]75e5a872009-04-02 23:56:111191 typedef ReplyParamType ReplyParam;
1192
[email protected]168ae922009-12-04 18:08:451193 MessageWithReply(int32 routing_id, uint32 type,
[email protected]c2fe31542009-05-20 18:24:141194 const RefSendParam& send, const ReplyParam& reply)
initial.commit09911bf2008-07-26 23:55:291195 : SyncMessage(routing_id, type, PRIORITY_NORMAL,
1196 new ParamDeserializer<ReplyParam>(reply)) {
1197 WriteParam(this, send);
1198 }
1199
[email protected]7d5c3ac2009-02-04 08:58:191200 static void Log(const Message* msg, std::wstring* l) {
initial.commit09911bf2008-07-26 23:55:291201 if (msg->is_sync()) {
1202 SendParam p;
1203 void* iter = SyncMessage::GetDataIterator(msg);
[email protected]1e86aa62009-04-24 21:22:331204 if (ReadParam(msg, &iter, &p))
1205 LogParam(p, l);
initial.commit09911bf2008-07-26 23:55:291206
[email protected]1156f7b2008-12-04 19:13:591207#if defined(IPC_MESSAGE_LOG_ENABLED)
initial.commit09911bf2008-07-26 23:55:291208 const std::wstring& output_params = msg->output_params();
1209 if (!l->empty() && !output_params.empty())
1210 l->append(L", ");
1211
1212 l->append(output_params);
[email protected]2a34f9c2008-12-04 19:12:041213#endif
initial.commit09911bf2008-07-26 23:55:291214 } else {
1215 // This is an outgoing reply. Now that we have the output parameters, we
1216 // can finally log the message.
[email protected]d4651ff2008-12-02 16:51:581217 typename ReplyParam::ValueTuple p;
initial.commit09911bf2008-07-26 23:55:291218 void* iter = SyncMessage::GetDataIterator(msg);
[email protected]1e86aa62009-04-24 21:22:331219 if (ReadParam(msg, &iter, &p))
1220 LogParam(p, l);
initial.commit09911bf2008-07-26 23:55:291221 }
1222 }
1223
1224 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191225 static bool Dispatch(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291226 SendParam send_params;
1227 void* iter = GetDataIterator(msg);
1228 Message* reply = GenerateReply(msg);
1229 bool error;
1230 if (ReadParam(msg, &iter, &send_params)) {
[email protected]d4651ff2008-12-02 16:51:581231 typename ReplyParam::ValueTuple reply_params;
initial.commit09911bf2008-07-26 23:55:291232 DispatchToMethod(obj, func, send_params, &reply_params);
1233 WriteParam(reply, reply_params);
1234 error = false;
1235#ifdef IPC_MESSAGE_LOG_ENABLED
1236 if (msg->received_time() != 0) {
1237 std::wstring output_params;
1238 LogParam(reply_params, &output_params);
1239 msg->set_output_params(output_params);
1240 }
1241#endif
1242 } else {
1243 NOTREACHED() << "Error deserializing message " << msg->type();
1244 reply->set_reply_error();
1245 error = true;
1246 }
1247
1248 obj->Send(reply);
1249 return !error;
1250 }
1251
1252 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191253 static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291254 SendParam send_params;
1255 void* iter = GetDataIterator(msg);
1256 Message* reply = GenerateReply(msg);
1257 bool error;
1258 if (ReadParam(msg, &iter, &send_params)) {
1259 Tuple1<Message&> t = MakeRefTuple(*reply);
1260
1261#ifdef IPC_MESSAGE_LOG_ENABLED
1262 if (msg->sent_time()) {
1263 // Don't log the sync message after dispatch, as we don't have the
1264 // output parameters at that point. Instead, save its data and log it
1265 // with the outgoing reply message when it's sent.
1266 LogData* data = new LogData;
[email protected]9a3a293b2009-06-04 22:28:161267 GenerateLogData("", *msg, data);
initial.commit09911bf2008-07-26 23:55:291268 msg->set_dont_log();
1269 reply->set_sync_log_data(data);
1270 }
1271#endif
1272 DispatchToMethod(obj, func, send_params, &t);
1273 error = false;
1274 } else {
1275 NOTREACHED() << "Error deserializing message " << msg->type();
1276 reply->set_reply_error();
1277 obj->Send(reply);
1278 error = true;
1279 }
1280 return !error;
1281 }
1282
1283 template<typename TA>
1284 static void WriteReplyParams(Message* reply, TA a) {
1285 ReplyParam p(a);
1286 WriteParam(reply, p);
1287 }
1288
1289 template<typename TA, typename TB>
1290 static void WriteReplyParams(Message* reply, TA a, TB b) {
1291 ReplyParam p(a, b);
1292 WriteParam(reply, p);
1293 }
1294
1295 template<typename TA, typename TB, typename TC>
1296 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
1297 ReplyParam p(a, b, c);
1298 WriteParam(reply, p);
1299 }
1300
1301 template<typename TA, typename TB, typename TC, typename TD>
1302 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
1303 ReplyParam p(a, b, c, d);
1304 WriteParam(reply, p);
1305 }
1306
1307 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1308 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
1309 ReplyParam p(a, b, c, d, e);
1310 WriteParam(reply, p);
1311 }
1312};
1313
[email protected]7d5c3ac2009-02-04 08:58:191314//-----------------------------------------------------------------------------
1315
[email protected]3178f4e22008-08-05 21:20:411316} // namespace IPC
initial.commit09911bf2008-07-26 23:55:291317
[email protected]946d1b22009-07-22 23:57:211318#endif // IPC_IPC_MESSAGE_UTILS_H_