blob: 75231d825f2b4178b52ce5f1b719b7eb10a7970c [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]939856a2010-08-24 20:29:0219#include "ipc/ipc_param_traits.h"
[email protected]0cfe5dae2010-08-17 00:24:5420#include "ipc/ipc_sync_message.h"
[email protected]55b4e212010-08-13 20:43:5821
[email protected]7a4de7a62010-08-17 18:38:2422#if defined(COMPILER_GCC)
23// GCC "helpfully" tries to inline template methods in release mode. Except we
24// want the majority of the template junk being expanded once in the
25// implementation file (and only provide the definitions in
26// ipc_message_utils_impl.h in those files) and exported, instead of expanded
27// at every call site. Special note: GCC happily accepts the attribute before
28// the method declaration, but only acts on it if it is after.
[email protected]efafbbd2010-08-19 20:23:2529#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
30// Starting in gcc 4.5, the noinline no longer implies the concept covered by
31// the introduced noclone attribute, which will create specialized versions of
32// functions/methods when certain types are constant.
33// www.gnu.org/software/gcc/gcc-4.5/changes.html
34#define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
35#else
[email protected]7a4de7a62010-08-17 18:38:2436#define IPC_MSG_NOINLINE __attribute__((noinline));
[email protected]efafbbd2010-08-19 20:23:2537#endif
[email protected]7a4de7a62010-08-17 18:38:2438#elif defined(COMPILER_MSVC)
39// MSVC++ doesn't do this.
40#define IPC_MSG_NOINLINE
41#else
42#error "Please add the noinline property for your new compiler here."
43#endif
44
[email protected]f91cb992009-02-04 20:10:1245// Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
46// base. Messages have unique IDs across channels in order for the IPC logging
47// code to figure out the message class from its ID.
48enum IPCMessageStart {
[email protected]f91cb992009-02-04 20:10:1249 AutomationMsgStart = 0,
50 ViewMsgStart,
[email protected]f91cb992009-02-04 20:10:1251 PluginMsgStart,
[email protected]21fa3a12010-12-08 23:34:1652 ProfileImportMsgStart,
[email protected]f91cb992009-02-04 20:10:1253 TestMsgStart,
[email protected]21fa3a12010-12-08 23:34:1654 DevToolsMsgStart,
[email protected]eb47a132009-03-04 00:39:5655 WorkerMsgStart,
[email protected]21fa3a12010-12-08 23:34:1656 NaClMsgStart,
[email protected]60f14392009-12-15 20:46:3257 UtilityMsgStart,
[email protected]c0fc0942010-01-13 00:55:3758 GpuMsgStart,
[email protected]38fe1962010-07-31 07:57:0059 ServiceMsgStart,
[email protected]709a847e2010-11-10 01:16:1160 PpapiMsgStart,
[email protected]21fa3a12010-12-08 23:34:1661 FirefoxImporterUnittestMsgStart,
[email protected]9f547bf2010-12-13 17:00:4262 FileUtilitiesMsgStart,
63 MimeRegistryMsgStart,
[email protected]26a9acf2010-12-13 19:35:0564 DatabaseMsgStart,
[email protected]56879f932010-12-13 21:05:3765 DOMStorageMsgStart,
[email protected]2ba871b2010-12-13 21:11:0066 IndexedDBMsgStart,
[email protected]61e78f12010-12-15 21:03:5567 PepperFileMsgStart,
[email protected]ca97f302011-01-20 13:57:0568 SpeechInputMsgStart,
[email protected]f0557932011-01-25 20:20:5169 PepperMsgStart,
[email protected]19d6e1e82011-01-26 05:08:5870 AutoFillMsgStart,
[email protected]f91cb992009-02-04 20:10:1271};
72
[email protected]7a4de7a62010-08-17 18:38:2473class DictionaryValue;
74class FilePath;
75class ListValue;
76class NullableString16;
77
78namespace base {
79class Time;
[email protected]d84e48b2010-10-21 22:04:5280class TimeDelta;
[email protected]7a4de7a62010-08-17 18:38:2481struct FileDescriptor;
82}
83
initial.commit09911bf2008-07-26 23:55:2984namespace IPC {
85
[email protected]7a4de7a62010-08-17 18:38:2486struct ChannelHandle;
87
initial.commit09911bf2008-07-26 23:55:2988//-----------------------------------------------------------------------------
89// An iterator class for reading the fields contained within a Message.
90
91class MessageIterator {
92 public:
[email protected]e1981f432008-08-12 15:22:1393 explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
initial.commit09911bf2008-07-26 23:55:2994 }
95 int NextInt() const {
[email protected]9422b7dc2009-12-30 20:09:0296 int val = -1;
initial.commit09911bf2008-07-26 23:55:2997 if (!msg_.ReadInt(&iter_, &val))
98 NOTREACHED();
99 return val;
100 }
initial.commit09911bf2008-07-26 23:55:29101 const std::string NextString() const {
102 std::string val;
103 if (!msg_.ReadString(&iter_, &val))
104 NOTREACHED();
105 return val;
106 }
107 const std::wstring NextWString() const {
108 std::wstring val;
109 if (!msg_.ReadWString(&iter_, &val))
110 NOTREACHED();
111 return val;
112 }
[email protected]225c8f52010-02-05 22:23:20113 void NextData(const char** data, int* length) const {
initial.commit09911bf2008-07-26 23:55:29114 if (!msg_.ReadData(&iter_, data, length)) {
115 NOTREACHED();
116 }
117 }
118 private:
119 const Message& msg_;
120 mutable void* iter_;
121};
122
123//-----------------------------------------------------------------------------
[email protected]6476c72c2011-02-11 18:46:19124// A dummy struct to place first just to allow leading commas for all
125// members in the macro-generated constructor initializer lists.
126struct NoParams {
127};
128
129//-----------------------------------------------------------------------------
[email protected]7d5c3ac2009-02-04 08:58:19130// ParamTraits specializations, etc.
131
[email protected]7d5c3ac2009-02-04 08:58:19132template <class P>
133static inline void WriteParam(Message* m, const P& p) {
[email protected]7b291f92009-08-14 05:43:53134 typedef typename SimilarTypeTraits<P>::Type Type;
[email protected]46ce5b562010-06-16 18:39:53135 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
[email protected]7d5c3ac2009-02-04 08:58:19136}
137
138template <class P>
[email protected]1e86aa62009-04-24 21:22:33139static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
140 P* p) {
[email protected]7b291f92009-08-14 05:43:53141 typedef typename SimilarTypeTraits<P>::Type Type;
142 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
[email protected]7d5c3ac2009-02-04 08:58:19143}
144
145template <class P>
[email protected]252cad62010-08-18 18:33:57146static inline void LogParam(const P& p, std::string* l) {
[email protected]7b291f92009-08-14 05:43:53147 typedef typename SimilarTypeTraits<P>::Type Type;
[email protected]46ce5b562010-06-16 18:39:53148 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
[email protected]7d5c3ac2009-02-04 08:58:19149}
150
151template <>
152struct ParamTraits<bool> {
153 typedef bool param_type;
154 static void Write(Message* m, const param_type& p) {
155 m->WriteBool(p);
156 }
157 static bool Read(const Message* m, void** iter, param_type* r) {
158 return m->ReadBool(iter, r);
159 }
[email protected]252cad62010-08-18 18:33:57160 static void Log(const param_type& p, std::string* l) {
161 l->append(p ? "true" : "false");
[email protected]7d5c3ac2009-02-04 08:58:19162 }
163};
164
165template <>
166struct ParamTraits<int> {
167 typedef int param_type;
168 static void Write(Message* m, const param_type& p) {
169 m->WriteInt(p);
170 }
171 static bool Read(const Message* m, void** iter, param_type* r) {
172 return m->ReadInt(iter, r);
173 }
[email protected]252cad62010-08-18 18:33:57174 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19175};
176
177template <>
[email protected]63263f92009-07-28 19:35:08178struct ParamTraits<unsigned int> {
179 typedef unsigned int param_type;
180 static void Write(Message* m, const param_type& p) {
181 m->WriteInt(p);
182 }
183 static bool Read(const Message* m, void** iter, param_type* r) {
184 return m->ReadInt(iter, reinterpret_cast<int*>(r));
185 }
[email protected]252cad62010-08-18 18:33:57186 static void Log(const param_type& p, std::string* l);
[email protected]63263f92009-07-28 19:35:08187};
188
189template <>
[email protected]7d5c3ac2009-02-04 08:58:19190struct ParamTraits<long> {
191 typedef long param_type;
192 static void Write(Message* m, const param_type& p) {
193 m->WriteLong(p);
194 }
195 static bool Read(const Message* m, void** iter, param_type* r) {
196 return m->ReadLong(iter, r);
197 }
[email protected]252cad62010-08-18 18:33:57198 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19199};
200
[email protected]140c3032009-06-26 18:22:54201template <>
202struct ParamTraits<unsigned long> {
203 typedef unsigned long param_type;
204 static void Write(Message* m, const param_type& p) {
205 m->WriteLong(p);
206 }
207 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]63263f92009-07-28 19:35:08208 return m->ReadLong(iter, reinterpret_cast<long*>(r));
[email protected]140c3032009-06-26 18:22:54209 }
[email protected]252cad62010-08-18 18:33:57210 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19211};
212
213template <>
[email protected]63263f92009-07-28 19:35:08214struct ParamTraits<long long> {
215 typedef long long param_type;
[email protected]7d5c3ac2009-02-04 08:58:19216 static void Write(Message* m, const param_type& p) {
217 m->WriteInt64(static_cast<int64>(p));
218 }
219 static bool Read(const Message* m, void** iter, param_type* r) {
220 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
221 }
[email protected]252cad62010-08-18 18:33:57222 static void Log(const param_type& p, std::string* l);
[email protected]63263f92009-07-28 19:35:08223};
224
225template <>
226struct ParamTraits<unsigned long long> {
227 typedef unsigned long long param_type;
228 static void Write(Message* m, const param_type& p) {
229 m->WriteInt64(p);
230 }
231 static bool Read(const Message* m, void** iter, param_type* r) {
232 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
233 }
[email protected]252cad62010-08-18 18:33:57234 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19235};
236
[email protected]43a40202010-11-12 16:25:01237template <>
238struct ParamTraits<unsigned short> {
239 typedef unsigned short param_type;
240 static void Write(Message* m, const param_type& p);
241 static bool Read(const Message* m, void** iter, param_type* r);
242 static void Log(const param_type& p, std::string* l);
243};
244
[email protected]20199662010-06-17 03:29:26245// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
246// should be sure to check the sanity of these values after receiving them over
247// IPC.
248template <>
249struct ParamTraits<float> {
250 typedef float param_type;
251 static void Write(Message* m, const param_type& p) {
252 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
253 }
254 static bool Read(const Message* m, void** iter, param_type* r) {
255 const char *data;
256 int data_size;
257 if (!m->ReadData(iter, &data, &data_size) ||
258 data_size != sizeof(param_type)) {
259 NOTREACHED();
260 return false;
261 }
262 memcpy(r, data, sizeof(param_type));
263 return true;
264 }
[email protected]252cad62010-08-18 18:33:57265 static void Log(const param_type& p, std::string* l) {
266 l->append(StringPrintf("%e", p));
[email protected]20199662010-06-17 03:29:26267 }
268};
269
[email protected]7d5c3ac2009-02-04 08:58:19270template <>
271struct ParamTraits<double> {
272 typedef double param_type;
273 static void Write(Message* m, const param_type& p) {
274 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
275 }
276 static bool Read(const Message* m, void** iter, param_type* r) {
277 const char *data;
[email protected]20199662010-06-17 03:29:26278 int data_size;
279 if (!m->ReadData(iter, &data, &data_size) ||
280 data_size != sizeof(param_type)) {
[email protected]7d5c3ac2009-02-04 08:58:19281 NOTREACHED();
[email protected]20199662010-06-17 03:29:26282 return false;
[email protected]7d5c3ac2009-02-04 08:58:19283 }
[email protected]20199662010-06-17 03:29:26284 memcpy(r, data, sizeof(param_type));
285 return true;
[email protected]7d5c3ac2009-02-04 08:58:19286 }
[email protected]252cad62010-08-18 18:33:57287 static void Log(const param_type& p, std::string* l) {
288 l->append(StringPrintf("%e", p));
[email protected]7d5c3ac2009-02-04 08:58:19289 }
290};
291
292template <>
[email protected]7d5c3ac2009-02-04 08:58:19293struct ParamTraits<base::Time> {
294 typedef base::Time param_type;
[email protected]7a4de7a62010-08-17 18:38:24295 static void Write(Message* m, const param_type& p);
296 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57297 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19298};
299
[email protected]d84e48b2010-10-21 22:04:52300template <>
301struct ParamTraits<base::TimeDelta> {
302 typedef base::TimeDelta param_type;
303 static void Write(Message* m, const param_type& p);
304 static bool Read(const Message* m, void** iter, param_type* r);
305 static void Log(const param_type& p, std::string* l);
306};
307
[email protected]7d5c3ac2009-02-04 08:58:19308#if defined(OS_WIN)
309template <>
310struct ParamTraits<LOGFONT> {
311 typedef LOGFONT param_type;
312 static void Write(Message* m, const param_type& p) {
313 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
314 }
315 static bool Read(const Message* m, void** iter, param_type* r) {
316 const char *data;
317 int data_size = 0;
318 bool result = m->ReadData(iter, &data, &data_size);
319 if (result && data_size == sizeof(LOGFONT)) {
320 memcpy(r, data, sizeof(LOGFONT));
321 } else {
322 result = false;
323 NOTREACHED();
324 }
325
326 return result;
327 }
[email protected]252cad62010-08-18 18:33:57328 static void Log(const param_type& p, std::string* l) {
329 l->append(StringPrintf("<LOGFONT>"));
[email protected]7d5c3ac2009-02-04 08:58:19330 }
331};
332
333template <>
334struct ParamTraits<MSG> {
335 typedef MSG param_type;
336 static void Write(Message* m, const param_type& p) {
337 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
338 }
339 static bool Read(const Message* m, void** iter, param_type* r) {
340 const char *data;
341 int data_size = 0;
342 bool result = m->ReadData(iter, &data, &data_size);
343 if (result && data_size == sizeof(MSG)) {
344 memcpy(r, data, sizeof(MSG));
345 } else {
346 result = false;
347 NOTREACHED();
348 }
349
350 return result;
351 }
[email protected]252cad62010-08-18 18:33:57352 static void Log(const param_type& p, std::string* l) {
353 l->append("<MSG>");
[email protected]7a4de7a62010-08-17 18:38:24354 }
[email protected]7d5c3ac2009-02-04 08:58:19355};
356#endif // defined(OS_WIN)
357
358template <>
[email protected]584f2b22009-05-21 01:01:59359struct ParamTraits<DictionaryValue> {
360 typedef DictionaryValue param_type;
361 static void Write(Message* m, const param_type& p);
362 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57363 static void Log(const param_type& p, std::string* l);
[email protected]584f2b22009-05-21 01:01:59364};
365
366template <>
367struct ParamTraits<ListValue> {
368 typedef ListValue param_type;
369 static void Write(Message* m, const param_type& p);
370 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57371 static void Log(const param_type& p, std::string* l);
[email protected]584f2b22009-05-21 01:01:59372};
373
374template <>
[email protected]7d5c3ac2009-02-04 08:58:19375struct ParamTraits<std::string> {
376 typedef std::string param_type;
377 static void Write(Message* m, const param_type& p) {
378 m->WriteString(p);
379 }
380 static bool Read(const Message* m, void** iter, param_type* r) {
381 return m->ReadString(iter, r);
382 }
[email protected]252cad62010-08-18 18:33:57383 static void Log(const param_type& p, std::string* l) {
384 l->append(p);
[email protected]7d5c3ac2009-02-04 08:58:19385 }
386};
387
[email protected]3dd7a7a2009-07-27 21:09:07388template<typename CharType>
[email protected]252cad62010-08-18 18:33:57389static void LogBytes(const std::vector<CharType>& data, std::string* out) {
[email protected]3dd7a7a2009-07-27 21:09:07390#if defined(OS_WIN)
391 // Windows has a GUI for logging, which can handle arbitrary binary data.
392 for (size_t i = 0; i < data.size(); ++i)
393 out->push_back(data[i]);
394#else
395 // On POSIX, we log to stdout, which we assume can display ASCII.
396 static const size_t kMaxBytesToLog = 100;
397 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
398 if (isprint(data[i]))
399 out->push_back(data[i]);
400 else
[email protected]252cad62010-08-18 18:33:57401 out->append(StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
[email protected]3dd7a7a2009-07-27 21:09:07402 }
403 if (data.size() > kMaxBytesToLog) {
404 out->append(
[email protected]252cad62010-08-18 18:33:57405 StringPrintf(" and %u more bytes",
[email protected]3dd7a7a2009-07-27 21:09:07406 static_cast<unsigned>(data.size() - kMaxBytesToLog)));
407 }
408#endif
409}
410
[email protected]7d5c3ac2009-02-04 08:58:19411template <>
412struct ParamTraits<std::vector<unsigned char> > {
413 typedef std::vector<unsigned char> param_type;
414 static void Write(Message* m, const param_type& p) {
415 if (p.size() == 0) {
416 m->WriteData(NULL, 0);
417 } else {
418 m->WriteData(reinterpret_cast<const char*>(&p.front()),
419 static_cast<int>(p.size()));
420 }
421 }
422 static bool Read(const Message* m, void** iter, param_type* r) {
423 const char *data;
424 int data_size = 0;
425 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
426 return false;
427 r->resize(data_size);
428 if (data_size)
429 memcpy(&r->front(), data, data_size);
430 return true;
431 }
[email protected]252cad62010-08-18 18:33:57432 static void Log(const param_type& p, std::string* l) {
[email protected]3dd7a7a2009-07-27 21:09:07433 LogBytes(p, l);
[email protected]7d5c3ac2009-02-04 08:58:19434 }
435};
436
437template <>
438struct ParamTraits<std::vector<char> > {
439 typedef std::vector<char> param_type;
440 static void Write(Message* m, const param_type& p) {
441 if (p.size() == 0) {
442 m->WriteData(NULL, 0);
443 } else {
444 m->WriteData(&p.front(), static_cast<int>(p.size()));
445 }
446 }
447 static bool Read(const Message* m, void** iter, param_type* r) {
448 const char *data;
449 int data_size = 0;
450 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
451 return false;
452 r->resize(data_size);
453 if (data_size)
454 memcpy(&r->front(), data, data_size);
455 return true;
456 }
[email protected]252cad62010-08-18 18:33:57457 static void Log(const param_type& p, std::string* l) {
[email protected]3dd7a7a2009-07-27 21:09:07458 LogBytes(p, l);
[email protected]7d5c3ac2009-02-04 08:58:19459 }
460};
461
462template <class P>
463struct ParamTraits<std::vector<P> > {
464 typedef std::vector<P> param_type;
465 static void Write(Message* m, const param_type& p) {
466 WriteParam(m, static_cast<int>(p.size()));
467 for (size_t i = 0; i < p.size(); i++)
468 WriteParam(m, p[i]);
469 }
470 static bool Read(const Message* m, void** iter, param_type* r) {
471 int size;
[email protected]86440f52009-12-31 05:17:23472 // ReadLength() checks for < 0 itself.
[email protected]7d5c3ac2009-02-04 08:58:19473 if (!m->ReadLength(iter, &size))
474 return false;
475 // Resizing beforehand is not safe, see BUG 1006367 for details.
[email protected]86440f52009-12-31 05:17:23476 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
477 return false;
478 r->resize(size);
479 for (int i = 0; i < size; i++) {
480 if (!ReadParam(m, iter, &(*r)[i]))
481 return false;
[email protected]7d5c3ac2009-02-04 08:58:19482 }
483 return true;
484 }
[email protected]252cad62010-08-18 18:33:57485 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19486 for (size_t i = 0; i < p.size(); ++i) {
487 if (i != 0)
[email protected]252cad62010-08-18 18:33:57488 l->append(" ");
[email protected]7d5c3ac2009-02-04 08:58:19489 LogParam((p[i]), l);
490 }
491 }
492};
493
[email protected]96da6962010-05-13 19:10:34494template <class P>
495struct ParamTraits<std::set<P> > {
496 typedef std::set<P> param_type;
497 static void Write(Message* m, const param_type& p) {
498 WriteParam(m, static_cast<int>(p.size()));
499 typename param_type::const_iterator iter;
500 for (iter = p.begin(); iter != p.end(); ++iter)
501 WriteParam(m, *iter);
502 }
503 static bool Read(const Message* m, void** iter, param_type* r) {
504 int size;
505 if (!m->ReadLength(iter, &size))
506 return false;
507 for (int i = 0; i < size; ++i) {
508 P item;
509 if (!ReadParam(m, iter, &item))
510 return false;
511 r->insert(item);
512 }
513 return true;
514 }
[email protected]252cad62010-08-18 18:33:57515 static void Log(const param_type& p, std::string* l) {
516 l->append("<std::set>");
[email protected]96da6962010-05-13 19:10:34517 }
518};
519
520
[email protected]7d5c3ac2009-02-04 08:58:19521template <class K, class V>
522struct ParamTraits<std::map<K, V> > {
523 typedef std::map<K, V> param_type;
524 static void Write(Message* m, const param_type& p) {
525 WriteParam(m, static_cast<int>(p.size()));
526 typename param_type::const_iterator iter;
527 for (iter = p.begin(); iter != p.end(); ++iter) {
528 WriteParam(m, iter->first);
529 WriteParam(m, iter->second);
530 }
531 }
532 static bool Read(const Message* m, void** iter, param_type* r) {
533 int size;
534 if (!ReadParam(m, iter, &size) || size < 0)
535 return false;
536 for (int i = 0; i < size; ++i) {
537 K k;
538 if (!ReadParam(m, iter, &k))
539 return false;
540 V& value = (*r)[k];
541 if (!ReadParam(m, iter, &value))
542 return false;
543 }
544 return true;
545 }
[email protected]252cad62010-08-18 18:33:57546 static void Log(const param_type& p, std::string* l) {
547 l->append("<std::map>");
[email protected]7d5c3ac2009-02-04 08:58:19548 }
549};
550
[email protected]eb47a132009-03-04 00:39:56551
[email protected]7d5c3ac2009-02-04 08:58:19552template <>
553struct ParamTraits<std::wstring> {
554 typedef std::wstring param_type;
555 static void Write(Message* m, const param_type& p) {
556 m->WriteWString(p);
557 }
558 static bool Read(const Message* m, void** iter, param_type* r) {
559 return m->ReadWString(iter, r);
560 }
[email protected]252cad62010-08-18 18:33:57561 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19562};
563
[email protected]a5da6d612009-08-04 02:00:56564template <class A, class B>
565struct ParamTraits<std::pair<A, B> > {
566 typedef std::pair<A, B> param_type;
567 static void Write(Message* m, const param_type& p) {
568 WriteParam(m, p.first);
569 WriteParam(m, p.second);
570 }
571 static bool Read(const Message* m, void** iter, param_type* r) {
572 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
573 }
[email protected]252cad62010-08-18 18:33:57574 static void Log(const param_type& p, std::string* l) {
575 l->append("(");
[email protected]a5da6d612009-08-04 02:00:56576 LogParam(p.first, l);
[email protected]252cad62010-08-18 18:33:57577 l->append(", ");
[email protected]a5da6d612009-08-04 02:00:56578 LogParam(p.second, l);
[email protected]252cad62010-08-18 18:33:57579 l->append(")");
[email protected]a5da6d612009-08-04 02:00:56580 }
581};
582
[email protected]15bf8712009-08-27 00:55:02583template <>
584struct ParamTraits<NullableString16> {
585 typedef NullableString16 param_type;
[email protected]7a4de7a62010-08-17 18:38:24586 static void Write(Message* m, const param_type& p);
587 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57588 static void Log(const param_type& p, std::string* l);
[email protected]15bf8712009-08-27 00:55:02589};
590
[email protected]eb47a132009-03-04 00:39:56591// If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
592// need this trait.
593#if !defined(WCHAR_T_IS_UTF16)
[email protected]eb47a132009-03-04 00:39:56594template <>
595struct ParamTraits<string16> {
596 typedef string16 param_type;
597 static void Write(Message* m, const param_type& p) {
[email protected]3a2a5d22009-03-04 03:36:36598 m->WriteString16(p);
[email protected]eb47a132009-03-04 00:39:56599 }
600 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]3a2a5d22009-03-04 03:36:36601 return m->ReadString16(iter, r);
[email protected]eb47a132009-03-04 00:39:56602 }
[email protected]252cad62010-08-18 18:33:57603 static void Log(const param_type& p, std::string* l);
[email protected]eb47a132009-03-04 00:39:56604};
[email protected]eb47a132009-03-04 00:39:56605#endif
606
[email protected]7d5c3ac2009-02-04 08:58:19607// and, a few more useful types...
608#if defined(OS_WIN)
609template <>
610struct ParamTraits<HANDLE> {
611 typedef HANDLE param_type;
612 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35613 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
614 // bit systems.
615 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19616 }
617 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35618 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
619 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19620 }
[email protected]252cad62010-08-18 18:33:57621 static void Log(const param_type& p, std::string* l) {
622 l->append(StringPrintf("0x%X", p));
[email protected]7d5c3ac2009-02-04 08:58:19623 }
624};
625
626template <>
627struct ParamTraits<HCURSOR> {
628 typedef HCURSOR param_type;
629 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35630 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19631 }
632 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35633 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
634 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19635 }
[email protected]252cad62010-08-18 18:33:57636 static void Log(const param_type& p, std::string* l) {
637 l->append(StringPrintf("0x%X", p));
[email protected]7d5c3ac2009-02-04 08:58:19638 }
639};
640
641template <>
[email protected]7d5c3ac2009-02-04 08:58:19642struct ParamTraits<HACCEL> {
643 typedef HACCEL param_type;
644 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35645 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19646 }
647 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35648 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
649 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19650 }
651};
652
653template <>
654struct ParamTraits<POINT> {
655 typedef POINT param_type;
656 static void Write(Message* m, const param_type& p) {
657 m->WriteInt(p.x);
658 m->WriteInt(p.y);
659 }
660 static bool Read(const Message* m, void** iter, param_type* r) {
661 int x, y;
662 if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
663 return false;
664 r->x = x;
665 r->y = y;
666 return true;
667 }
[email protected]252cad62010-08-18 18:33:57668 static void Log(const param_type& p, std::string* l) {
669 l->append(StringPrintf("(%d, %d)", p.x, p.y));
[email protected]7d5c3ac2009-02-04 08:58:19670 }
671};
672#endif // defined(OS_WIN)
673
674template <>
675struct ParamTraits<FilePath> {
676 typedef FilePath param_type;
[email protected]7a4de7a62010-08-17 18:38:24677 static void Write(Message* m, const param_type& p);
678 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57679 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19680};
681
[email protected]526776c2009-02-07 00:39:26682#if defined(OS_POSIX)
[email protected]2749885f2009-03-05 21:40:11683// FileDescriptors may be serialised over IPC channels on POSIX. On the
684// receiving side, the FileDescriptor is a valid duplicate of the file
685// descriptor which was transmitted: *it is not just a copy of the integer like
686// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
687// this case, the receiving end will see a value of -1. *Zero is a valid file
688// descriptor*.
689//
690// The received file descriptor will have the |auto_close| flag set to true. The
691// code which handles the message is responsible for taking ownership of it.
692// File descriptors are OS resources and must be closed when no longer needed.
693//
694// When sending a file descriptor, the file descriptor must be valid at the time
695// of transmission. Since transmission is not synchronous, one should consider
696// dup()ing any file descriptors to be transmitted and setting the |auto_close|
697// flag, which causes the file descriptor to be closed after writing.
[email protected]526776c2009-02-07 00:39:26698template<>
[email protected]5fe733de2009-02-11 18:59:20699struct ParamTraits<base::FileDescriptor> {
700 typedef base::FileDescriptor param_type;
[email protected]7a4de7a62010-08-17 18:38:24701 static void Write(Message* m, const param_type& p);
702 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57703 static void Log(const param_type& p, std::string* l);
[email protected]526776c2009-02-07 00:39:26704};
[email protected]379e7a52010-03-09 00:38:41705#endif // defined(OS_POSIX)
[email protected]526776c2009-02-07 00:39:26706
[email protected]d2e884d2009-06-22 20:37:52707// A ChannelHandle is basically a platform-inspecific wrapper around the
708// fact that IPC endpoints are handled specially on POSIX. See above comments
709// on FileDescriptor for more background.
710template<>
711struct ParamTraits<IPC::ChannelHandle> {
712 typedef ChannelHandle param_type;
[email protected]7a4de7a62010-08-17 18:38:24713 static void Write(Message* m, const param_type& p);
714 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57715 static void Log(const param_type& p, std::string* l);
[email protected]d2e884d2009-06-22 20:37:52716};
717
[email protected]7d5c3ac2009-02-04 08:58:19718#if defined(OS_WIN)
719template <>
720struct ParamTraits<XFORM> {
721 typedef XFORM param_type;
722 static void Write(Message* m, const param_type& p) {
723 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
724 }
725 static bool Read(const Message* m, void** iter, param_type* r) {
726 const char *data;
727 int data_size = 0;
728 bool result = m->ReadData(iter, &data, &data_size);
729 if (result && data_size == sizeof(XFORM)) {
730 memcpy(r, data, sizeof(XFORM));
731 } else {
732 result = false;
733 NOTREACHED();
734 }
735
736 return result;
737 }
[email protected]252cad62010-08-18 18:33:57738 static void Log(const param_type& p, std::string* l) {
739 l->append("<XFORM>");
[email protected]7d5c3ac2009-02-04 08:58:19740 }
741};
742#endif // defined(OS_WIN)
743
[email protected]7d5c3ac2009-02-04 08:58:19744struct LogData {
[email protected]20f0487a2010-09-30 20:06:30745 LogData();
746 ~LogData();
747
[email protected]9a3a293b2009-06-04 22:28:16748 std::string channel;
[email protected]8bef70e2009-04-14 19:11:24749 int32 routing_id;
[email protected]168ae922009-12-04 18:08:45750 uint32 type; // "User-defined" message type, from ipc_message.h.
[email protected]252cad62010-08-18 18:33:57751 std::string flags;
[email protected]7d5c3ac2009-02-04 08:58:19752 int64 sent; // Time that the message was sent (i.e. at Send()).
753 int64 receive; // Time before it was dispatched (i.e. before calling
754 // OnMessageReceived).
755 int64 dispatch; // Time after it was dispatched (i.e. after calling
756 // OnMessageReceived).
[email protected]252cad62010-08-18 18:33:57757 std::string message_name;
758 std::string params;
[email protected]7d5c3ac2009-02-04 08:58:19759};
760
761template <>
762struct ParamTraits<LogData> {
763 typedef LogData param_type;
[email protected]20f0487a2010-09-30 20:06:30764 static void Write(Message* m, const param_type& p);
765 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57766 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19767 // Doesn't make sense to implement this!
768 }
769};
770
[email protected]eb47a132009-03-04 00:39:56771template <>
[email protected]503683f2009-02-26 09:13:01772struct ParamTraits<Message> {
773 static void Write(Message* m, const Message& p) {
[email protected]8a861402011-01-28 19:59:11774 DCHECK(p.size() <= INT_MAX);
775 int message_size = static_cast<int>(p.size());
776 m->WriteInt(message_size);
777 m->WriteData(reinterpret_cast<const char*>(p.data()), message_size);
[email protected]503683f2009-02-26 09:13:01778 }
779 static bool Read(const Message* m, void** iter, Message* r) {
780 int size;
781 if (!m->ReadInt(iter, &size))
782 return false;
783 const char* data;
784 if (!m->ReadData(iter, &data, &size))
785 return false;
786 *r = Message(data, size);
787 return true;
788 }
[email protected]252cad62010-08-18 18:33:57789 static void Log(const Message& p, std::string* l) {
790 l->append("<IPC::Message>");
[email protected]503683f2009-02-26 09:13:01791 }
792};
793
794template <>
[email protected]7d5c3ac2009-02-04 08:58:19795struct ParamTraits<Tuple0> {
796 typedef Tuple0 param_type;
797 static void Write(Message* m, const param_type& p) {
798 }
799 static bool Read(const Message* m, void** iter, param_type* r) {
800 return true;
801 }
[email protected]252cad62010-08-18 18:33:57802 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19803 }
804};
805
806template <class A>
807struct ParamTraits< Tuple1<A> > {
808 typedef Tuple1<A> param_type;
809 static void Write(Message* m, const param_type& p) {
810 WriteParam(m, p.a);
811 }
812 static bool Read(const Message* m, void** iter, param_type* r) {
813 return ReadParam(m, iter, &r->a);
814 }
[email protected]252cad62010-08-18 18:33:57815 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19816 LogParam(p.a, l);
817 }
818};
819
820template <class A, class B>
821struct ParamTraits< Tuple2<A, B> > {
822 typedef Tuple2<A, B> param_type;
823 static void Write(Message* m, const param_type& p) {
824 WriteParam(m, p.a);
825 WriteParam(m, p.b);
826 }
827 static bool Read(const Message* m, void** iter, param_type* r) {
828 return (ReadParam(m, iter, &r->a) &&
829 ReadParam(m, iter, &r->b));
830 }
[email protected]252cad62010-08-18 18:33:57831 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19832 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57833 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19834 LogParam(p.b, l);
835 }
836};
837
838template <class A, class B, class C>
839struct ParamTraits< Tuple3<A, B, C> > {
840 typedef Tuple3<A, B, C> param_type;
841 static void Write(Message* m, const param_type& p) {
842 WriteParam(m, p.a);
843 WriteParam(m, p.b);
844 WriteParam(m, p.c);
845 }
846 static bool Read(const Message* m, void** iter, param_type* r) {
847 return (ReadParam(m, iter, &r->a) &&
848 ReadParam(m, iter, &r->b) &&
849 ReadParam(m, iter, &r->c));
850 }
[email protected]252cad62010-08-18 18:33:57851 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19852 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57853 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19854 LogParam(p.b, l);
[email protected]252cad62010-08-18 18:33:57855 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19856 LogParam(p.c, l);
857 }
858};
859
860template <class A, class B, class C, class D>
861struct ParamTraits< Tuple4<A, B, C, D> > {
862 typedef Tuple4<A, B, C, D> param_type;
863 static void Write(Message* m, const param_type& p) {
864 WriteParam(m, p.a);
865 WriteParam(m, p.b);
866 WriteParam(m, p.c);
867 WriteParam(m, p.d);
868 }
869 static bool Read(const Message* m, void** iter, param_type* r) {
870 return (ReadParam(m, iter, &r->a) &&
871 ReadParam(m, iter, &r->b) &&
872 ReadParam(m, iter, &r->c) &&
873 ReadParam(m, iter, &r->d));
874 }
[email protected]252cad62010-08-18 18:33:57875 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19876 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57877 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19878 LogParam(p.b, l);
[email protected]252cad62010-08-18 18:33:57879 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19880 LogParam(p.c, l);
[email protected]252cad62010-08-18 18:33:57881 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19882 LogParam(p.d, l);
883 }
884};
885
886template <class A, class B, class C, class D, class E>
887struct ParamTraits< Tuple5<A, B, C, D, E> > {
888 typedef Tuple5<A, B, C, D, E> param_type;
889 static void Write(Message* m, const param_type& p) {
890 WriteParam(m, p.a);
891 WriteParam(m, p.b);
892 WriteParam(m, p.c);
893 WriteParam(m, p.d);
894 WriteParam(m, p.e);
895 }
896 static bool Read(const Message* m, void** iter, param_type* r) {
897 return (ReadParam(m, iter, &r->a) &&
898 ReadParam(m, iter, &r->b) &&
899 ReadParam(m, iter, &r->c) &&
900 ReadParam(m, iter, &r->d) &&
901 ReadParam(m, iter, &r->e));
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);
[email protected]252cad62010-08-18 18:33:57911 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19912 LogParam(p.e, l);
913 }
914};
915
[email protected]7d5c3ac2009-02-04 08:58:19916//-----------------------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:29917// Generic message subclasses
918
919// Used for asynchronous messages.
[email protected]81a34412009-01-05 19:17:24920template <class ParamType>
initial.commit09911bf2008-07-26 23:55:29921class MessageWithTuple : public Message {
922 public:
[email protected]81a34412009-01-05 19:17:24923 typedef ParamType Param;
[email protected]7a4de7a62010-08-17 18:38:24924 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
[email protected]81a34412009-01-05 19:17:24925
[email protected]7a4de7a62010-08-17 18:38:24926 // The constructor and the Read() method's templated implementations are in
927 // ipc_message_utils_impl.h. The subclass constructor and Log() methods call
928 // the templated versions of these and make sure there are instantiations in
929 // those translation units.
930 MessageWithTuple(int32 routing_id, uint32 type, const RefParam& p);
[email protected]071b4b92010-08-09 16:06:58931
[email protected]7a4de7a62010-08-17 18:38:24932 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
initial.commit09911bf2008-07-26 23:55:29933
934 // Generic dispatcher. Should cover most cases.
[email protected]65412272010-12-21 20:03:24935 template<class T, class S, class Method>
936 static bool Dispatch(const Message* msg, T* obj, S* sender, Method func) {
initial.commit09911bf2008-07-26 23:55:29937 Param p;
938 if (Read(msg, &p)) {
939 DispatchToMethod(obj, func, p);
940 return true;
941 }
942 return false;
943 }
944
945 // The following dispatchers exist for the case where the callback function
946 // needs the message as well. They assume that "Param" is a type of Tuple
947 // (except the one arg case, as there is no Tuple1).
[email protected]65412272010-12-21 20:03:24948 template<class T, class S, typename TA>
949 static bool Dispatch(const Message* msg, T* obj, S* sender,
initial.commit09911bf2008-07-26 23:55:29950 void (T::*func)(const Message&, TA)) {
951 Param p;
952 if (Read(msg, &p)) {
[email protected]c2fe31542009-05-20 18:24:14953 (obj->*func)(*msg, p.a);
initial.commit09911bf2008-07-26 23:55:29954 return true;
955 }
956 return false;
957 }
958
[email protected]65412272010-12-21 20:03:24959 template<class T, class S, typename TA, typename TB>
960 static bool Dispatch(const Message* msg, T* obj, S* sender,
initial.commit09911bf2008-07-26 23:55:29961 void (T::*func)(const Message&, TA, TB)) {
962 Param p;
963 if (Read(msg, &p)) {
964 (obj->*func)(*msg, p.a, p.b);
965 return true;
966 }
967 return false;
968 }
969
[email protected]65412272010-12-21 20:03:24970 template<class T, class S, typename TA, typename TB, typename TC>
971 static bool Dispatch(const Message* msg, T* obj, S* sender,
initial.commit09911bf2008-07-26 23:55:29972 void (T::*func)(const Message&, TA, TB, TC)) {
973 Param p;
974 if (Read(msg, &p)) {
975 (obj->*func)(*msg, p.a, p.b, p.c);
976 return true;
977 }
978 return false;
979 }
980
[email protected]65412272010-12-21 20:03:24981 template<class T, class S, typename TA, typename TB, typename TC, typename TD>
982 static bool Dispatch(const Message* msg, T* obj, S* sender,
initial.commit09911bf2008-07-26 23:55:29983 void (T::*func)(const Message&, TA, TB, TC, TD)) {
984 Param p;
985 if (Read(msg, &p)) {
986 (obj->*func)(*msg, p.a, p.b, p.c, p.d);
987 return true;
988 }
989 return false;
990 }
991
[email protected]65412272010-12-21 20:03:24992 template<class T, class S, typename TA, typename TB, typename TC, typename TD,
initial.commit09911bf2008-07-26 23:55:29993 typename TE>
[email protected]65412272010-12-21 20:03:24994 static bool Dispatch(const Message* msg, T* obj, S* sender,
initial.commit09911bf2008-07-26 23:55:29995 void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
996 Param p;
997 if (Read(msg, &p)) {
998 (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
999 return true;
1000 }
1001 return false;
1002 }
1003
[email protected]deb57402009-02-06 01:35:301004 // Functions used to do manual unpacking. Only used by the automation code,
1005 // these should go away once that code uses SyncChannel.
1006 template<typename TA, typename TB>
1007 static bool Read(const IPC::Message* msg, TA* a, TB* b) {
1008 ParamType params;
1009 if (!Read(msg, &params))
1010 return false;
1011 *a = params.a;
1012 *b = params.b;
1013 return true;
1014 }
1015
1016 template<typename TA, typename TB, typename TC>
1017 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
1018 ParamType params;
1019 if (!Read(msg, &params))
1020 return false;
1021 *a = params.a;
1022 *b = params.b;
1023 *c = params.c;
1024 return true;
1025 }
1026
1027 template<typename TA, typename TB, typename TC, typename TD>
1028 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
1029 ParamType params;
1030 if (!Read(msg, &params))
1031 return false;
1032 *a = params.a;
1033 *b = params.b;
1034 *c = params.c;
1035 *d = params.d;
1036 return true;
1037 }
1038
1039 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1040 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
1041 ParamType params;
1042 if (!Read(msg, &params))
1043 return false;
1044 *a = params.a;
1045 *b = params.b;
1046 *c = params.c;
1047 *d = params.d;
1048 *e = params.e;
1049 return true;
1050 }
initial.commit09911bf2008-07-26 23:55:291051};
1052
[email protected]7a4de7a62010-08-17 18:38:241053// defined in ipc_logging.cc
1054void GenerateLogData(const std::string& channel, const Message& message,
1055 LogData* data);
1056
1057
1058#if defined(IPC_MESSAGE_LOG_ENABLED)
[email protected]252cad62010-08-18 18:33:571059inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
1060 const std::string& output_params = msg->output_params();
[email protected]7a4de7a62010-08-17 18:38:241061 if (!l->empty() && !output_params.empty())
[email protected]252cad62010-08-18 18:33:571062 l->append(", ");
[email protected]7a4de7a62010-08-17 18:38:241063
1064 l->append(output_params);
1065}
1066
1067template <class ReplyParamType>
1068inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1069 const Message* msg) {
1070 if (msg->received_time() != 0) {
[email protected]252cad62010-08-18 18:33:571071 std::string output_params;
[email protected]7a4de7a62010-08-17 18:38:241072 LogParam(reply_params, &output_params);
1073 msg->set_output_params(output_params);
1074 }
1075}
1076
1077inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
1078 if (msg->sent_time()) {
1079 // Don't log the sync message after dispatch, as we don't have the
1080 // output parameters at that point. Instead, save its data and log it
1081 // with the outgoing reply message when it's sent.
1082 LogData* data = new LogData;
1083 GenerateLogData("", *msg, data);
1084 msg->set_dont_log();
1085 reply->set_sync_log_data(data);
1086 }
1087}
1088#else
[email protected]252cad62010-08-18 18:33:571089inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
[email protected]7a4de7a62010-08-17 18:38:241090
1091template <class ReplyParamType>
1092inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1093 const Message* msg) {}
1094
1095inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
1096#endif
1097
initial.commit09911bf2008-07-26 23:55:291098// This class assumes that its template argument is a RefTuple (a Tuple with
[email protected]7a4de7a62010-08-17 18:38:241099// reference elements). This would go into ipc_message_utils_impl.h, but it is
1100// also used by chrome_frame.
initial.commit09911bf2008-07-26 23:55:291101template <class RefTuple>
1102class ParamDeserializer : public MessageReplyDeserializer {
1103 public:
[email protected]e1981f432008-08-12 15:22:131104 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
initial.commit09911bf2008-07-26 23:55:291105
1106 bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
1107 return ReadParam(&msg, &iter, &out_);
1108 }
1109
1110 RefTuple out_;
1111};
1112
initial.commit09911bf2008-07-26 23:55:291113// Used for synchronous messages.
[email protected]75e5a872009-04-02 23:56:111114template <class SendParamType, class ReplyParamType>
initial.commit09911bf2008-07-26 23:55:291115class MessageWithReply : public SyncMessage {
1116 public:
[email protected]75e5a872009-04-02 23:56:111117 typedef SendParamType SendParam;
[email protected]7a4de7a62010-08-17 18:38:241118 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
[email protected]75e5a872009-04-02 23:56:111119 typedef ReplyParamType ReplyParam;
1120
[email protected]168ae922009-12-04 18:08:451121 MessageWithReply(int32 routing_id, uint32 type,
[email protected]7a4de7a62010-08-17 18:38:241122 const RefSendParam& send, const ReplyParam& reply);
1123 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
1124 static bool ReadReplyParam(
1125 const Message* msg,
1126 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
initial.commit09911bf2008-07-26 23:55:291127
[email protected]65412272010-12-21 20:03:241128 template<class T, class S, class Method>
1129 static bool Dispatch(const Message* msg, T* obj, S* sender, Method func) {
initial.commit09911bf2008-07-26 23:55:291130 SendParam send_params;
initial.commit09911bf2008-07-26 23:55:291131 Message* reply = GenerateReply(msg);
1132 bool error;
[email protected]7a4de7a62010-08-17 18:38:241133 if (ReadSendParam(msg, &send_params)) {
1134 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
initial.commit09911bf2008-07-26 23:55:291135 DispatchToMethod(obj, func, send_params, &reply_params);
1136 WriteParam(reply, reply_params);
1137 error = false;
[email protected]7a4de7a62010-08-17 18:38:241138 LogReplyParamsToMessage(reply_params, msg);
initial.commit09911bf2008-07-26 23:55:291139 } else {
1140 NOTREACHED() << "Error deserializing message " << msg->type();
1141 reply->set_reply_error();
1142 error = true;
1143 }
1144
[email protected]65412272010-12-21 20:03:241145 sender->Send(reply);
initial.commit09911bf2008-07-26 23:55:291146 return !error;
1147 }
1148
1149 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191150 static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291151 SendParam send_params;
initial.commit09911bf2008-07-26 23:55:291152 Message* reply = GenerateReply(msg);
1153 bool error;
[email protected]7a4de7a62010-08-17 18:38:241154 if (ReadSendParam(msg, &send_params)) {
initial.commit09911bf2008-07-26 23:55:291155 Tuple1<Message&> t = MakeRefTuple(*reply);
[email protected]7a4de7a62010-08-17 18:38:241156 ConnectMessageAndReply(msg, reply);
initial.commit09911bf2008-07-26 23:55:291157 DispatchToMethod(obj, func, send_params, &t);
1158 error = false;
1159 } else {
1160 NOTREACHED() << "Error deserializing message " << msg->type();
1161 reply->set_reply_error();
1162 obj->Send(reply);
1163 error = true;
1164 }
1165 return !error;
1166 }
1167
1168 template<typename TA>
1169 static void WriteReplyParams(Message* reply, TA a) {
1170 ReplyParam p(a);
1171 WriteParam(reply, p);
1172 }
1173
1174 template<typename TA, typename TB>
1175 static void WriteReplyParams(Message* reply, TA a, TB b) {
1176 ReplyParam p(a, b);
1177 WriteParam(reply, p);
1178 }
1179
1180 template<typename TA, typename TB, typename TC>
1181 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
1182 ReplyParam p(a, b, c);
1183 WriteParam(reply, p);
1184 }
1185
1186 template<typename TA, typename TB, typename TC, typename TD>
1187 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
1188 ReplyParam p(a, b, c, d);
1189 WriteParam(reply, p);
1190 }
1191
1192 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1193 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
1194 ReplyParam p(a, b, c, d, e);
1195 WriteParam(reply, p);
1196 }
1197};
1198
[email protected]7d5c3ac2009-02-04 08:58:191199//-----------------------------------------------------------------------------
1200
[email protected]3178f4e22008-08-05 21:20:411201} // namespace IPC
initial.commit09911bf2008-07-26 23:55:291202
[email protected]946d1b22009-07-22 23:57:211203#endif // IPC_IPC_MESSAGE_UTILS_H_