blob: 75b80ae3b8f861670c1377e9d2ac865ada374888 [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.
[email protected]efafbbd2010-08-19 20:23:2528#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500
29// Starting in gcc 4.5, the noinline no longer implies the concept covered by
30// the introduced noclone attribute, which will create specialized versions of
31// functions/methods when certain types are constant.
32// www.gnu.org/software/gcc/gcc-4.5/changes.html
33#define IPC_MSG_NOINLINE __attribute__((noinline, noclone));
34#else
[email protected]7a4de7a62010-08-17 18:38:2435#define IPC_MSG_NOINLINE __attribute__((noinline));
[email protected]efafbbd2010-08-19 20:23:2536#endif
[email protected]7a4de7a62010-08-17 18:38:2437#elif defined(COMPILER_MSVC)
38// MSVC++ doesn't do this.
39#define IPC_MSG_NOINLINE
40#else
41#error "Please add the noinline property for your new compiler here."
42#endif
43
[email protected]f91cb992009-02-04 20:10:1244// Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
45// base. Messages have unique IDs across channels in order for the IPC logging
46// code to figure out the message class from its ID.
47enum IPCMessageStart {
48 // By using a start value of 0 for automation messages, we keep backward
49 // compatibility with old builds.
50 AutomationMsgStart = 0,
51 ViewMsgStart,
52 ViewHostMsgStart,
53 PluginProcessMsgStart,
54 PluginProcessHostMsgStart,
55 PluginMsgStart,
56 PluginHostMsgStart,
[email protected]96da6962010-05-13 19:10:3457 ProfileImportProcessMsgStart,
58 ProfileImportProcessHostMsgStart,
[email protected]f91cb992009-02-04 20:10:1259 NPObjectMsgStart,
60 TestMsgStart,
[email protected]503683f2009-02-26 09:13:0161 DevToolsAgentMsgStart,
62 DevToolsClientMsgStart,
[email protected]eb47a132009-03-04 00:39:5663 WorkerProcessMsgStart,
64 WorkerProcessHostMsgStart,
65 WorkerMsgStart,
66 WorkerHostMsgStart,
[email protected]d032f492009-09-29 00:33:4667 NaClProcessMsgStart,
[email protected]246a70452010-03-05 21:53:5068 GpuCommandBufferMsgStart,
[email protected]60f14392009-12-15 20:46:3269 UtilityMsgStart,
70 UtilityHostMsgStart,
[email protected]c0fc0942010-01-13 00:55:3771 GpuMsgStart,
72 GpuHostMsgStart,
[email protected]246a70452010-03-05 21:53:5073 GpuChannelMsgStart,
[email protected]ee68378a2010-08-10 01:05:4174 GpuVideoDecoderHostMsgStart,
75 GpuVideoDecoderMsgStart,
[email protected]38fe1962010-07-31 07:57:0076 ServiceMsgStart,
77 ServiceHostMsgStart,
[email protected]f91cb992009-02-04 20:10:1278 // NOTE: When you add a new message class, also update
79 // IPCStatusView::IPCStatusView to ensure logging works.
[email protected]f91cb992009-02-04 20:10:1280 LastMsgIndex
81};
82
[email protected]7a4de7a62010-08-17 18:38:2483class DictionaryValue;
84class FilePath;
85class ListValue;
86class NullableString16;
87
88namespace base {
89class Time;
90struct FileDescriptor;
91}
92
initial.commit09911bf2008-07-26 23:55:2993namespace IPC {
94
[email protected]7a4de7a62010-08-17 18:38:2495struct ChannelHandle;
96
initial.commit09911bf2008-07-26 23:55:2997//-----------------------------------------------------------------------------
98// An iterator class for reading the fields contained within a Message.
99
100class MessageIterator {
101 public:
[email protected]e1981f432008-08-12 15:22:13102 explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
initial.commit09911bf2008-07-26 23:55:29103 }
104 int NextInt() const {
[email protected]9422b7dc2009-12-30 20:09:02105 int val = -1;
initial.commit09911bf2008-07-26 23:55:29106 if (!msg_.ReadInt(&iter_, &val))
107 NOTREACHED();
108 return val;
109 }
initial.commit09911bf2008-07-26 23:55:29110 const std::string NextString() const {
111 std::string val;
112 if (!msg_.ReadString(&iter_, &val))
113 NOTREACHED();
114 return val;
115 }
116 const std::wstring NextWString() const {
117 std::wstring val;
118 if (!msg_.ReadWString(&iter_, &val))
119 NOTREACHED();
120 return val;
121 }
[email protected]225c8f52010-02-05 22:23:20122 void NextData(const char** data, int* length) const {
initial.commit09911bf2008-07-26 23:55:29123 if (!msg_.ReadData(&iter_, data, length)) {
124 NOTREACHED();
125 }
126 }
127 private:
128 const Message& msg_;
129 mutable void* iter_;
130};
131
132//-----------------------------------------------------------------------------
[email protected]7d5c3ac2009-02-04 08:58:19133// ParamTraits specializations, etc.
134
[email protected]7b291f92009-08-14 05:43:53135template <class P> struct ParamTraits {
136};
137
138template <class P>
139struct SimilarTypeTraits {
140 typedef P Type;
141};
[email protected]7d5c3ac2009-02-04 08:58:19142
143template <class P>
144static inline void WriteParam(Message* m, const P& p) {
[email protected]7b291f92009-08-14 05:43:53145 typedef typename SimilarTypeTraits<P>::Type Type;
[email protected]46ce5b562010-06-16 18:39:53146 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
[email protected]7d5c3ac2009-02-04 08:58:19147}
148
149template <class P>
[email protected]1e86aa62009-04-24 21:22:33150static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
151 P* p) {
[email protected]7b291f92009-08-14 05:43:53152 typedef typename SimilarTypeTraits<P>::Type Type;
153 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
[email protected]7d5c3ac2009-02-04 08:58:19154}
155
156template <class P>
[email protected]252cad62010-08-18 18:33:57157static inline void LogParam(const P& p, std::string* l) {
[email protected]7b291f92009-08-14 05:43:53158 typedef typename SimilarTypeTraits<P>::Type Type;
[email protected]46ce5b562010-06-16 18:39:53159 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
[email protected]7d5c3ac2009-02-04 08:58:19160}
161
162template <>
163struct ParamTraits<bool> {
164 typedef bool param_type;
165 static void Write(Message* m, const param_type& p) {
166 m->WriteBool(p);
167 }
168 static bool Read(const Message* m, void** iter, param_type* r) {
169 return m->ReadBool(iter, r);
170 }
[email protected]252cad62010-08-18 18:33:57171 static void Log(const param_type& p, std::string* l) {
172 l->append(p ? "true" : "false");
[email protected]7d5c3ac2009-02-04 08:58:19173 }
174};
175
176template <>
177struct ParamTraits<int> {
178 typedef int param_type;
179 static void Write(Message* m, const param_type& p) {
180 m->WriteInt(p);
181 }
182 static bool Read(const Message* m, void** iter, param_type* r) {
183 return m->ReadInt(iter, r);
184 }
[email protected]252cad62010-08-18 18:33:57185 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19186};
187
188template <>
[email protected]63263f92009-07-28 19:35:08189struct ParamTraits<unsigned int> {
190 typedef unsigned int param_type;
191 static void Write(Message* m, const param_type& p) {
192 m->WriteInt(p);
193 }
194 static bool Read(const Message* m, void** iter, param_type* r) {
195 return m->ReadInt(iter, reinterpret_cast<int*>(r));
196 }
[email protected]252cad62010-08-18 18:33:57197 static void Log(const param_type& p, std::string* l);
[email protected]63263f92009-07-28 19:35:08198};
199
200template <>
[email protected]7d5c3ac2009-02-04 08:58:19201struct ParamTraits<long> {
202 typedef long param_type;
203 static void Write(Message* m, const param_type& p) {
204 m->WriteLong(p);
205 }
206 static bool Read(const Message* m, void** iter, param_type* r) {
207 return m->ReadLong(iter, r);
208 }
[email protected]252cad62010-08-18 18:33:57209 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19210};
211
[email protected]140c3032009-06-26 18:22:54212template <>
213struct ParamTraits<unsigned long> {
214 typedef unsigned long param_type;
215 static void Write(Message* m, const param_type& p) {
216 m->WriteLong(p);
217 }
218 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]63263f92009-07-28 19:35:08219 return m->ReadLong(iter, reinterpret_cast<long*>(r));
[email protected]140c3032009-06-26 18:22:54220 }
[email protected]252cad62010-08-18 18:33:57221 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19222};
223
224template <>
[email protected]63263f92009-07-28 19:35:08225struct ParamTraits<long long> {
226 typedef long long param_type;
[email protected]7d5c3ac2009-02-04 08:58:19227 static void Write(Message* m, const param_type& p) {
228 m->WriteInt64(static_cast<int64>(p));
229 }
230 static bool Read(const Message* m, void** iter, param_type* r) {
231 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
232 }
[email protected]252cad62010-08-18 18:33:57233 static void Log(const param_type& p, std::string* l);
[email protected]63263f92009-07-28 19:35:08234};
235
236template <>
237struct ParamTraits<unsigned long long> {
238 typedef unsigned long long param_type;
239 static void Write(Message* m, const param_type& p) {
240 m->WriteInt64(p);
241 }
242 static bool Read(const Message* m, void** iter, param_type* r) {
243 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
244 }
[email protected]252cad62010-08-18 18:33:57245 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19246};
247
[email protected]20199662010-06-17 03:29:26248// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
249// should be sure to check the sanity of these values after receiving them over
250// IPC.
251template <>
252struct ParamTraits<float> {
253 typedef float param_type;
254 static void Write(Message* m, const param_type& p) {
255 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
256 }
257 static bool Read(const Message* m, void** iter, param_type* r) {
258 const char *data;
259 int data_size;
260 if (!m->ReadData(iter, &data, &data_size) ||
261 data_size != sizeof(param_type)) {
262 NOTREACHED();
263 return false;
264 }
265 memcpy(r, data, sizeof(param_type));
266 return true;
267 }
[email protected]252cad62010-08-18 18:33:57268 static void Log(const param_type& p, std::string* l) {
269 l->append(StringPrintf("%e", p));
[email protected]20199662010-06-17 03:29:26270 }
271};
272
[email protected]7d5c3ac2009-02-04 08:58:19273template <>
274struct ParamTraits<double> {
275 typedef double param_type;
276 static void Write(Message* m, const param_type& p) {
277 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
278 }
279 static bool Read(const Message* m, void** iter, param_type* r) {
280 const char *data;
[email protected]20199662010-06-17 03:29:26281 int data_size;
282 if (!m->ReadData(iter, &data, &data_size) ||
283 data_size != sizeof(param_type)) {
[email protected]7d5c3ac2009-02-04 08:58:19284 NOTREACHED();
[email protected]20199662010-06-17 03:29:26285 return false;
[email protected]7d5c3ac2009-02-04 08:58:19286 }
[email protected]20199662010-06-17 03:29:26287 memcpy(r, data, sizeof(param_type));
288 return true;
[email protected]7d5c3ac2009-02-04 08:58:19289 }
[email protected]252cad62010-08-18 18:33:57290 static void Log(const param_type& p, std::string* l) {
291 l->append(StringPrintf("%e", p));
[email protected]7d5c3ac2009-02-04 08:58:19292 }
293};
294
295template <>
296struct ParamTraits<wchar_t> {
297 typedef wchar_t param_type;
298 static void Write(Message* m, const param_type& p) {
299 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
300 }
301 static bool Read(const Message* m, void** iter, param_type* r) {
302 const char *data;
303 int data_size = 0;
304 bool result = m->ReadData(iter, &data, &data_size);
305 if (result && data_size == sizeof(param_type)) {
306 memcpy(r, data, sizeof(param_type));
307 } else {
308 result = false;
309 NOTREACHED();
310 }
311
312 return result;
313 }
[email protected]252cad62010-08-18 18:33:57314 static void Log(const param_type& p, std::string* l) {
315 l->append(StringPrintf("%lc", p));
[email protected]7d5c3ac2009-02-04 08:58:19316 }
317};
318
319template <>
320struct ParamTraits<base::Time> {
321 typedef base::Time param_type;
[email protected]7a4de7a62010-08-17 18:38:24322 static void Write(Message* m, const param_type& p);
323 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57324 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19325};
326
327#if defined(OS_WIN)
328template <>
329struct ParamTraits<LOGFONT> {
330 typedef LOGFONT param_type;
331 static void Write(Message* m, const param_type& p) {
332 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
333 }
334 static bool Read(const Message* m, void** iter, param_type* r) {
335 const char *data;
336 int data_size = 0;
337 bool result = m->ReadData(iter, &data, &data_size);
338 if (result && data_size == sizeof(LOGFONT)) {
339 memcpy(r, data, sizeof(LOGFONT));
340 } else {
341 result = false;
342 NOTREACHED();
343 }
344
345 return result;
346 }
[email protected]252cad62010-08-18 18:33:57347 static void Log(const param_type& p, std::string* l) {
348 l->append(StringPrintf("<LOGFONT>"));
[email protected]7d5c3ac2009-02-04 08:58:19349 }
350};
351
352template <>
353struct ParamTraits<MSG> {
354 typedef MSG param_type;
355 static void Write(Message* m, const param_type& p) {
356 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
357 }
358 static bool Read(const Message* m, void** iter, param_type* r) {
359 const char *data;
360 int data_size = 0;
361 bool result = m->ReadData(iter, &data, &data_size);
362 if (result && data_size == sizeof(MSG)) {
363 memcpy(r, data, sizeof(MSG));
364 } else {
365 result = false;
366 NOTREACHED();
367 }
368
369 return result;
370 }
[email protected]252cad62010-08-18 18:33:57371 static void Log(const param_type& p, std::string* l) {
372 l->append("<MSG>");
[email protected]7a4de7a62010-08-17 18:38:24373 }
[email protected]7d5c3ac2009-02-04 08:58:19374};
375#endif // defined(OS_WIN)
376
377template <>
[email protected]584f2b22009-05-21 01:01:59378struct ParamTraits<DictionaryValue> {
379 typedef DictionaryValue 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 <>
386struct ParamTraits<ListValue> {
387 typedef ListValue param_type;
388 static void Write(Message* m, const param_type& p);
389 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57390 static void Log(const param_type& p, std::string* l);
[email protected]584f2b22009-05-21 01:01:59391};
392
393template <>
[email protected]7d5c3ac2009-02-04 08:58:19394struct ParamTraits<std::string> {
395 typedef std::string param_type;
396 static void Write(Message* m, const param_type& p) {
397 m->WriteString(p);
398 }
399 static bool Read(const Message* m, void** iter, param_type* r) {
400 return m->ReadString(iter, r);
401 }
[email protected]252cad62010-08-18 18:33:57402 static void Log(const param_type& p, std::string* l) {
403 l->append(p);
[email protected]7d5c3ac2009-02-04 08:58:19404 }
405};
406
[email protected]3dd7a7a2009-07-27 21:09:07407template<typename CharType>
[email protected]252cad62010-08-18 18:33:57408static void LogBytes(const std::vector<CharType>& data, std::string* out) {
[email protected]3dd7a7a2009-07-27 21:09:07409#if defined(OS_WIN)
410 // Windows has a GUI for logging, which can handle arbitrary binary data.
411 for (size_t i = 0; i < data.size(); ++i)
412 out->push_back(data[i]);
413#else
414 // On POSIX, we log to stdout, which we assume can display ASCII.
415 static const size_t kMaxBytesToLog = 100;
416 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
417 if (isprint(data[i]))
418 out->push_back(data[i]);
419 else
[email protected]252cad62010-08-18 18:33:57420 out->append(StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
[email protected]3dd7a7a2009-07-27 21:09:07421 }
422 if (data.size() > kMaxBytesToLog) {
423 out->append(
[email protected]252cad62010-08-18 18:33:57424 StringPrintf(" and %u more bytes",
[email protected]3dd7a7a2009-07-27 21:09:07425 static_cast<unsigned>(data.size() - kMaxBytesToLog)));
426 }
427#endif
428}
429
[email protected]7d5c3ac2009-02-04 08:58:19430template <>
431struct ParamTraits<std::vector<unsigned char> > {
432 typedef std::vector<unsigned char> param_type;
433 static void Write(Message* m, const param_type& p) {
434 if (p.size() == 0) {
435 m->WriteData(NULL, 0);
436 } else {
437 m->WriteData(reinterpret_cast<const char*>(&p.front()),
438 static_cast<int>(p.size()));
439 }
440 }
441 static bool Read(const Message* m, void** iter, param_type* r) {
442 const char *data;
443 int data_size = 0;
444 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
445 return false;
446 r->resize(data_size);
447 if (data_size)
448 memcpy(&r->front(), data, data_size);
449 return true;
450 }
[email protected]252cad62010-08-18 18:33:57451 static void Log(const param_type& p, std::string* l) {
[email protected]3dd7a7a2009-07-27 21:09:07452 LogBytes(p, l);
[email protected]7d5c3ac2009-02-04 08:58:19453 }
454};
455
456template <>
457struct ParamTraits<std::vector<char> > {
458 typedef std::vector<char> param_type;
459 static void Write(Message* m, const param_type& p) {
460 if (p.size() == 0) {
461 m->WriteData(NULL, 0);
462 } else {
463 m->WriteData(&p.front(), static_cast<int>(p.size()));
464 }
465 }
466 static bool Read(const Message* m, void** iter, param_type* r) {
467 const char *data;
468 int data_size = 0;
469 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
470 return false;
471 r->resize(data_size);
472 if (data_size)
473 memcpy(&r->front(), data, data_size);
474 return true;
475 }
[email protected]252cad62010-08-18 18:33:57476 static void Log(const param_type& p, std::string* l) {
[email protected]3dd7a7a2009-07-27 21:09:07477 LogBytes(p, l);
[email protected]7d5c3ac2009-02-04 08:58:19478 }
479};
480
481template <class P>
482struct ParamTraits<std::vector<P> > {
483 typedef std::vector<P> param_type;
484 static void Write(Message* m, const param_type& p) {
485 WriteParam(m, static_cast<int>(p.size()));
486 for (size_t i = 0; i < p.size(); i++)
487 WriteParam(m, p[i]);
488 }
489 static bool Read(const Message* m, void** iter, param_type* r) {
490 int size;
[email protected]86440f52009-12-31 05:17:23491 // ReadLength() checks for < 0 itself.
[email protected]7d5c3ac2009-02-04 08:58:19492 if (!m->ReadLength(iter, &size))
493 return false;
494 // Resizing beforehand is not safe, see BUG 1006367 for details.
[email protected]86440f52009-12-31 05:17:23495 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
496 return false;
497 r->resize(size);
498 for (int i = 0; i < size; i++) {
499 if (!ReadParam(m, iter, &(*r)[i]))
500 return false;
[email protected]7d5c3ac2009-02-04 08:58:19501 }
502 return true;
503 }
[email protected]252cad62010-08-18 18:33:57504 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19505 for (size_t i = 0; i < p.size(); ++i) {
506 if (i != 0)
[email protected]252cad62010-08-18 18:33:57507 l->append(" ");
[email protected]7d5c3ac2009-02-04 08:58:19508 LogParam((p[i]), l);
509 }
510 }
511};
512
[email protected]96da6962010-05-13 19:10:34513template <class P>
514struct ParamTraits<std::set<P> > {
515 typedef std::set<P> param_type;
516 static void Write(Message* m, const param_type& p) {
517 WriteParam(m, static_cast<int>(p.size()));
518 typename param_type::const_iterator iter;
519 for (iter = p.begin(); iter != p.end(); ++iter)
520 WriteParam(m, *iter);
521 }
522 static bool Read(const Message* m, void** iter, param_type* r) {
523 int size;
524 if (!m->ReadLength(iter, &size))
525 return false;
526 for (int i = 0; i < size; ++i) {
527 P item;
528 if (!ReadParam(m, iter, &item))
529 return false;
530 r->insert(item);
531 }
532 return true;
533 }
[email protected]252cad62010-08-18 18:33:57534 static void Log(const param_type& p, std::string* l) {
535 l->append("<std::set>");
[email protected]96da6962010-05-13 19:10:34536 }
537};
538
539
[email protected]7d5c3ac2009-02-04 08:58:19540template <class K, class V>
541struct ParamTraits<std::map<K, V> > {
542 typedef std::map<K, V> param_type;
543 static void Write(Message* m, const param_type& p) {
544 WriteParam(m, static_cast<int>(p.size()));
545 typename param_type::const_iterator iter;
546 for (iter = p.begin(); iter != p.end(); ++iter) {
547 WriteParam(m, iter->first);
548 WriteParam(m, iter->second);
549 }
550 }
551 static bool Read(const Message* m, void** iter, param_type* r) {
552 int size;
553 if (!ReadParam(m, iter, &size) || size < 0)
554 return false;
555 for (int i = 0; i < size; ++i) {
556 K k;
557 if (!ReadParam(m, iter, &k))
558 return false;
559 V& value = (*r)[k];
560 if (!ReadParam(m, iter, &value))
561 return false;
562 }
563 return true;
564 }
[email protected]252cad62010-08-18 18:33:57565 static void Log(const param_type& p, std::string* l) {
566 l->append("<std::map>");
[email protected]7d5c3ac2009-02-04 08:58:19567 }
568};
569
[email protected]eb47a132009-03-04 00:39:56570
[email protected]7d5c3ac2009-02-04 08:58:19571template <>
572struct ParamTraits<std::wstring> {
573 typedef std::wstring param_type;
574 static void Write(Message* m, const param_type& p) {
575 m->WriteWString(p);
576 }
577 static bool Read(const Message* m, void** iter, param_type* r) {
578 return m->ReadWString(iter, r);
579 }
[email protected]252cad62010-08-18 18:33:57580 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19581};
582
[email protected]a5da6d612009-08-04 02:00:56583template <class A, class B>
584struct ParamTraits<std::pair<A, B> > {
585 typedef std::pair<A, B> param_type;
586 static void Write(Message* m, const param_type& p) {
587 WriteParam(m, p.first);
588 WriteParam(m, p.second);
589 }
590 static bool Read(const Message* m, void** iter, param_type* r) {
591 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
592 }
[email protected]252cad62010-08-18 18:33:57593 static void Log(const param_type& p, std::string* l) {
594 l->append("(");
[email protected]a5da6d612009-08-04 02:00:56595 LogParam(p.first, l);
[email protected]252cad62010-08-18 18:33:57596 l->append(", ");
[email protected]a5da6d612009-08-04 02:00:56597 LogParam(p.second, l);
[email protected]252cad62010-08-18 18:33:57598 l->append(")");
[email protected]a5da6d612009-08-04 02:00:56599 }
600};
601
[email protected]15bf8712009-08-27 00:55:02602template <>
603struct ParamTraits<NullableString16> {
604 typedef NullableString16 param_type;
[email protected]7a4de7a62010-08-17 18:38:24605 static void Write(Message* m, const param_type& p);
606 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57607 static void Log(const param_type& p, std::string* l);
[email protected]15bf8712009-08-27 00:55:02608};
609
[email protected]eb47a132009-03-04 00:39:56610// If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
611// need this trait.
612#if !defined(WCHAR_T_IS_UTF16)
[email protected]eb47a132009-03-04 00:39:56613template <>
614struct ParamTraits<string16> {
615 typedef string16 param_type;
616 static void Write(Message* m, const param_type& p) {
[email protected]3a2a5d22009-03-04 03:36:36617 m->WriteString16(p);
[email protected]eb47a132009-03-04 00:39:56618 }
619 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]3a2a5d22009-03-04 03:36:36620 return m->ReadString16(iter, r);
[email protected]eb47a132009-03-04 00:39:56621 }
[email protected]252cad62010-08-18 18:33:57622 static void Log(const param_type& p, std::string* l);
[email protected]eb47a132009-03-04 00:39:56623};
[email protected]eb47a132009-03-04 00:39:56624#endif
625
[email protected]7d5c3ac2009-02-04 08:58:19626// and, a few more useful types...
627#if defined(OS_WIN)
628template <>
629struct ParamTraits<HANDLE> {
630 typedef HANDLE param_type;
631 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35632 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
633 // bit systems.
634 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19635 }
636 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35637 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
638 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19639 }
[email protected]252cad62010-08-18 18:33:57640 static void Log(const param_type& p, std::string* l) {
641 l->append(StringPrintf("0x%X", p));
[email protected]7d5c3ac2009-02-04 08:58:19642 }
643};
644
645template <>
646struct ParamTraits<HCURSOR> {
647 typedef HCURSOR param_type;
648 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35649 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19650 }
651 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35652 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
653 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19654 }
[email protected]252cad62010-08-18 18:33:57655 static void Log(const param_type& p, std::string* l) {
656 l->append(StringPrintf("0x%X", p));
[email protected]7d5c3ac2009-02-04 08:58:19657 }
658};
659
660template <>
[email protected]7d5c3ac2009-02-04 08:58:19661struct ParamTraits<HACCEL> {
662 typedef HACCEL param_type;
663 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35664 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19665 }
666 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35667 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
668 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19669 }
670};
671
672template <>
673struct ParamTraits<POINT> {
674 typedef POINT param_type;
675 static void Write(Message* m, const param_type& p) {
676 m->WriteInt(p.x);
677 m->WriteInt(p.y);
678 }
679 static bool Read(const Message* m, void** iter, param_type* r) {
680 int x, y;
681 if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
682 return false;
683 r->x = x;
684 r->y = y;
685 return true;
686 }
[email protected]252cad62010-08-18 18:33:57687 static void Log(const param_type& p, std::string* l) {
688 l->append(StringPrintf("(%d, %d)", p.x, p.y));
[email protected]7d5c3ac2009-02-04 08:58:19689 }
690};
691#endif // defined(OS_WIN)
692
693template <>
694struct ParamTraits<FilePath> {
695 typedef FilePath param_type;
[email protected]7a4de7a62010-08-17 18:38:24696 static void Write(Message* m, const param_type& p);
697 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57698 static void Log(const param_type& p, std::string* l);
[email protected]7d5c3ac2009-02-04 08:58:19699};
700
[email protected]526776c2009-02-07 00:39:26701#if defined(OS_POSIX)
[email protected]2749885f2009-03-05 21:40:11702// FileDescriptors may be serialised over IPC channels on POSIX. On the
703// receiving side, the FileDescriptor is a valid duplicate of the file
704// descriptor which was transmitted: *it is not just a copy of the integer like
705// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
706// this case, the receiving end will see a value of -1. *Zero is a valid file
707// descriptor*.
708//
709// The received file descriptor will have the |auto_close| flag set to true. The
710// code which handles the message is responsible for taking ownership of it.
711// File descriptors are OS resources and must be closed when no longer needed.
712//
713// When sending a file descriptor, the file descriptor must be valid at the time
714// of transmission. Since transmission is not synchronous, one should consider
715// dup()ing any file descriptors to be transmitted and setting the |auto_close|
716// flag, which causes the file descriptor to be closed after writing.
[email protected]526776c2009-02-07 00:39:26717template<>
[email protected]5fe733de2009-02-11 18:59:20718struct ParamTraits<base::FileDescriptor> {
719 typedef base::FileDescriptor param_type;
[email protected]7a4de7a62010-08-17 18:38:24720 static void Write(Message* m, const param_type& p);
721 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57722 static void Log(const param_type& p, std::string* l);
[email protected]526776c2009-02-07 00:39:26723};
[email protected]379e7a52010-03-09 00:38:41724#endif // defined(OS_POSIX)
[email protected]526776c2009-02-07 00:39:26725
[email protected]d2e884d2009-06-22 20:37:52726// A ChannelHandle is basically a platform-inspecific wrapper around the
727// fact that IPC endpoints are handled specially on POSIX. See above comments
728// on FileDescriptor for more background.
729template<>
730struct ParamTraits<IPC::ChannelHandle> {
731 typedef ChannelHandle param_type;
[email protected]7a4de7a62010-08-17 18:38:24732 static void Write(Message* m, const param_type& p);
733 static bool Read(const Message* m, void** iter, param_type* r);
[email protected]252cad62010-08-18 18:33:57734 static void Log(const param_type& p, std::string* l);
[email protected]d2e884d2009-06-22 20:37:52735};
736
[email protected]7d5c3ac2009-02-04 08:58:19737#if defined(OS_WIN)
738template <>
739struct ParamTraits<XFORM> {
740 typedef XFORM param_type;
741 static void Write(Message* m, const param_type& p) {
742 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
743 }
744 static bool Read(const Message* m, void** iter, param_type* r) {
745 const char *data;
746 int data_size = 0;
747 bool result = m->ReadData(iter, &data, &data_size);
748 if (result && data_size == sizeof(XFORM)) {
749 memcpy(r, data, sizeof(XFORM));
750 } else {
751 result = false;
752 NOTREACHED();
753 }
754
755 return result;
756 }
[email protected]252cad62010-08-18 18:33:57757 static void Log(const param_type& p, std::string* l) {
758 l->append("<XFORM>");
[email protected]7d5c3ac2009-02-04 08:58:19759 }
760};
761#endif // defined(OS_WIN)
762
[email protected]7d5c3ac2009-02-04 08:58:19763struct LogData {
[email protected]9a3a293b2009-06-04 22:28:16764 std::string channel;
[email protected]8bef70e2009-04-14 19:11:24765 int32 routing_id;
[email protected]168ae922009-12-04 18:08:45766 uint32 type; // "User-defined" message type, from ipc_message.h.
[email protected]252cad62010-08-18 18:33:57767 std::string flags;
[email protected]7d5c3ac2009-02-04 08:58:19768 int64 sent; // Time that the message was sent (i.e. at Send()).
769 int64 receive; // Time before it was dispatched (i.e. before calling
770 // OnMessageReceived).
771 int64 dispatch; // Time after it was dispatched (i.e. after calling
772 // OnMessageReceived).
[email protected]252cad62010-08-18 18:33:57773 std::string message_name;
774 std::string params;
[email protected]7d5c3ac2009-02-04 08:58:19775};
776
777template <>
778struct ParamTraits<LogData> {
779 typedef LogData param_type;
780 static void Write(Message* m, const param_type& p) {
781 WriteParam(m, p.channel);
[email protected]8bef70e2009-04-14 19:11:24782 WriteParam(m, p.routing_id);
[email protected]7d5c3ac2009-02-04 08:58:19783 WriteParam(m, static_cast<int>(p.type));
784 WriteParam(m, p.flags);
785 WriteParam(m, p.sent);
786 WriteParam(m, p.receive);
787 WriteParam(m, p.dispatch);
788 WriteParam(m, p.params);
789 }
790 static bool Read(const Message* m, void** iter, param_type* r) {
791 int type;
792 bool result =
793 ReadParam(m, iter, &r->channel) &&
[email protected]25af92052010-03-26 22:21:17794 ReadParam(m, iter, &r->routing_id) &&
[email protected]7d5c3ac2009-02-04 08:58:19795 ReadParam(m, iter, &type) &&
796 ReadParam(m, iter, &r->flags) &&
797 ReadParam(m, iter, &r->sent) &&
798 ReadParam(m, iter, &r->receive) &&
799 ReadParam(m, iter, &r->dispatch) &&
800 ReadParam(m, iter, &r->params);
801 r->type = static_cast<uint16>(type);
802 return result;
803 }
[email protected]252cad62010-08-18 18:33:57804 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19805 // Doesn't make sense to implement this!
806 }
807};
808
[email protected]eb47a132009-03-04 00:39:56809template <>
[email protected]503683f2009-02-26 09:13:01810struct ParamTraits<Message> {
811 static void Write(Message* m, const Message& p) {
812 m->WriteInt(p.size());
813 m->WriteData(reinterpret_cast<const char*>(p.data()), p.size());
814 }
815 static bool Read(const Message* m, void** iter, Message* r) {
816 int size;
817 if (!m->ReadInt(iter, &size))
818 return false;
819 const char* data;
820 if (!m->ReadData(iter, &data, &size))
821 return false;
822 *r = Message(data, size);
823 return true;
824 }
[email protected]252cad62010-08-18 18:33:57825 static void Log(const Message& p, std::string* l) {
826 l->append("<IPC::Message>");
[email protected]503683f2009-02-26 09:13:01827 }
828};
829
830template <>
[email protected]7d5c3ac2009-02-04 08:58:19831struct ParamTraits<Tuple0> {
832 typedef Tuple0 param_type;
833 static void Write(Message* m, const param_type& p) {
834 }
835 static bool Read(const Message* m, void** iter, param_type* r) {
836 return true;
837 }
[email protected]252cad62010-08-18 18:33:57838 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19839 }
840};
841
842template <class A>
843struct ParamTraits< Tuple1<A> > {
844 typedef Tuple1<A> param_type;
845 static void Write(Message* m, const param_type& p) {
846 WriteParam(m, p.a);
847 }
848 static bool Read(const Message* m, void** iter, param_type* r) {
849 return ReadParam(m, iter, &r->a);
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);
853 }
854};
855
856template <class A, class B>
857struct ParamTraits< Tuple2<A, B> > {
858 typedef Tuple2<A, B> param_type;
859 static void Write(Message* m, const param_type& p) {
860 WriteParam(m, p.a);
861 WriteParam(m, p.b);
862 }
863 static bool Read(const Message* m, void** iter, param_type* r) {
864 return (ReadParam(m, iter, &r->a) &&
865 ReadParam(m, iter, &r->b));
866 }
[email protected]252cad62010-08-18 18:33:57867 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19868 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57869 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19870 LogParam(p.b, l);
871 }
872};
873
874template <class A, class B, class C>
875struct ParamTraits< Tuple3<A, B, C> > {
876 typedef Tuple3<A, B, C> param_type;
877 static void Write(Message* m, const param_type& p) {
878 WriteParam(m, p.a);
879 WriteParam(m, p.b);
880 WriteParam(m, p.c);
881 }
882 static bool Read(const Message* m, void** iter, param_type* r) {
883 return (ReadParam(m, iter, &r->a) &&
884 ReadParam(m, iter, &r->b) &&
885 ReadParam(m, iter, &r->c));
886 }
[email protected]252cad62010-08-18 18:33:57887 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19888 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57889 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19890 LogParam(p.b, l);
[email protected]252cad62010-08-18 18:33:57891 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19892 LogParam(p.c, l);
893 }
894};
895
896template <class A, class B, class C, class D>
897struct ParamTraits< Tuple4<A, B, C, D> > {
898 typedef Tuple4<A, B, C, D> param_type;
899 static void Write(Message* m, const param_type& p) {
900 WriteParam(m, p.a);
901 WriteParam(m, p.b);
902 WriteParam(m, p.c);
903 WriteParam(m, p.d);
904 }
905 static bool Read(const Message* m, void** iter, param_type* r) {
906 return (ReadParam(m, iter, &r->a) &&
907 ReadParam(m, iter, &r->b) &&
908 ReadParam(m, iter, &r->c) &&
909 ReadParam(m, iter, &r->d));
910 }
[email protected]252cad62010-08-18 18:33:57911 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19912 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57913 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19914 LogParam(p.b, l);
[email protected]252cad62010-08-18 18:33:57915 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19916 LogParam(p.c, l);
[email protected]252cad62010-08-18 18:33:57917 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19918 LogParam(p.d, l);
919 }
920};
921
922template <class A, class B, class C, class D, class E>
923struct ParamTraits< Tuple5<A, B, C, D, E> > {
924 typedef Tuple5<A, B, C, D, E> param_type;
925 static void Write(Message* m, const param_type& p) {
926 WriteParam(m, p.a);
927 WriteParam(m, p.b);
928 WriteParam(m, p.c);
929 WriteParam(m, p.d);
930 WriteParam(m, p.e);
931 }
932 static bool Read(const Message* m, void** iter, param_type* r) {
933 return (ReadParam(m, iter, &r->a) &&
934 ReadParam(m, iter, &r->b) &&
935 ReadParam(m, iter, &r->c) &&
936 ReadParam(m, iter, &r->d) &&
937 ReadParam(m, iter, &r->e));
938 }
[email protected]252cad62010-08-18 18:33:57939 static void Log(const param_type& p, std::string* l) {
[email protected]7d5c3ac2009-02-04 08:58:19940 LogParam(p.a, l);
[email protected]252cad62010-08-18 18:33:57941 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19942 LogParam(p.b, l);
[email protected]252cad62010-08-18 18:33:57943 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19944 LogParam(p.c, l);
[email protected]252cad62010-08-18 18:33:57945 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19946 LogParam(p.d, l);
[email protected]252cad62010-08-18 18:33:57947 l->append(", ");
[email protected]7d5c3ac2009-02-04 08:58:19948 LogParam(p.e, l);
949 }
950};
951
[email protected]7d5c3ac2009-02-04 08:58:19952//-----------------------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:29953// Generic message subclasses
954
955// Used for asynchronous messages.
[email protected]81a34412009-01-05 19:17:24956template <class ParamType>
initial.commit09911bf2008-07-26 23:55:29957class MessageWithTuple : public Message {
958 public:
[email protected]81a34412009-01-05 19:17:24959 typedef ParamType Param;
[email protected]7a4de7a62010-08-17 18:38:24960 typedef typename TupleTypes<ParamType>::ParamTuple RefParam;
[email protected]81a34412009-01-05 19:17:24961
[email protected]7a4de7a62010-08-17 18:38:24962 // The constructor and the Read() method's templated implementations are in
963 // ipc_message_utils_impl.h. The subclass constructor and Log() methods call
964 // the templated versions of these and make sure there are instantiations in
965 // those translation units.
966 MessageWithTuple(int32 routing_id, uint32 type, const RefParam& p);
[email protected]071b4b92010-08-09 16:06:58967
[email protected]7a4de7a62010-08-17 18:38:24968 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE;
initial.commit09911bf2008-07-26 23:55:29969
970 // Generic dispatcher. Should cover most cases.
971 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:19972 static bool Dispatch(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:29973 Param p;
974 if (Read(msg, &p)) {
975 DispatchToMethod(obj, func, p);
976 return true;
977 }
978 return false;
979 }
980
981 // The following dispatchers exist for the case where the callback function
982 // needs the message as well. They assume that "Param" is a type of Tuple
983 // (except the one arg case, as there is no Tuple1).
984 template<class T, typename TA>
[email protected]7d5c3ac2009-02-04 08:58:19985 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:29986 void (T::*func)(const Message&, TA)) {
987 Param p;
988 if (Read(msg, &p)) {
[email protected]c2fe31542009-05-20 18:24:14989 (obj->*func)(*msg, p.a);
initial.commit09911bf2008-07-26 23:55:29990 return true;
991 }
992 return false;
993 }
994
995 template<class T, typename TA, typename TB>
[email protected]7d5c3ac2009-02-04 08:58:19996 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:29997 void (T::*func)(const Message&, TA, TB)) {
998 Param p;
999 if (Read(msg, &p)) {
1000 (obj->*func)(*msg, p.a, p.b);
1001 return true;
1002 }
1003 return false;
1004 }
1005
1006 template<class T, typename TA, typename TB, typename TC>
[email protected]7d5c3ac2009-02-04 08:58:191007 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291008 void (T::*func)(const Message&, TA, TB, TC)) {
1009 Param p;
1010 if (Read(msg, &p)) {
1011 (obj->*func)(*msg, p.a, p.b, p.c);
1012 return true;
1013 }
1014 return false;
1015 }
1016
1017 template<class T, typename TA, typename TB, typename TC, typename TD>
[email protected]7d5c3ac2009-02-04 08:58:191018 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291019 void (T::*func)(const Message&, TA, TB, TC, TD)) {
1020 Param p;
1021 if (Read(msg, &p)) {
1022 (obj->*func)(*msg, p.a, p.b, p.c, p.d);
1023 return true;
1024 }
1025 return false;
1026 }
1027
1028 template<class T, typename TA, typename TB, typename TC, typename TD,
1029 typename TE>
[email protected]7d5c3ac2009-02-04 08:58:191030 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291031 void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
1032 Param p;
1033 if (Read(msg, &p)) {
1034 (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
1035 return true;
1036 }
1037 return false;
1038 }
1039
[email protected]deb57402009-02-06 01:35:301040 // Functions used to do manual unpacking. Only used by the automation code,
1041 // these should go away once that code uses SyncChannel.
1042 template<typename TA, typename TB>
1043 static bool Read(const IPC::Message* msg, TA* a, TB* b) {
1044 ParamType params;
1045 if (!Read(msg, &params))
1046 return false;
1047 *a = params.a;
1048 *b = params.b;
1049 return true;
1050 }
1051
1052 template<typename TA, typename TB, typename TC>
1053 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
1054 ParamType params;
1055 if (!Read(msg, &params))
1056 return false;
1057 *a = params.a;
1058 *b = params.b;
1059 *c = params.c;
1060 return true;
1061 }
1062
1063 template<typename TA, typename TB, typename TC, typename TD>
1064 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
1065 ParamType params;
1066 if (!Read(msg, &params))
1067 return false;
1068 *a = params.a;
1069 *b = params.b;
1070 *c = params.c;
1071 *d = params.d;
1072 return true;
1073 }
1074
1075 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1076 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
1077 ParamType params;
1078 if (!Read(msg, &params))
1079 return false;
1080 *a = params.a;
1081 *b = params.b;
1082 *c = params.c;
1083 *d = params.d;
1084 *e = params.e;
1085 return true;
1086 }
initial.commit09911bf2008-07-26 23:55:291087};
1088
[email protected]7a4de7a62010-08-17 18:38:241089// defined in ipc_logging.cc
1090void GenerateLogData(const std::string& channel, const Message& message,
1091 LogData* data);
1092
1093
1094#if defined(IPC_MESSAGE_LOG_ENABLED)
[email protected]252cad62010-08-18 18:33:571095inline void AddOutputParamsToLog(const Message* msg, std::string* l) {
1096 const std::string& output_params = msg->output_params();
[email protected]7a4de7a62010-08-17 18:38:241097 if (!l->empty() && !output_params.empty())
[email protected]252cad62010-08-18 18:33:571098 l->append(", ");
[email protected]7a4de7a62010-08-17 18:38:241099
1100 l->append(output_params);
1101}
1102
1103template <class ReplyParamType>
1104inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1105 const Message* msg) {
1106 if (msg->received_time() != 0) {
[email protected]252cad62010-08-18 18:33:571107 std::string output_params;
[email protected]7a4de7a62010-08-17 18:38:241108 LogParam(reply_params, &output_params);
1109 msg->set_output_params(output_params);
1110 }
1111}
1112
1113inline void ConnectMessageAndReply(const Message* msg, Message* reply) {
1114 if (msg->sent_time()) {
1115 // Don't log the sync message after dispatch, as we don't have the
1116 // output parameters at that point. Instead, save its data and log it
1117 // with the outgoing reply message when it's sent.
1118 LogData* data = new LogData;
1119 GenerateLogData("", *msg, data);
1120 msg->set_dont_log();
1121 reply->set_sync_log_data(data);
1122 }
1123}
1124#else
[email protected]252cad62010-08-18 18:33:571125inline void AddOutputParamsToLog(const Message* msg, std::string* l) {}
[email protected]7a4de7a62010-08-17 18:38:241126
1127template <class ReplyParamType>
1128inline void LogReplyParamsToMessage(const ReplyParamType& reply_params,
1129 const Message* msg) {}
1130
1131inline void ConnectMessageAndReply(const Message* msg, Message* reply) {}
1132#endif
1133
initial.commit09911bf2008-07-26 23:55:291134// This class assumes that its template argument is a RefTuple (a Tuple with
[email protected]7a4de7a62010-08-17 18:38:241135// reference elements). This would go into ipc_message_utils_impl.h, but it is
1136// also used by chrome_frame.
initial.commit09911bf2008-07-26 23:55:291137template <class RefTuple>
1138class ParamDeserializer : public MessageReplyDeserializer {
1139 public:
[email protected]e1981f432008-08-12 15:22:131140 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
initial.commit09911bf2008-07-26 23:55:291141
1142 bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
1143 return ReadParam(&msg, &iter, &out_);
1144 }
1145
1146 RefTuple out_;
1147};
1148
initial.commit09911bf2008-07-26 23:55:291149// Used for synchronous messages.
[email protected]75e5a872009-04-02 23:56:111150template <class SendParamType, class ReplyParamType>
initial.commit09911bf2008-07-26 23:55:291151class MessageWithReply : public SyncMessage {
1152 public:
[email protected]75e5a872009-04-02 23:56:111153 typedef SendParamType SendParam;
[email protected]7a4de7a62010-08-17 18:38:241154 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam;
[email protected]75e5a872009-04-02 23:56:111155 typedef ReplyParamType ReplyParam;
1156
[email protected]168ae922009-12-04 18:08:451157 MessageWithReply(int32 routing_id, uint32 type,
[email protected]7a4de7a62010-08-17 18:38:241158 const RefSendParam& send, const ReplyParam& reply);
1159 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE;
1160 static bool ReadReplyParam(
1161 const Message* msg,
1162 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE;
initial.commit09911bf2008-07-26 23:55:291163
1164 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191165 static bool Dispatch(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291166 SendParam send_params;
initial.commit09911bf2008-07-26 23:55:291167 Message* reply = GenerateReply(msg);
1168 bool error;
[email protected]7a4de7a62010-08-17 18:38:241169 if (ReadSendParam(msg, &send_params)) {
1170 typename TupleTypes<ReplyParam>::ValueTuple reply_params;
initial.commit09911bf2008-07-26 23:55:291171 DispatchToMethod(obj, func, send_params, &reply_params);
1172 WriteParam(reply, reply_params);
1173 error = false;
[email protected]7a4de7a62010-08-17 18:38:241174 LogReplyParamsToMessage(reply_params, msg);
initial.commit09911bf2008-07-26 23:55:291175 } else {
1176 NOTREACHED() << "Error deserializing message " << msg->type();
1177 reply->set_reply_error();
1178 error = true;
1179 }
1180
1181 obj->Send(reply);
1182 return !error;
1183 }
1184
1185 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191186 static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291187 SendParam send_params;
initial.commit09911bf2008-07-26 23:55:291188 Message* reply = GenerateReply(msg);
1189 bool error;
[email protected]7a4de7a62010-08-17 18:38:241190 if (ReadSendParam(msg, &send_params)) {
initial.commit09911bf2008-07-26 23:55:291191 Tuple1<Message&> t = MakeRefTuple(*reply);
[email protected]7a4de7a62010-08-17 18:38:241192 ConnectMessageAndReply(msg, reply);
initial.commit09911bf2008-07-26 23:55:291193 DispatchToMethod(obj, func, send_params, &t);
1194 error = false;
1195 } else {
1196 NOTREACHED() << "Error deserializing message " << msg->type();
1197 reply->set_reply_error();
1198 obj->Send(reply);
1199 error = true;
1200 }
1201 return !error;
1202 }
1203
1204 template<typename TA>
1205 static void WriteReplyParams(Message* reply, TA a) {
1206 ReplyParam p(a);
1207 WriteParam(reply, p);
1208 }
1209
1210 template<typename TA, typename TB>
1211 static void WriteReplyParams(Message* reply, TA a, TB b) {
1212 ReplyParam p(a, b);
1213 WriteParam(reply, p);
1214 }
1215
1216 template<typename TA, typename TB, typename TC>
1217 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
1218 ReplyParam p(a, b, c);
1219 WriteParam(reply, p);
1220 }
1221
1222 template<typename TA, typename TB, typename TC, typename TD>
1223 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
1224 ReplyParam p(a, b, c, d);
1225 WriteParam(reply, p);
1226 }
1227
1228 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1229 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
1230 ReplyParam p(a, b, c, d, e);
1231 WriteParam(reply, p);
1232 }
1233};
1234
[email protected]7d5c3ac2009-02-04 08:58:191235//-----------------------------------------------------------------------------
1236
[email protected]3178f4e22008-08-05 21:20:411237} // namespace IPC
initial.commit09911bf2008-07-26 23:55:291238
[email protected]946d1b22009-07-22 23:57:211239#endif // IPC_IPC_MESSAGE_UTILS_H_