blob: c3a9ca4629c8a9485c6ad771c8c13a8e494405f5 [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]dce5df52009-06-29 17:58:2515#include "base/format_macros.h"
[email protected]eb47a132009-03-04 00:39:5616#include "base/string16.h"
[email protected]dce5df52009-06-29 17:58:2517#include "base/string_util.h"
initial.commit09911bf2008-07-26 23:55:2918#include "base/tuple.h"
[email protected]0cfe5dae2010-08-17 00:24:5419#include "ipc/ipc_sync_message.h"
[email protected]55b4e212010-08-13 20:43:5820
[email protected]7a4de7a62010-08-17 18:38:2421#if defined(COMPILER_GCC)
22// GCC "helpfully" tries to inline template methods in release mode. Except we
23// want the majority of the template junk being expanded once in the
24// implementation file (and only provide the definitions in
25// ipc_message_utils_impl.h in those files) and exported, instead of expanded
26// at every call site. Special note: GCC happily accepts the attribute before
27// the method declaration, but only acts on it if it is after.
28#define IPC_MSG_NOINLINE __attribute__((noinline));
29#elif defined(COMPILER_MSVC)
30// MSVC++ doesn't do this.
31#define IPC_MSG_NOINLINE
32#else
33#error "Please add the noinline property for your new compiler here."
34#endif
35
[email protected]f91cb992009-02-04 20:10:1236// Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
37// base. Messages have unique IDs across channels in order for the IPC logging
38// code to figure out the message class from its ID.
39enum IPCMessageStart {
40 // By using a start value of 0 for automation messages, we keep backward
41 // compatibility with old builds.
42 AutomationMsgStart = 0,
43 ViewMsgStart,
44 ViewHostMsgStart,
45 PluginProcessMsgStart,
46 PluginProcessHostMsgStart,
47 PluginMsgStart,
48 PluginHostMsgStart,
[email protected]96da6962010-05-13 19:10:3449 ProfileImportProcessMsgStart,
50 ProfileImportProcessHostMsgStart,
[email protected]f91cb992009-02-04 20:10:1251 NPObjectMsgStart,
52 TestMsgStart,
[email protected]503683f2009-02-26 09:13:0153 DevToolsAgentMsgStart,
54 DevToolsClientMsgStart,
[email protected]eb47a132009-03-04 00:39:5655 WorkerProcessMsgStart,
56 WorkerProcessHostMsgStart,
57 WorkerMsgStart,
58 WorkerHostMsgStart,
[email protected]d032f492009-09-29 00:33:4659 NaClProcessMsgStart,
[email protected]246a70452010-03-05 21:53:5060 GpuCommandBufferMsgStart,
[email protected]60f14392009-12-15 20:46:3261 UtilityMsgStart,
62 UtilityHostMsgStart,
[email protected]c0fc0942010-01-13 00:55:3763 GpuMsgStart,
64 GpuHostMsgStart,
[email protected]246a70452010-03-05 21:53:5065 GpuChannelMsgStart,
[email protected]ee68378a2010-08-10 01:05:4166 GpuVideoDecoderHostMsgStart,
67 GpuVideoDecoderMsgStart,
[email protected]38fe1962010-07-31 07:57:0068 ServiceMsgStart,
69 ServiceHostMsgStart,
[email protected]f91cb992009-02-04 20:10:1270 // NOTE: When you add a new message class, also update
71 // IPCStatusView::IPCStatusView to ensure logging works.
[email protected]f91cb992009-02-04 20:10:1272 LastMsgIndex
73};
74
[email protected]7a4de7a62010-08-17 18:38:2475class DictionaryValue;
76class FilePath;
77class ListValue;
78class NullableString16;
79
80namespace base {
81class Time;
82struct FileDescriptor;
83}
84
initial.commit09911bf2008-07-26 23:55:2985namespace IPC {
86
[email protected]7a4de7a62010-08-17 18:38:2487struct ChannelHandle;
88
initial.commit09911bf2008-07-26 23:55:2989//-----------------------------------------------------------------------------
90// An iterator class for reading the fields contained within a Message.
91
92class MessageIterator {
93 public:
[email protected]e1981f432008-08-12 15:22:1394 explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
initial.commit09911bf2008-07-26 23:55:2995 }
96 int NextInt() const {
[email protected]9422b7dc2009-12-30 20:09:0297 int val = -1;
initial.commit09911bf2008-07-26 23:55:2998 if (!msg_.ReadInt(&iter_, &val))
99 NOTREACHED();
100 return val;
101 }
initial.commit09911bf2008-07-26 23:55:29102 const std::string NextString() const {
103 std::string val;
104 if (!msg_.ReadString(&iter_, &val))
105 NOTREACHED();
106 return val;
107 }
108 const std::wstring NextWString() const {
109 std::wstring val;
110 if (!msg_.ReadWString(&iter_, &val))
111 NOTREACHED();
112 return val;
113 }
[email protected]225c8f52010-02-05 22:23:20114 void NextData(const char** data, int* length) const {
initial.commit09911bf2008-07-26 23:55:29115 if (!msg_.ReadData(&iter_, data, length)) {
116 NOTREACHED();
117 }
118 }
119 private:
120 const Message& msg_;
121 mutable void* iter_;
122};
123
124//-----------------------------------------------------------------------------
[email protected]7d5c3ac2009-02-04 08:58:19125// ParamTraits specializations, etc.
126
[email protected]7b291f92009-08-14 05:43:53127template <class P> struct ParamTraits {
128};
129
130template <class P>
131struct SimilarTypeTraits {
132 typedef P Type;
133};
[email protected]7d5c3ac2009-02-04 08:58:19134
135template <class P>
136static inline void WriteParam(Message* m, const P& p) {
[email protected]7b291f92009-08-14 05:43:53137 typedef typename SimilarTypeTraits<P>::Type Type;
[email protected]46ce5b562010-06-16 18:39:53138 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
[email protected]7d5c3ac2009-02-04 08:58:19139}
140
141template <class P>
[email protected]1e86aa62009-04-24 21:22:33142static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
143 P* p) {
[email protected]7b291f92009-08-14 05:43:53144 typedef typename SimilarTypeTraits<P>::Type Type;
145 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
[email protected]7d5c3ac2009-02-04 08:58:19146}
147
148template <class P>
[email protected]252cad62010-08-18 18:33:57149static inline void LogParam(const P& p, std::string* l) {
[email protected]7b291f92009-08-14 05:43:53150 typedef typename SimilarTypeTraits<P>::Type Type;
[email protected]46ce5b562010-06-16 18:39:53151 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
[email protected]7d5c3ac2009-02-04 08:58:19152}
153
154template <>
155struct ParamTraits<bool> {
156 typedef bool param_type;
157 static void Write(Message* m, const param_type& p) {
158 m->WriteBool(p);
159 }
160 static bool Read(const Message* m, void** iter, param_type* r) {
161 return m->ReadBool(iter, r);
162 }
[email protected]252cad62010-08-18 18:33:57163 static void Log(const param_type& p, std::string* l) {
164 l->append(p ? "true" : "false");
[email protected]7d5c3ac2009-02-04 08:58:19165 }
166};
167
168template <>
169struct ParamTraits<int> {
170 typedef int param_type;
171 static void Write(Message* m, const param_type& p) {
172 m->WriteInt(p);
173 }
174 static bool Read(const Message* m, void** iter, param_type* r) {
175 return m->ReadInt(iter, r);
176 }
[email protected]252cad62010-08-18 18:33:57177 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19178};
179
180template <>
[email protected]63263f92009-07-28 19:35:08181struct ParamTraits<unsigned int> {
182 typedef unsigned int param_type;
183 static void Write(Message* m, const param_type& p) {
184 m->WriteInt(p);
185 }
186 static bool Read(const Message* m, void** iter, param_type* r) {
187 return m->ReadInt(iter, reinterpret_cast<int*>(r));
188 }
[email protected]252cad62010-08-18 18:33:57189 static void Log(const param_type& p, std::string* l);
[email protected]63263f92009-07-28 19:35:08190};
191
192template <>
[email protected]7d5c3ac2009-02-04 08:58:19193struct ParamTraits<long> {
194 typedef long param_type;
195 static void Write(Message* m, const param_type& p) {
196 m->WriteLong(p);
197 }
198 static bool Read(const Message* m, void** iter, param_type* r) {
199 return m->ReadLong(iter, r);
200 }
[email protected]252cad62010-08-18 18:33:57201 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19202};
203
[email protected]140c3032009-06-26 18:22:54204template <>
205struct ParamTraits<unsigned long> {
206 typedef unsigned long param_type;
207 static void Write(Message* m, const param_type& p) {
208 m->WriteLong(p);
209 }
210 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]63263f92009-07-28 19:35:08211 return m->ReadLong(iter, reinterpret_cast<long*>(r));
[email protected]140c3032009-06-26 18:22:54212 }
[email protected]252cad62010-08-18 18:33:57213 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19214};
215
216template <>
[email protected]63263f92009-07-28 19:35:08217struct ParamTraits<long long> {
218 typedef long long param_type;
[email protected]7d5c3ac2009-02-04 08:58:19219 static void Write(Message* m, const param_type& p) {
220 m->WriteInt64(static_cast<int64>(p));
221 }
222 static bool Read(const Message* m, void** iter, param_type* r) {
223 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
224 }
[email protected]252cad62010-08-18 18:33:57225 static void Log(const param_type& p, std::string* l);
[email protected]63263f92009-07-28 19:35:08226};
227
228template <>
229struct ParamTraits<unsigned long long> {
230 typedef unsigned long long param_type;
231 static void Write(Message* m, const param_type& p) {
232 m->WriteInt64(p);
233 }
234 static bool Read(const Message* m, void** iter, param_type* r) {
235 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
236 }
[email protected]252cad62010-08-18 18:33:57237 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19238};
239
[email protected]20199662010-06-17 03:29:26240// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
241// should be sure to check the sanity of these values after receiving them over
242// IPC.
243template <>
244struct ParamTraits<float> {
245 typedef float param_type;
246 static void Write(Message* m, const param_type& p) {
247 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
248 }
249 static bool Read(const Message* m, void** iter, param_type* r) {
250 const char *data;
251 int data_size;
252 if (!m->ReadData(iter, &data, &data_size) ||
253 data_size != sizeof(param_type)) {
254 NOTREACHED();
255 return false;
256 }
257 memcpy(r, data, sizeof(param_type));
258 return true;
259 }
[email protected]252cad62010-08-18 18:33:57260 static void Log(const param_type& p, std::string* l) {
261 l->append(StringPrintf("%e", p));
[email protected]20199662010-06-17 03:29:26262 }
263};
264
[email protected]7d5c3ac2009-02-04 08:58:19265template <>
266struct 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;
[email protected]20199662010-06-17 03:29:26273 int data_size;
274 if (!m->ReadData(iter, &data, &data_size) ||
275 data_size != sizeof(param_type)) {
[email protected]7d5c3ac2009-02-04 08:58:19276 NOTREACHED();
[email protected]20199662010-06-17 03:29:26277 return false;
[email protected]7d5c3ac2009-02-04 08:58:19278 }
[email protected]20199662010-06-17 03:29:26279 memcpy(r, data, sizeof(param_type));
280 return true;
[email protected]7d5c3ac2009-02-04 08:58:19281 }
[email protected]252cad62010-08-18 18:33:57282 static void Log(const param_type& p, std::string* l) {
283 l->append(StringPrintf("%e", p));
[email protected]7d5c3ac2009-02-04 08:58:19284 }
285};
286
287template <>
288struct ParamTraits<wchar_t> {
289 typedef wchar_t param_type;
290 static void Write(Message* m, const param_type& p) {
291 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
292 }
293 static bool Read(const Message* m, void** iter, param_type* r) {
294 const char *data;
295 int data_size = 0;
296 bool result = m->ReadData(iter, &data, &data_size);
297 if (result && data_size == sizeof(param_type)) {
298 memcpy(r, data, sizeof(param_type));
299 } else {
300 result = false;
301 NOTREACHED();
302 }
303
304 return result;
305 }
[email protected]252cad62010-08-18 18:33:57306 static void Log(const param_type& p, std::string* l) {
307 l->append(StringPrintf("%lc", p));
[email protected]7d5c3ac2009-02-04 08:58:19308 }
309};
310
311template <>
312struct ParamTraits<base::Time> {
313 typedef base::Time param_type;
[email protected]7a4de7a62010-08-17 18:38:24314 static void Write(Message* m, const param_type& p);
315 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57316 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19317};
318
319#if defined(OS_WIN)
320template <>
321struct ParamTraits<LOGFONT> {
322 typedef LOGFONT param_type;
323 static void Write(Message* m, const param_type& p) {
324 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
325 }
326 static bool Read(const Message* m, void** iter, param_type* r) {
327 const char *data;
328 int data_size = 0;
329 bool result = m->ReadData(iter, &data, &data_size);
330 if (result && data_size == sizeof(LOGFONT)) {
331 memcpy(r, data, sizeof(LOGFONT));
332 } else {
333 result = false;
334 NOTREACHED();
335 }
336
337 return result;
338 }
[email protected]252cad62010-08-18 18:33:57339 static void Log(const param_type& p, std::string* l) {
340 l->append(StringPrintf("<LOGFONT>"));
[email protected]7d5c3ac2009-02-04 08:58:19341 }
342};
343
344template <>
345struct ParamTraits<MSG> {
346 typedef MSG param_type;
347 static void Write(Message* m, const param_type& p) {
348 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
349 }
350 static bool Read(const Message* m, void** iter, param_type* r) {
351 const char *data;
352 int data_size = 0;
353 bool result = m->ReadData(iter, &data, &data_size);
354 if (result && data_size == sizeof(MSG)) {
355 memcpy(r, data, sizeof(MSG));
356 } else {
357 result = false;
358 NOTREACHED();
359 }
360
361 return result;
362 }
[email protected]252cad62010-08-18 18:33:57363 static void Log(const param_type& p, std::string* l) {
364 l->append("<MSG>");
[email protected]7a4de7a62010-08-17 18:38:24365 }
[email protected]7d5c3ac2009-02-04 08:58:19366};
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);
[email protected]252cad62010-08-18 18:33:57374 static void Log(const param_type& p, std::string* l);
[email protected]584f2b22009-05-21 01:01:59375};
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);
[email protected]252cad62010-08-18 18:33:57382 static void Log(const param_type& p, std::string* l);
[email protected]584f2b22009-05-21 01:01:59383};
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 }
[email protected]252cad62010-08-18 18:33:57394 static void Log(const param_type& p, std::string* l) {
395 l->append(p);
[email protected]7d5c3ac2009-02-04 08:58:19396 }
397};
398
[email protected]3dd7a7a2009-07-27 21:09:07399template<typename CharType>
[email protected]252cad62010-08-18 18:33:57400static void LogBytes(const std::vector<CharType>& data, std::string* out) {
[email protected]3dd7a7a2009-07-27 21:09:07401#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
[email protected]252cad62010-08-18 18:33:57412 out->append(StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
[email protected]3dd7a7a2009-07-27 21:09:07413 }
414 if (data.size() > kMaxBytesToLog) {
415 out->append(
[email protected]252cad62010-08-18 18:33:57416 StringPrintf(" and %u more bytes",
[email protected]3dd7a7a2009-07-27 21:09:07417 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 }
[email protected]252cad62010-08-18 18:33:57443 static void Log(const param_type& p, std::string* 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 }
[email protected]252cad62010-08-18 18:33:57468 static void Log(const param_type& p, std::string* 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 }
[email protected]252cad62010-08-18 18:33:57496 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19497 for (size_t i = 0; i < p.size(); ++i) {
498 if (i != 0)
[email protected]252cad62010-08-18 18:33:57499 l->append(" ");
[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 }
[email protected]252cad62010-08-18 18:33:57526 static void Log(const param_type& p, std::string* l) {
527 l->append("<std::set>");
[email protected]96da6962010-05-13 19:10:34528 }
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 }
[email protected]252cad62010-08-18 18:33:57557 static void Log(const param_type& p, std::string* l) {
558 l->append("<std::map>");
[email protected]7d5c3ac2009-02-04 08:58:19559 }
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 }
[email protected]252cad62010-08-18 18:33:57572 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19573};
574
[email protected]a5da6d612009-08-04 02:00:56575template <class A, class B>
576struct ParamTraits<std::pair<A, B> > {
577 typedef std::pair<A, B> param_type;
578 static void Write(Message* m, const param_type& p) {
579 WriteParam(m, p.first);
580 WriteParam(m, p.second);
581 }
582 static bool Read(const Message* m, void** iter, param_type* r) {
583 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
584 }
[email protected]252cad62010-08-18 18:33:57585 static void Log(const param_type& p, std::string* l) {
586 l->append("(");
[email protected]a5da6d612009-08-04 02:00:56587 LogParam(p.first, l);
[email protected]252cad62010-08-18 18:33:57588 l->append(", ");
[email protected]a5da6d612009-08-04 02:00:56589 LogParam(p.second, l);
[email protected]252cad62010-08-18 18:33:57590 l->append(")");
[email protected]a5da6d612009-08-04 02:00:56591 }
592};
593
[email protected]15bf8712009-08-27 00:55:02594template <>
595struct ParamTraits<NullableString16> {
596 typedef NullableString16 param_type;
[email protected]7a4de7a62010-08-17 18:38:24597 static void Write(Message* m, const param_type& p);
598 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57599 static void Log(const param_type& p, std::string* l);
[email protected]15bf8712009-08-27 00:55:02600};
601
[email protected]eb47a132009-03-04 00:39:56602// If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
603// need this trait.
604#if !defined(WCHAR_T_IS_UTF16)
[email protected]eb47a132009-03-04 00:39:56605template <>
606struct ParamTraits<string16> {
607 typedef string16 param_type;
608 static void Write(Message* m, const param_type& p) {
[email protected]3a2a5d22009-03-04 03:36:36609 m->WriteString16(p);
[email protected]eb47a132009-03-04 00:39:56610 }
611 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]3a2a5d22009-03-04 03:36:36612 return m->ReadString16(iter, r);
[email protected]eb47a132009-03-04 00:39:56613 }
[email protected]252cad62010-08-18 18:33:57614 static void Log(const param_type& p, std::string* l);
[email protected]eb47a132009-03-04 00:39:56615};
[email protected]eb47a132009-03-04 00:39:56616#endif
617
[email protected]7d5c3ac2009-02-04 08:58:19618// and, a few more useful types...
619#if defined(OS_WIN)
620template <>
621struct ParamTraits<HANDLE> {
622 typedef HANDLE param_type;
623 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35624 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
625 // bit systems.
626 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19627 }
628 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35629 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
630 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19631 }
[email protected]252cad62010-08-18 18:33:57632 static void Log(const param_type& p, std::string* l) {
633 l->append(StringPrintf("0x%X", p));
[email protected]7d5c3ac2009-02-04 08:58:19634 }
635};
636
637template <>
638struct ParamTraits<HCURSOR> {
639 typedef HCURSOR param_type;
640 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35641 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19642 }
643 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35644 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
645 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19646 }
[email protected]252cad62010-08-18 18:33:57647 static void Log(const param_type& p, std::string* l) {
648 l->append(StringPrintf("0x%X", p));
[email protected]7d5c3ac2009-02-04 08:58:19649 }
650};
651
652template <>
[email protected]7d5c3ac2009-02-04 08:58:19653struct ParamTraits<HACCEL> {
654 typedef HACCEL param_type;
655 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35656 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19657 }
658 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35659 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
660 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19661 }
662};
663
664template <>
665struct ParamTraits<POINT> {
666 typedef POINT param_type;
667 static void Write(Message* m, const param_type& p) {
668 m->WriteInt(p.x);
669 m->WriteInt(p.y);
670 }
671 static bool Read(const Message* m, void** iter, param_type* r) {
672 int x, y;
673 if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
674 return false;
675 r->x = x;
676 r->y = y;
677 return true;
678 }
[email protected]252cad62010-08-18 18:33:57679 static void Log(const param_type& p, std::string* l) {
680 l->append(StringPrintf("(%d, %d)", p.x, p.y));
[email protected]7d5c3ac2009-02-04 08:58:19681 }
682};
683#endif // defined(OS_WIN)
684
685template <>
686struct ParamTraits<FilePath> {
687 typedef FilePath param_type;
[email protected]7a4de7a62010-08-17 18:38:24688 static void Write(Message* m, const param_type& p);
689 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57690 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19691};
692
[email protected]526776c2009-02-07 00:39:26693#if defined(OS_POSIX)
[email protected]2749885f2009-03-05 21:40:11694// FileDescriptors may be serialised over IPC channels on POSIX. On the
695// receiving side, the FileDescriptor is a valid duplicate of the file
696// descriptor which was transmitted: *it is not just a copy of the integer like
697// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
698// this case, the receiving end will see a value of -1. *Zero is a valid file
699// descriptor*.
700//
701// The received file descriptor will have the |auto_close| flag set to true. The
702// code which handles the message is responsible for taking ownership of it.
703// File descriptors are OS resources and must be closed when no longer needed.
704//
705// When sending a file descriptor, the file descriptor must be valid at the time
706// of transmission. Since transmission is not synchronous, one should consider
707// dup()ing any file descriptors to be transmitted and setting the |auto_close|
708// flag, which causes the file descriptor to be closed after writing.
[email protected]526776c2009-02-07 00:39:26709template<>
[email protected]5fe733de2009-02-11 18:59:20710struct ParamTraits<base::FileDescriptor> {
711 typedef base::FileDescriptor param_type;
[email protected]7a4de7a62010-08-17 18:38:24712 static void Write(Message* m, const param_type& p);
713 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57714 static void Log(const param_type& p, std::string* l);
[email protected]526776c2009-02-07 00:39:26715};
[email protected]379e7a52010-03-09 00:38:41716#endif // defined(OS_POSIX)
[email protected]526776c2009-02-07 00:39:26717
[email protected]d2e884d2009-06-22 20:37:52718// A ChannelHandle is basically a platform-inspecific wrapper around the
719// fact that IPC endpoints are handled specially on POSIX. See above comments
720// on FileDescriptor for more background.
721template<>
722struct ParamTraits<IPC::ChannelHandle> {
723 typedef ChannelHandle param_type;
[email protected]7a4de7a62010-08-17 18:38:24724 static void Write(Message* m, const param_type& p);
725 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57726 static void Log(const param_type& p, std::string* l);
[email protected]d2e884d2009-06-22 20:37:52727};
728
[email protected]7d5c3ac2009-02-04 08:58:19729#if defined(OS_WIN)
730template <>
731struct ParamTraits<XFORM> {
732 typedef XFORM param_type;
733 static void Write(Message* m, const param_type& p) {
734 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
735 }
736 static bool Read(const Message* m, void** iter, param_type* r) {
737 const char *data;
738 int data_size = 0;
739 bool result = m->ReadData(iter, &data, &data_size);
740 if (result && data_size == sizeof(XFORM)) {
741 memcpy(r, data, sizeof(XFORM));
742 } else {
743 result = false;
744 NOTREACHED();
745 }
746
747 return result;
748 }
[email protected]252cad62010-08-18 18:33:57749 static void Log(const param_type& p, std::string* l) {
750 l->append("<XFORM>");
[email protected]7d5c3ac2009-02-04 08:58:19751 }
752};
753#endif // defined(OS_WIN)
754
[email protected]7d5c3ac2009-02-04 08:58:19755struct LogData {
[email protected]9a3a293b2009-06-04 22:28:16756 std::string channel;
[email protected]8bef70e2009-04-14 19:11:24757 int32 routing_id;
[email protected]168ae922009-12-04 18:08:45758 uint32 type; // "User-defined" message type, from ipc_message.h.
[email protected]252cad62010-08-18 18:33:57759 std::string flags;
[email protected]7d5c3ac2009-02-04 08:58:19760 int64 sent; // Time that the message was sent (i.e. at Send()).
761 int64 receive; // Time before it was dispatched (i.e. before calling
762 // OnMessageReceived).
763 int64 dispatch; // Time after it was dispatched (i.e. after calling
764 // OnMessageReceived).
[email protected]252cad62010-08-18 18:33:57765 std::string message_name;
766 std::string params;
[email protected]7d5c3ac2009-02-04 08:58:19767};
768
769template <>
770struct ParamTraits<LogData> {
771 typedef LogData param_type;
772 static void Write(Message* m, const param_type& p) {
773 WriteParam(m, p.channel);
[email protected]8bef70e2009-04-14 19:11:24774 WriteParam(m, p.routing_id);
[email protected]7d5c3ac2009-02-04 08:58:19775 WriteParam(m, static_cast<int>(p.type));
776 WriteParam(m, p.flags);
777 WriteParam(m, p.sent);
778 WriteParam(m, p.receive);
779 WriteParam(m, p.dispatch);
780 WriteParam(m, p.params);
781 }
782 static bool Read(const Message* m, void** iter, param_type* r) {
783 int type;
784 bool result =
785 ReadParam(m, iter, &r->channel) &&
[email protected]25af92052010-03-26 22:21:17786 ReadParam(m, iter, &r->routing_id) &&
[email protected]7d5c3ac2009-02-04 08:58:19787 ReadParam(m, iter, &type) &&
788 ReadParam(m, iter, &r->flags) &&
789 ReadParam(m, iter, &r->sent) &&
790 ReadParam(m, iter, &r->receive) &&
791 ReadParam(m, iter, &r->dispatch) &&
792 ReadParam(m, iter, &r->params);
793 r->type = static_cast<uint16>(type);
794 return result;
795 }
[email protected]252cad62010-08-18 18:33:57796 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19797 // Doesn't make sense to implement this!
798 }
799};
800
[email protected]eb47a132009-03-04 00:39:56801template <>
[email protected]503683f2009-02-26 09:13:01802struct ParamTraits<Message> {
803 static void Write(Message* m, const Message& p) {
804 m->WriteInt(p.size());
805 m->WriteData(reinterpret_cast<const char*>(p.data()), p.size());
806 }
807 static bool Read(const Message* m, void** iter, Message* r) {
808 int size;
809 if (!m->ReadInt(iter, &size))
810 return false;
811 const char* data;
812 if (!m->ReadData(iter, &data, &size))
813 return false;
814 *r = Message(data, size);
815 return true;
816 }
[email protected]252cad62010-08-18 18:33:57817 static void Log(const Message& p, std::string* l) {
818 l->append("<IPC::Message>");
[email protected]503683f2009-02-26 09:13:01819 }
820};
821
822template <>
[email protected]7d5c3ac2009-02-04 08:58:19823struct ParamTraits<Tuple0> {
824 typedef Tuple0 param_type;
825 static void Write(Message* m, const param_type& p) {
826 }
827 static bool Read(const Message* m, void** iter, param_type* r) {
828 return true;
829 }
[email protected]252cad62010-08-18 18:33:57830 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19831 }
832};
833
834template <class A>
835struct ParamTraits< Tuple1<A> > {
836 typedef Tuple1<A> param_type;
837 static void Write(Message* m, const param_type& p) {
838 WriteParam(m, p.a);
839 }
840 static bool Read(const Message* m, void** iter, param_type* r) {
841 return ReadParam(m, iter, &r->a);
842 }
[email protected]252cad62010-08-18 18:33:57843 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19844 LogParam(p.a, l);
845 }
846};
847
848template <class A, class B>
849struct ParamTraits< Tuple2<A, B> > {
850 typedef Tuple2<A, B> param_type;
851 static void Write(Message* m, const param_type& p) {
852 WriteParam(m, p.a);
853 WriteParam(m, p.b);
854 }
855 static bool Read(const Message* m, void** iter, param_type* r) {
856 return (ReadParam(m, iter, &r->a) &&
857 ReadParam(m, iter, &r->b));
858 }
[email protected]252cad62010-08-18 18:33:57859 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19860 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57861 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19862 LogParam(p.b, l);
863 }
864};
865
866template <class A, class B, class C>
867struct ParamTraits< Tuple3<A, B, C> > {
868 typedef Tuple3<A, B, C> param_type;
869 static void Write(Message* m, const param_type& p) {
870 WriteParam(m, p.a);
871 WriteParam(m, p.b);
872 WriteParam(m, p.c);
873 }
874 static bool Read(const Message* m, void** iter, param_type* r) {
875 return (ReadParam(m, iter, &r->a) &&
876 ReadParam(m, iter, &r->b) &&
877 ReadParam(m, iter, &r->c));
878 }
[email protected]252cad62010-08-18 18:33:57879 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19880 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57881 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19882 LogParam(p.b, l);
[email protected]252cad62010-08-18 18:33:57883 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19884 LogParam(p.c, l);
885 }
886};
887
888template <class A, class B, class C, class D>
889struct ParamTraits< Tuple4<A, B, C, D> > {
890 typedef Tuple4<A, B, C, D> param_type;
891 static void Write(Message* m, const param_type& p) {
892 WriteParam(m, p.a);
893 WriteParam(m, p.b);
894 WriteParam(m, p.c);
895 WriteParam(m, p.d);
896 }
897 static bool Read(const Message* m, void** iter, param_type* r) {
898 return (ReadParam(m, iter, &r->a) &&
899 ReadParam(m, iter, &r->b) &&
900 ReadParam(m, iter, &r->c) &&
901 ReadParam(m, iter, &r->d));
902 }
[email protected]252cad62010-08-18 18:33:57903 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19904 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57905 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19906 LogParam(p.b, l);
[email protected]252cad62010-08-18 18:33:57907 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19908 LogParam(p.c, l);
[email protected]252cad62010-08-18 18:33:57909 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19910 LogParam(p.d, l);
911 }
912};
913
914template <class A, class B, class C, class D, class E>
915struct ParamTraits< Tuple5<A, B, C, D, E> > {
916 typedef Tuple5<A, B, C, D, E> param_type;
917 static void Write(Message* m, const param_type& p) {
918 WriteParam(m, p.a);
919 WriteParam(m, p.b);
920 WriteParam(m, p.c);
921 WriteParam(m, p.d);
922 WriteParam(m, p.e);
923 }
924 static bool Read(const Message* m, void** iter, param_type* r) {
925 return (ReadParam(m, iter, &r->a) &&
926 ReadParam(m, iter, &r->b) &&
927 ReadParam(m, iter, &r->c) &&
928 ReadParam(m, iter, &r->d) &&
929 ReadParam(m, iter, &r->e));
930 }
[email protected]252cad62010-08-18 18:33:57931 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19932 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57933 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19934 LogParam(p.b, l);
[email protected]252cad62010-08-18 18:33:57935 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19936 LogParam(p.c, l);
[email protected]252cad62010-08-18 18:33:57937 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19938 LogParam(p.d, l);
[email protected]252cad62010-08-18 18:33:57939 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19940 LogParam(p.e, l);
941 }
942};
943
[email protected]7d5c3ac2009-02-04 08:58:19944//-----------------------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:29945// Generic message subclasses
946
947// Used for asynchronous messages.
[email protected]81a34412009-01-05 19:17:24948template <class ParamType>
initial.commit09911bf2008-07-26 23:55:29949class MessageWithTuple : public Message {
950 public:
[email protected]81a34412009-01-05 19:17:24951 typedef ParamType Param;
[email protected]7a4de7a62010-08-17 18:38:24952 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
[email protected]81a34412009-01-05 19:17:24953
[email protected]7a4de7a62010-08-17 18:38:24954 // The constructor and the Read() method's templated implementations are in
955 // ipc_message_utils_impl.h. The subclass constructor and Log() methods call
956 // the templated versions of these and make sure there are instantiations in
957 // those translation units.
958 MessageWithTuple(int32 routing_id, uint32 type, const RefParam& p);
[email protected]071b4b92010-08-09 16:06:58959
[email protected]7a4de7a62010-08-17 18:38:24960 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
initial.commit09911bf2008-07-26 23:55:29961
962 // Generic dispatcher. Should cover most cases.
963 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:19964 static bool Dispatch(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:29965 Param p;
966 if (Read(msg, &p)) {
967 DispatchToMethod(obj, func, p);
968 return true;
969 }
970 return false;
971 }
972
973 // The following dispatchers exist for the case where the callback function
974 // needs the message as well. They assume that "Param" is a type of Tuple
975 // (except the one arg case, as there is no Tuple1).
976 template<class T, typename TA>
[email protected]7d5c3ac2009-02-04 08:58:19977 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:29978 void (T::*func)(const Message&, TA)) {
979 Param p;
980 if (Read(msg, &p)) {
[email protected]c2fe31542009-05-20 18:24:14981 (obj->*func)(*msg, p.a);
initial.commit09911bf2008-07-26 23:55:29982 return true;
983 }
984 return false;
985 }
986
987 template<class T, typename TA, typename TB>
[email protected]7d5c3ac2009-02-04 08:58:19988 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:29989 void (T::*func)(const Message&, TA, TB)) {
990 Param p;
991 if (Read(msg, &p)) {
992 (obj->*func)(*msg, p.a, p.b);
993 return true;
994 }
995 return false;
996 }
997
998 template<class T, typename TA, typename TB, typename TC>
[email protected]7d5c3ac2009-02-04 08:58:19999 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291000 void (T::*func)(const Message&, TA, TB, TC)) {
1001 Param p;
1002 if (Read(msg, &p)) {
1003 (obj->*func)(*msg, p.a, p.b, p.c);
1004 return true;
1005 }
1006 return false;
1007 }
1008
1009 template<class T, typename TA, typename TB, typename TC, typename TD>
[email protected]7d5c3ac2009-02-04 08:58:191010 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291011 void (T::*func)(const Message&, TA, TB, TC, TD)) {
1012 Param p;
1013 if (Read(msg, &p)) {
1014 (obj->*func)(*msg, p.a, p.b, p.c, p.d);
1015 return true;
1016 }
1017 return false;
1018 }
1019
1020 template<class T, typename TA, typename TB, typename TC, typename TD,
1021 typename TE>
[email protected]7d5c3ac2009-02-04 08:58:191022 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291023 void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
1024 Param p;
1025 if (Read(msg, &p)) {
1026 (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
1027 return true;
1028 }
1029 return false;
1030 }
1031
[email protected]deb57402009-02-06 01:35:301032 // Functions used to do manual unpacking. Only used by the automation code,
1033 // these should go away once that code uses SyncChannel.
1034 template<typename TA, typename TB>
1035 static bool Read(const IPC::Message* msg, TA* a, TB* b) {
1036 ParamType params;
1037 if (!Read(msg, &params))
1038 return false;
1039 *a = params.a;
1040 *b = params.b;
1041 return true;
1042 }
1043
1044 template<typename TA, typename TB, typename TC>
1045 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
1046 ParamType params;
1047 if (!Read(msg, &params))
1048 return false;
1049 *a = params.a;
1050 *b = params.b;
1051 *c = params.c;
1052 return true;
1053 }
1054
1055 template<typename TA, typename TB, typename TC, typename TD>
1056 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
1057 ParamType params;
1058 if (!Read(msg, &params))
1059 return false;
1060 *a = params.a;
1061 *b = params.b;
1062 *c = params.c;
1063 *d = params.d;
1064 return true;
1065 }
1066
1067 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1068 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
1069 ParamType params;
1070 if (!Read(msg, &params))
1071 return false;
1072 *a = params.a;
1073 *b = params.b;
1074 *c = params.c;
1075 *d = params.d;
1076 *e = params.e;
1077 return true;
1078 }
initial.commit09911bf2008-07-26 23:55:291079};
1080
[email protected]7a4de7a62010-08-17 18:38:241081// defined in ipc_logging.cc
1082void GenerateLogData(const std::string& channel, const Message& message,
1083 LogData* data);
1084
1085
1086#if defined(IPC_MESSAGE_LOG_ENABLED)
[email protected]252cad62010-08-18 18:33:571087inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
1088 const std::string& output_params = msg->output_params();
[email protected]7a4de7a62010-08-17 18:38:241089 if (!l->empty() && !output_params.empty())
[email protected]252cad62010-08-18 18:33:571090 l->append(", ");
[email protected]7a4de7a62010-08-17 18:38:241091
1092 l->append(output_params);
1093}
1094
1095template <class ReplyParamType>
1096inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1097 const Message* msg) {
1098 if (msg->received_time() != 0) {
[email protected]252cad62010-08-18 18:33:571099 std::string output_params;
[email protected]7a4de7a62010-08-17 18:38:241100 LogParam(reply_params, &output_params);
1101 msg->set_output_params(output_params);
1102 }
1103}
1104
1105inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
1106 if (msg->sent_time()) {
1107 // Don't log the sync message after dispatch, as we don't have the
1108 // output parameters at that point. Instead, save its data and log it
1109 // with the outgoing reply message when it's sent.
1110 LogData* data = new LogData;
1111 GenerateLogData("", *msg, data);
1112 msg->set_dont_log();
1113 reply->set_sync_log_data(data);
1114 }
1115}
1116#else
[email protected]252cad62010-08-18 18:33:571117inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
[email protected]7a4de7a62010-08-17 18:38:241118
1119template <class ReplyParamType>
1120inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1121 const Message* msg) {}
1122
1123inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
1124#endif
1125
initial.commit09911bf2008-07-26 23:55:291126// This class assumes that its template argument is a RefTuple (a Tuple with
[email protected]7a4de7a62010-08-17 18:38:241127// reference elements). This would go into ipc_message_utils_impl.h, but it is
1128// also used by chrome_frame.
initial.commit09911bf2008-07-26 23:55:291129template <class RefTuple>
1130class ParamDeserializer : public MessageReplyDeserializer {
1131 public:
[email protected]e1981f432008-08-12 15:22:131132 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
initial.commit09911bf2008-07-26 23:55:291133
1134 bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
1135 return ReadParam(&msg, &iter, &out_);
1136 }
1137
1138 RefTuple out_;
1139};
1140
initial.commit09911bf2008-07-26 23:55:291141// Used for synchronous messages.
[email protected]75e5a872009-04-02 23:56:111142template <class SendParamType, class ReplyParamType>
initial.commit09911bf2008-07-26 23:55:291143class MessageWithReply : public SyncMessage {
1144 public:
[email protected]75e5a872009-04-02 23:56:111145 typedef SendParamType SendParam;
[email protected]7a4de7a62010-08-17 18:38:241146 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
[email protected]75e5a872009-04-02 23:56:111147 typedef ReplyParamType ReplyParam;
1148
[email protected]168ae922009-12-04 18:08:451149 MessageWithReply(int32 routing_id, uint32 type,
[email protected]7a4de7a62010-08-17 18:38:241150 const RefSendParam& send, const ReplyParam& reply);
1151 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
1152 static bool ReadReplyParam(
1153 const Message* msg,
1154 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
initial.commit09911bf2008-07-26 23:55:291155
1156 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191157 static bool Dispatch(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291158 SendParam send_params;
initial.commit09911bf2008-07-26 23:55:291159 Message* reply = GenerateReply(msg);
1160 bool error;
[email protected]7a4de7a62010-08-17 18:38:241161 if (ReadSendParam(msg, &send_params)) {
1162 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
initial.commit09911bf2008-07-26 23:55:291163 DispatchToMethod(obj, func, send_params, &reply_params);
1164 WriteParam(reply, reply_params);
1165 error = false;
[email protected]7a4de7a62010-08-17 18:38:241166 LogReplyParamsToMessage(reply_params, msg);
initial.commit09911bf2008-07-26 23:55:291167 } else {
1168 NOTREACHED() << "Error deserializing message " << msg->type();
1169 reply->set_reply_error();
1170 error = true;
1171 }
1172
1173 obj->Send(reply);
1174 return !error;
1175 }
1176
1177 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191178 static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291179 SendParam send_params;
initial.commit09911bf2008-07-26 23:55:291180 Message* reply = GenerateReply(msg);
1181 bool error;
[email protected]7a4de7a62010-08-17 18:38:241182 if (ReadSendParam(msg, &send_params)) {
initial.commit09911bf2008-07-26 23:55:291183 Tuple1<Message&> t = MakeRefTuple(*reply);
[email protected]7a4de7a62010-08-17 18:38:241184 ConnectMessageAndReply(msg, reply);
initial.commit09911bf2008-07-26 23:55:291185 DispatchToMethod(obj, func, send_params, &t);
1186 error = false;
1187 } else {
1188 NOTREACHED() << "Error deserializing message " << msg->type();
1189 reply->set_reply_error();
1190 obj->Send(reply);
1191 error = true;
1192 }
1193 return !error;
1194 }
1195
1196 template<typename TA>
1197 static void WriteReplyParams(Message* reply, TA a) {
1198 ReplyParam p(a);
1199 WriteParam(reply, p);
1200 }
1201
1202 template<typename TA, typename TB>
1203 static void WriteReplyParams(Message* reply, TA a, TB b) {
1204 ReplyParam p(a, b);
1205 WriteParam(reply, p);
1206 }
1207
1208 template<typename TA, typename TB, typename TC>
1209 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
1210 ReplyParam p(a, b, c);
1211 WriteParam(reply, p);
1212 }
1213
1214 template<typename TA, typename TB, typename TC, typename TD>
1215 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
1216 ReplyParam p(a, b, c, d);
1217 WriteParam(reply, p);
1218 }
1219
1220 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1221 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
1222 ReplyParam p(a, b, c, d, e);
1223 WriteParam(reply, p);
1224 }
1225};
1226
[email protected]7d5c3ac2009-02-04 08:58:191227//-----------------------------------------------------------------------------
1228
[email protected]3178f4e22008-08-05 21:20:411229} // namespace IPC
initial.commit09911bf2008-07-26 23:55:291230
[email protected]946d1b22009-07-22 23:57:211231#endif // IPC_IPC_MESSAGE_UTILS_H_