blob: aab80ee96784d5427b1f4d8e753bf9274b980655 [file] [log] [blame]
[email protected]225c8f52010-02-05 22:23:201// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]946d1b22009-07-22 23:57:215#ifndef IPC_IPC_MESSAGE_UTILS_H_
6#define IPC_IPC_MESSAGE_UTILS_H_
[email protected]32b76ef2010-07-26 23:08:247#pragma once
initial.commit09911bf2008-07-26 23:55:298
[email protected]379e7a52010-03-09 00:38:419#include <algorithm>
initial.commit09911bf2008-07-26 23:55:2910#include <string>
11#include <vector>
12#include <map>
[email protected]96da6962010-05-13 19:10:3413#include <set>
initial.commit09911bf2008-07-26 23:55:2914
[email protected]690a99c2009-01-06 16:48:4515#include "base/file_path.h"
[email protected]dce5df52009-06-29 17:58:2516#include "base/format_macros.h"
[email protected]15bf8712009-08-27 00:55:0217#include "base/nullable_string16.h"
[email protected]eb47a132009-03-04 00:39:5618#include "base/string16.h"
[email protected]dce5df52009-06-29 17:58:2519#include "base/string_util.h"
[email protected]379e7a52010-03-09 00:38:4120#include "base/utf_string_conversions.h"
[email protected]946d1b22009-07-22 23:57:2121#include "base/time.h"
initial.commit09911bf2008-07-26 23:55:2922#include "base/tuple.h"
[email protected]946d1b22009-07-22 23:57:2123#include "base/values.h"
[email protected]526776c2009-02-07 00:39:2624#if defined(OS_POSIX)
[email protected]946d1b22009-07-22 23:57:2125#include "ipc/file_descriptor_set_posix.h"
[email protected]526776c2009-02-07 00:39:2626#endif
[email protected]946d1b22009-07-22 23:57:2127#include "ipc/ipc_channel_handle.h"
28#include "ipc/ipc_sync_message.h"
[email protected]82e5ee82009-04-03 02:29:4529
[email protected]f91cb992009-02-04 20:10:1230// Used by IPC_BEGIN_MESSAGES so that each message class starts from a unique
31// base. Messages have unique IDs across channels in order for the IPC logging
32// code to figure out the message class from its ID.
33enum IPCMessageStart {
34 // By using a start value of 0 for automation messages, we keep backward
35 // compatibility with old builds.
36 AutomationMsgStart = 0,
37 ViewMsgStart,
38 ViewHostMsgStart,
39 PluginProcessMsgStart,
40 PluginProcessHostMsgStart,
41 PluginMsgStart,
42 PluginHostMsgStart,
[email protected]96da6962010-05-13 19:10:3443 ProfileImportProcessMsgStart,
44 ProfileImportProcessHostMsgStart,
[email protected]f91cb992009-02-04 20:10:1245 NPObjectMsgStart,
46 TestMsgStart,
[email protected]503683f2009-02-26 09:13:0147 DevToolsAgentMsgStart,
48 DevToolsClientMsgStart,
[email protected]eb47a132009-03-04 00:39:5649 WorkerProcessMsgStart,
50 WorkerProcessHostMsgStart,
51 WorkerMsgStart,
52 WorkerHostMsgStart,
[email protected]d032f492009-09-29 00:33:4653 NaClProcessMsgStart,
[email protected]246a70452010-03-05 21:53:5054 GpuCommandBufferMsgStart,
[email protected]60f14392009-12-15 20:46:3255 UtilityMsgStart,
56 UtilityHostMsgStart,
[email protected]c0fc0942010-01-13 00:55:3757 GpuMsgStart,
58 GpuHostMsgStart,
[email protected]246a70452010-03-05 21:53:5059 GpuChannelMsgStart,
[email protected]f91cb992009-02-04 20:10:1260 // NOTE: When you add a new message class, also update
61 // IPCStatusView::IPCStatusView to ensure logging works.
[email protected]f91cb992009-02-04 20:10:1262 LastMsgIndex
63};
64
initial.commit09911bf2008-07-26 23:55:2965namespace IPC {
66
initial.commit09911bf2008-07-26 23:55:2967//-----------------------------------------------------------------------------
68// An iterator class for reading the fields contained within a Message.
69
70class MessageIterator {
71 public:
[email protected]e1981f432008-08-12 15:22:1372 explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
initial.commit09911bf2008-07-26 23:55:2973 }
74 int NextInt() const {
[email protected]9422b7dc2009-12-30 20:09:0275 int val = -1;
initial.commit09911bf2008-07-26 23:55:2976 if (!msg_.ReadInt(&iter_, &val))
77 NOTREACHED();
78 return val;
79 }
initial.commit09911bf2008-07-26 23:55:2980 const std::string NextString() const {
81 std::string val;
82 if (!msg_.ReadString(&iter_, &val))
83 NOTREACHED();
84 return val;
85 }
86 const std::wstring NextWString() const {
87 std::wstring val;
88 if (!msg_.ReadWString(&iter_, &val))
89 NOTREACHED();
90 return val;
91 }
[email protected]225c8f52010-02-05 22:23:2092 void NextData(const char** data, int* length) const {
initial.commit09911bf2008-07-26 23:55:2993 if (!msg_.ReadData(&iter_, data, length)) {
94 NOTREACHED();
95 }
96 }
97 private:
98 const Message& msg_;
99 mutable void* iter_;
100};
101
102//-----------------------------------------------------------------------------
[email protected]7d5c3ac2009-02-04 08:58:19103// ParamTraits specializations, etc.
104
[email protected]7b291f92009-08-14 05:43:53105template <class P> struct ParamTraits {
106};
107
108template <class P>
109struct SimilarTypeTraits {
110 typedef P Type;
111};
[email protected]7d5c3ac2009-02-04 08:58:19112
113template <class P>
114static inline void WriteParam(Message* m, const P& p) {
[email protected]7b291f92009-08-14 05:43:53115 typedef typename SimilarTypeTraits<P>::Type Type;
[email protected]46ce5b562010-06-16 18:39:53116 ParamTraits<Type>::Write(m, static_cast<const Type& >(p));
[email protected]7d5c3ac2009-02-04 08:58:19117}
118
119template <class P>
[email protected]1e86aa62009-04-24 21:22:33120static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
121 P* p) {
[email protected]7b291f92009-08-14 05:43:53122 typedef typename SimilarTypeTraits<P>::Type Type;
123 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p));
[email protected]7d5c3ac2009-02-04 08:58:19124}
125
126template <class P>
127static inline void LogParam(const P& p, std::wstring* l) {
[email protected]7b291f92009-08-14 05:43:53128 typedef typename SimilarTypeTraits<P>::Type Type;
[email protected]46ce5b562010-06-16 18:39:53129 ParamTraits<Type>::Log(static_cast<const Type& >(p), l);
[email protected]7d5c3ac2009-02-04 08:58:19130}
131
132template <>
133struct ParamTraits<bool> {
134 typedef bool param_type;
135 static void Write(Message* m, const param_type& p) {
136 m->WriteBool(p);
137 }
138 static bool Read(const Message* m, void** iter, param_type* r) {
139 return m->ReadBool(iter, r);
140 }
141 static void Log(const param_type& p, std::wstring* l) {
142 l->append(p ? L"true" : L"false");
143 }
144};
145
146template <>
147struct ParamTraits<int> {
148 typedef int param_type;
149 static void Write(Message* m, const param_type& p) {
150 m->WriteInt(p);
151 }
152 static bool Read(const Message* m, void** iter, param_type* r) {
153 return m->ReadInt(iter, r);
154 }
155 static void Log(const param_type& p, std::wstring* l) {
156 l->append(StringPrintf(L"%d", p));
157 }
158};
159
160template <>
[email protected]63263f92009-07-28 19:35:08161struct ParamTraits<unsigned int> {
162 typedef unsigned int param_type;
163 static void Write(Message* m, const param_type& p) {
164 m->WriteInt(p);
165 }
166 static bool Read(const Message* m, void** iter, param_type* r) {
167 return m->ReadInt(iter, reinterpret_cast<int*>(r));
168 }
169 static void Log(const param_type& p, std::wstring* l) {
170 l->append(StringPrintf(L"%d", p));
171 }
172};
173
174template <>
[email protected]7d5c3ac2009-02-04 08:58:19175struct ParamTraits<long> {
176 typedef long param_type;
177 static void Write(Message* m, const param_type& p) {
178 m->WriteLong(p);
179 }
180 static bool Read(const Message* m, void** iter, param_type* r) {
181 return m->ReadLong(iter, r);
182 }
183 static void Log(const param_type& p, std::wstring* l) {
[email protected]63263f92009-07-28 19:35:08184 l->append(StringPrintf(L"%ld", p));
[email protected]7d5c3ac2009-02-04 08:58:19185 }
186};
187
[email protected]140c3032009-06-26 18:22:54188template <>
189struct ParamTraits<unsigned long> {
190 typedef unsigned long param_type;
191 static void Write(Message* m, const param_type& p) {
192 m->WriteLong(p);
193 }
194 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]63263f92009-07-28 19:35:08195 return m->ReadLong(iter, reinterpret_cast<long*>(r));
[email protected]140c3032009-06-26 18:22:54196 }
197 static void Log(const param_type& p, std::wstring* l) {
[email protected]63263f92009-07-28 19:35:08198 l->append(StringPrintf(L"%lu", p));
[email protected]7d5c3ac2009-02-04 08:58:19199 }
200};
201
202template <>
[email protected]63263f92009-07-28 19:35:08203struct ParamTraits<long long> {
204 typedef long long param_type;
[email protected]7d5c3ac2009-02-04 08:58:19205 static void Write(Message* m, const param_type& p) {
206 m->WriteInt64(static_cast<int64>(p));
207 }
208 static bool Read(const Message* m, void** iter, param_type* r) {
209 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
210 }
211 static void Log(const param_type& p, std::wstring* l) {
[email protected]63263f92009-07-28 19:35:08212 l->append(Int64ToWString(static_cast<int64>(p)));
213 }
214};
215
216template <>
217struct ParamTraits<unsigned long long> {
218 typedef unsigned long long param_type;
219 static void Write(Message* m, const param_type& p) {
220 m->WriteInt64(p);
221 }
222 static bool Read(const Message* m, void** iter, param_type* r) {
223 return m->ReadInt64(iter, reinterpret_cast<int64*>(r));
224 }
225 static void Log(const param_type& p, std::wstring* l) {
226 l->append(Uint64ToWString(p));
[email protected]7d5c3ac2009-02-04 08:58:19227 }
228};
229
[email protected]20199662010-06-17 03:29:26230// Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients
231// should be sure to check the sanity of these values after receiving them over
232// IPC.
233template <>
234struct ParamTraits<float> {
235 typedef float param_type;
236 static void Write(Message* m, const param_type& p) {
237 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
238 }
239 static bool Read(const Message* m, void** iter, param_type* r) {
240 const char *data;
241 int data_size;
242 if (!m->ReadData(iter, &data, &data_size) ||
243 data_size != sizeof(param_type)) {
244 NOTREACHED();
245 return false;
246 }
247 memcpy(r, data, sizeof(param_type));
248 return true;
249 }
250 static void Log(const param_type& p, std::wstring* l) {
251 l->append(StringPrintf(L"e", p));
252 }
253};
254
[email protected]7d5c3ac2009-02-04 08:58:19255template <>
256struct ParamTraits<double> {
257 typedef double param_type;
258 static void Write(Message* m, const param_type& p) {
259 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
260 }
261 static bool Read(const Message* m, void** iter, param_type* r) {
262 const char *data;
[email protected]20199662010-06-17 03:29:26263 int data_size;
264 if (!m->ReadData(iter, &data, &data_size) ||
265 data_size != sizeof(param_type)) {
[email protected]7d5c3ac2009-02-04 08:58:19266 NOTREACHED();
[email protected]20199662010-06-17 03:29:26267 return false;
[email protected]7d5c3ac2009-02-04 08:58:19268 }
[email protected]20199662010-06-17 03:29:26269 memcpy(r, data, sizeof(param_type));
270 return true;
[email protected]7d5c3ac2009-02-04 08:58:19271 }
272 static void Log(const param_type& p, std::wstring* l) {
273 l->append(StringPrintf(L"e", p));
274 }
275};
276
277template <>
278struct ParamTraits<wchar_t> {
279 typedef wchar_t param_type;
280 static void Write(Message* m, const param_type& p) {
281 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
282 }
283 static bool Read(const Message* m, void** iter, param_type* r) {
284 const char *data;
285 int data_size = 0;
286 bool result = m->ReadData(iter, &data, &data_size);
287 if (result && data_size == sizeof(param_type)) {
288 memcpy(r, data, sizeof(param_type));
289 } else {
290 result = false;
291 NOTREACHED();
292 }
293
294 return result;
295 }
296 static void Log(const param_type& p, std::wstring* l) {
297 l->append(StringPrintf(L"%lc", p));
298 }
299};
300
301template <>
302struct ParamTraits<base::Time> {
303 typedef base::Time param_type;
304 static void Write(Message* m, const param_type& p) {
305 ParamTraits<int64>::Write(m, p.ToInternalValue());
306 }
307 static bool Read(const Message* m, void** iter, param_type* r) {
308 int64 value;
309 if (!ParamTraits<int64>::Read(m, iter, &value))
310 return false;
311 *r = base::Time::FromInternalValue(value);
312 return true;
313 }
314 static void Log(const param_type& p, std::wstring* l) {
315 ParamTraits<int64>::Log(p.ToInternalValue(), l);
316 }
317};
318
319#if defined(OS_WIN)
320template <>
321struct ParamTraits<LOGFONT> {
322 typedef LOGFONT param_type;
323 static void Write(Message* m, const param_type& p) {
324 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
325 }
326 static bool Read(const Message* m, void** iter, param_type* r) {
327 const char *data;
328 int data_size = 0;
329 bool result = m->ReadData(iter, &data, &data_size);
330 if (result && data_size == sizeof(LOGFONT)) {
331 memcpy(r, data, sizeof(LOGFONT));
332 } else {
333 result = false;
334 NOTREACHED();
335 }
336
337 return result;
338 }
339 static void Log(const param_type& p, std::wstring* l) {
340 l->append(StringPrintf(L"<LOGFONT>"));
341 }
342};
343
344template <>
345struct ParamTraits<MSG> {
346 typedef MSG param_type;
347 static void Write(Message* m, const param_type& p) {
348 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
349 }
350 static bool Read(const Message* m, void** iter, param_type* r) {
351 const char *data;
352 int data_size = 0;
353 bool result = m->ReadData(iter, &data, &data_size);
354 if (result && data_size == sizeof(MSG)) {
355 memcpy(r, data, sizeof(MSG));
356 } else {
357 result = false;
358 NOTREACHED();
359 }
360
361 return result;
362 }
363};
364#endif // defined(OS_WIN)
365
366template <>
[email protected]584f2b22009-05-21 01:01:59367struct ParamTraits<DictionaryValue> {
368 typedef DictionaryValue param_type;
369 static void Write(Message* m, const param_type& p);
370 static bool Read(const Message* m, void** iter, param_type* r);
371 static void Log(const param_type& p, std::wstring* l);
372};
373
374template <>
375struct ParamTraits<ListValue> {
376 typedef ListValue param_type;
377 static void Write(Message* m, const param_type& p);
378 static bool Read(const Message* m, void** iter, param_type* r);
379 static void Log(const param_type& p, std::wstring* l);
380};
381
382template <>
[email protected]7d5c3ac2009-02-04 08:58:19383struct ParamTraits<std::string> {
384 typedef std::string param_type;
385 static void Write(Message* m, const param_type& p) {
386 m->WriteString(p);
387 }
388 static bool Read(const Message* m, void** iter, param_type* r) {
389 return m->ReadString(iter, r);
390 }
391 static void Log(const param_type& p, std::wstring* l) {
392 l->append(UTF8ToWide(p));
393 }
394};
395
[email protected]3dd7a7a2009-07-27 21:09:07396template<typename CharType>
397static void LogBytes(const std::vector<CharType>& data, std::wstring* out) {
398#if defined(OS_WIN)
399 // Windows has a GUI for logging, which can handle arbitrary binary data.
400 for (size_t i = 0; i < data.size(); ++i)
401 out->push_back(data[i]);
402#else
403 // On POSIX, we log to stdout, which we assume can display ASCII.
404 static const size_t kMaxBytesToLog = 100;
405 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
406 if (isprint(data[i]))
407 out->push_back(data[i]);
408 else
409 out->append(StringPrintf(L"[%02X]", static_cast<unsigned char>(data[i])));
410 }
411 if (data.size() > kMaxBytesToLog) {
412 out->append(
413 StringPrintf(L" and %u more bytes",
414 static_cast<unsigned>(data.size() - kMaxBytesToLog)));
415 }
416#endif
417}
418
[email protected]7d5c3ac2009-02-04 08:58:19419template <>
420struct ParamTraits<std::vector<unsigned char> > {
421 typedef std::vector<unsigned char> param_type;
422 static void Write(Message* m, const param_type& p) {
423 if (p.size() == 0) {
424 m->WriteData(NULL, 0);
425 } else {
426 m->WriteData(reinterpret_cast<const char*>(&p.front()),
427 static_cast<int>(p.size()));
428 }
429 }
430 static bool Read(const Message* m, void** iter, param_type* r) {
431 const char *data;
432 int data_size = 0;
433 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
434 return false;
435 r->resize(data_size);
436 if (data_size)
437 memcpy(&r->front(), data, data_size);
438 return true;
439 }
440 static void Log(const param_type& p, std::wstring* l) {
[email protected]3dd7a7a2009-07-27 21:09:07441 LogBytes(p, l);
[email protected]7d5c3ac2009-02-04 08:58:19442 }
443};
444
445template <>
446struct ParamTraits<std::vector<char> > {
447 typedef std::vector<char> param_type;
448 static void Write(Message* m, const param_type& p) {
449 if (p.size() == 0) {
450 m->WriteData(NULL, 0);
451 } else {
452 m->WriteData(&p.front(), static_cast<int>(p.size()));
453 }
454 }
455 static bool Read(const Message* m, void** iter, param_type* r) {
456 const char *data;
457 int data_size = 0;
458 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
459 return false;
460 r->resize(data_size);
461 if (data_size)
462 memcpy(&r->front(), data, data_size);
463 return true;
464 }
465 static void Log(const param_type& p, std::wstring* l) {
[email protected]3dd7a7a2009-07-27 21:09:07466 LogBytes(p, l);
[email protected]7d5c3ac2009-02-04 08:58:19467 }
468};
469
470template <class P>
471struct ParamTraits<std::vector<P> > {
472 typedef std::vector<P> param_type;
473 static void Write(Message* m, const param_type& p) {
474 WriteParam(m, static_cast<int>(p.size()));
475 for (size_t i = 0; i < p.size(); i++)
476 WriteParam(m, p[i]);
477 }
478 static bool Read(const Message* m, void** iter, param_type* r) {
479 int size;
[email protected]86440f52009-12-31 05:17:23480 // ReadLength() checks for < 0 itself.
[email protected]7d5c3ac2009-02-04 08:58:19481 if (!m->ReadLength(iter, &size))
482 return false;
483 // Resizing beforehand is not safe, see BUG 1006367 for details.
[email protected]86440f52009-12-31 05:17:23484 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size))
485 return false;
486 r->resize(size);
487 for (int i = 0; i < size; i++) {
488 if (!ReadParam(m, iter, &(*r)[i]))
489 return false;
[email protected]7d5c3ac2009-02-04 08:58:19490 }
491 return true;
492 }
493 static void Log(const param_type& p, std::wstring* l) {
494 for (size_t i = 0; i < p.size(); ++i) {
495 if (i != 0)
496 l->append(L" ");
[email protected]7d5c3ac2009-02-04 08:58:19497 LogParam((p[i]), l);
498 }
499 }
500};
501
[email protected]96da6962010-05-13 19:10:34502template <class P>
503struct ParamTraits<std::set<P> > {
504 typedef std::set<P> param_type;
505 static void Write(Message* m, const param_type& p) {
506 WriteParam(m, static_cast<int>(p.size()));
507 typename param_type::const_iterator iter;
508 for (iter = p.begin(); iter != p.end(); ++iter)
509 WriteParam(m, *iter);
510 }
511 static bool Read(const Message* m, void** iter, param_type* r) {
512 int size;
513 if (!m->ReadLength(iter, &size))
514 return false;
515 for (int i = 0; i < size; ++i) {
516 P item;
517 if (!ReadParam(m, iter, &item))
518 return false;
519 r->insert(item);
520 }
521 return true;
522 }
523 static void Log(const param_type& p, std::wstring* l) {
524 l->append(L"<std::set>");
525 }
526};
527
528
[email protected]7d5c3ac2009-02-04 08:58:19529template <class K, class V>
530struct ParamTraits<std::map<K, V> > {
531 typedef std::map<K, V> param_type;
532 static void Write(Message* m, const param_type& p) {
533 WriteParam(m, static_cast<int>(p.size()));
534 typename param_type::const_iterator iter;
535 for (iter = p.begin(); iter != p.end(); ++iter) {
536 WriteParam(m, iter->first);
537 WriteParam(m, iter->second);
538 }
539 }
540 static bool Read(const Message* m, void** iter, param_type* r) {
541 int size;
542 if (!ReadParam(m, iter, &size) || size < 0)
543 return false;
544 for (int i = 0; i < size; ++i) {
545 K k;
546 if (!ReadParam(m, iter, &k))
547 return false;
548 V& value = (*r)[k];
549 if (!ReadParam(m, iter, &value))
550 return false;
551 }
552 return true;
553 }
554 static void Log(const param_type& p, std::wstring* l) {
555 l->append(L"<std::map>");
556 }
557};
558
[email protected]eb47a132009-03-04 00:39:56559
[email protected]7d5c3ac2009-02-04 08:58:19560template <>
561struct ParamTraits<std::wstring> {
562 typedef std::wstring param_type;
563 static void Write(Message* m, const param_type& p) {
564 m->WriteWString(p);
565 }
566 static bool Read(const Message* m, void** iter, param_type* r) {
567 return m->ReadWString(iter, r);
568 }
569 static void Log(const param_type& p, std::wstring* l) {
570 l->append(p);
571 }
572};
573
[email protected]a5da6d612009-08-04 02:00:56574template <class A, class B>
575struct ParamTraits<std::pair<A, B> > {
576 typedef std::pair<A, B> param_type;
577 static void Write(Message* m, const param_type& p) {
578 WriteParam(m, p.first);
579 WriteParam(m, p.second);
580 }
581 static bool Read(const Message* m, void** iter, param_type* r) {
582 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second);
583 }
584 static void Log(const param_type& p, std::wstring* l) {
585 l->append(L"(");
586 LogParam(p.first, l);
587 l->append(L", ");
588 LogParam(p.second, l);
589 l->append(L")");
590 }
591};
592
[email protected]15bf8712009-08-27 00:55:02593template <>
594struct ParamTraits<NullableString16> {
595 typedef NullableString16 param_type;
596 static void Write(Message* m, const param_type& p) {
597 WriteParam(m, p.string());
598 WriteParam(m, p.is_null());
599 }
600 static bool Read(const Message* m, void** iter, param_type* r) {
601 string16 string;
602 if (!ReadParam(m, iter, &string))
603 return false;
604 bool is_null;
605 if (!ReadParam(m, iter, &is_null))
606 return false;
607 *r = NullableString16(string, is_null);
608 return true;
609 }
610 static void Log(const param_type& p, std::wstring* l) {
611 l->append(L"(");
612 LogParam(p.string(), l);
613 l->append(L", ");
614 LogParam(p.is_null(), l);
615 l->append(L")");
616 }
617};
618
[email protected]eb47a132009-03-04 00:39:56619// If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't
620// need this trait.
621#if !defined(WCHAR_T_IS_UTF16)
[email protected]eb47a132009-03-04 00:39:56622template <>
623struct ParamTraits<string16> {
624 typedef string16 param_type;
625 static void Write(Message* m, const param_type& p) {
[email protected]3a2a5d22009-03-04 03:36:36626 m->WriteString16(p);
[email protected]eb47a132009-03-04 00:39:56627 }
628 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]3a2a5d22009-03-04 03:36:36629 return m->ReadString16(iter, r);
[email protected]eb47a132009-03-04 00:39:56630 }
631 static void Log(const param_type& p, std::wstring* l) {
632 l->append(UTF16ToWide(p));
633 }
634};
[email protected]eb47a132009-03-04 00:39:56635#endif
636
[email protected]7d5c3ac2009-02-04 08:58:19637// and, a few more useful types...
638#if defined(OS_WIN)
639template <>
640struct ParamTraits<HANDLE> {
641 typedef HANDLE param_type;
642 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35643 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
644 // bit systems.
645 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 static void Log(const param_type& p, std::wstring* l) {
652 l->append(StringPrintf(L"0x%X", p));
653 }
654};
655
656template <>
657struct ParamTraits<HCURSOR> {
658 typedef HCURSOR param_type;
659 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35660 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19661 }
662 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35663 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
664 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19665 }
666 static void Log(const param_type& p, std::wstring* l) {
667 l->append(StringPrintf(L"0x%X", p));
668 }
669};
670
671template <>
[email protected]7d5c3ac2009-02-04 08:58:19672struct ParamTraits<HACCEL> {
673 typedef HACCEL param_type;
674 static void Write(Message* m, const param_type& p) {
[email protected]37477912010-02-09 08:06:35675 m->WriteUInt32(reinterpret_cast<uint32>(p));
[email protected]7d5c3ac2009-02-04 08:58:19676 }
677 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]37477912010-02-09 08:06:35678 DCHECK_EQ(sizeof(param_type), sizeof(uint32));
679 return m->ReadUInt32(iter, reinterpret_cast<uint32*>(r));
[email protected]7d5c3ac2009-02-04 08:58:19680 }
681};
682
683template <>
684struct ParamTraits<POINT> {
685 typedef POINT param_type;
686 static void Write(Message* m, const param_type& p) {
687 m->WriteInt(p.x);
688 m->WriteInt(p.y);
689 }
690 static bool Read(const Message* m, void** iter, param_type* r) {
691 int x, y;
692 if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
693 return false;
694 r->x = x;
695 r->y = y;
696 return true;
697 }
698 static void Log(const param_type& p, std::wstring* l) {
699 l->append(StringPrintf(L"(%d, %d)", p.x, p.y));
700 }
701};
702#endif // defined(OS_WIN)
703
704template <>
705struct ParamTraits<FilePath> {
706 typedef FilePath param_type;
707 static void Write(Message* m, const param_type& p) {
708 ParamTraits<FilePath::StringType>::Write(m, p.value());
709 }
710 static bool Read(const Message* m, void** iter, param_type* r) {
711 FilePath::StringType value;
712 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
713 return false;
714 *r = FilePath(value);
715 return true;
716 }
717 static void Log(const param_type& p, std::wstring* l) {
718 ParamTraits<FilePath::StringType>::Log(p.value(), l);
719 }
720};
721
[email protected]526776c2009-02-07 00:39:26722#if defined(OS_POSIX)
[email protected]2749885f2009-03-05 21:40:11723// FileDescriptors may be serialised over IPC channels on POSIX. On the
724// receiving side, the FileDescriptor is a valid duplicate of the file
725// descriptor which was transmitted: *it is not just a copy of the integer like
726// HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
727// this case, the receiving end will see a value of -1. *Zero is a valid file
728// descriptor*.
729//
730// The received file descriptor will have the |auto_close| flag set to true. The
731// code which handles the message is responsible for taking ownership of it.
732// File descriptors are OS resources and must be closed when no longer needed.
733//
734// When sending a file descriptor, the file descriptor must be valid at the time
735// of transmission. Since transmission is not synchronous, one should consider
736// dup()ing any file descriptors to be transmitted and setting the |auto_close|
737// flag, which causes the file descriptor to be closed after writing.
[email protected]526776c2009-02-07 00:39:26738template<>
[email protected]5fe733de2009-02-11 18:59:20739struct ParamTraits<base::FileDescriptor> {
740 typedef base::FileDescriptor param_type;
[email protected]526776c2009-02-07 00:39:26741 static void Write(Message* m, const param_type& p) {
[email protected]2749885f2009-03-05 21:40:11742 const bool valid = p.fd >= 0;
743 WriteParam(m, valid);
744
745 if (valid) {
746 if (!m->WriteFileDescriptor(p))
747 NOTREACHED();
748 }
[email protected]526776c2009-02-07 00:39:26749 }
750 static bool Read(const Message* m, void** iter, param_type* r) {
[email protected]2749885f2009-03-05 21:40:11751 bool valid;
752 if (!ReadParam(m, iter, &valid))
753 return false;
754
755 if (!valid) {
756 r->fd = -1;
757 r->auto_close = false;
758 return true;
759 }
760
[email protected]7135bb042009-02-12 04:05:28761 return m->ReadFileDescriptor(iter, r);
[email protected]526776c2009-02-07 00:39:26762 }
763 static void Log(const param_type& p, std::wstring* l) {
764 if (p.auto_close) {
[email protected]7135bb042009-02-12 04:05:28765 l->append(StringPrintf(L"FD(%d auto-close)", p.fd));
[email protected]526776c2009-02-07 00:39:26766 } else {
[email protected]7135bb042009-02-12 04:05:28767 l->append(StringPrintf(L"FD(%d)", p.fd));
[email protected]526776c2009-02-07 00:39:26768 }
769 }
770};
[email protected]379e7a52010-03-09 00:38:41771#endif // defined(OS_POSIX)
[email protected]526776c2009-02-07 00:39:26772
[email protected]d2e884d2009-06-22 20:37:52773// A ChannelHandle is basically a platform-inspecific wrapper around the
774// fact that IPC endpoints are handled specially on POSIX. See above comments
775// on FileDescriptor for more background.
776template<>
777struct ParamTraits<IPC::ChannelHandle> {
778 typedef ChannelHandle param_type;
779 static void Write(Message* m, const param_type& p) {
780 WriteParam(m, p.name);
781#if defined(OS_POSIX)
782 WriteParam(m, p.socket);
783#endif
784 }
785 static bool Read(const Message* m, void** iter, param_type* r) {
786 return ReadParam(m, iter, &r->name)
787#if defined(OS_POSIX)
788 && ReadParam(m, iter, &r->socket)
789#endif
790 ;
791 }
792 static void Log(const param_type& p, std::wstring* l) {
[email protected]e9abf8d2009-07-10 22:41:00793 l->append(ASCIIToWide(StringPrintf("ChannelHandle(%s", p.name.c_str())));
[email protected]d2e884d2009-06-22 20:37:52794#if defined(OS_POSIX)
795 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
796#endif
797 l->append(L")");
798 }
799};
800
[email protected]7d5c3ac2009-02-04 08:58:19801#if defined(OS_WIN)
802template <>
803struct ParamTraits<XFORM> {
804 typedef XFORM param_type;
805 static void Write(Message* m, const param_type& p) {
806 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
807 }
808 static bool Read(const Message* m, void** iter, param_type* r) {
809 const char *data;
810 int data_size = 0;
811 bool result = m->ReadData(iter, &data, &data_size);
812 if (result && data_size == sizeof(XFORM)) {
813 memcpy(r, data, sizeof(XFORM));
814 } else {
815 result = false;
816 NOTREACHED();
817 }
818
819 return result;
820 }
821 static void Log(const param_type& p, std::wstring* l) {
822 l->append(L"<XFORM>");
823 }
824};
825#endif // defined(OS_WIN)
826
[email protected]7d5c3ac2009-02-04 08:58:19827struct LogData {
[email protected]9a3a293b2009-06-04 22:28:16828 std::string channel;
[email protected]8bef70e2009-04-14 19:11:24829 int32 routing_id;
[email protected]168ae922009-12-04 18:08:45830 uint32 type; // "User-defined" message type, from ipc_message.h.
[email protected]7d5c3ac2009-02-04 08:58:19831 std::wstring flags;
832 int64 sent; // Time that the message was sent (i.e. at Send()).
833 int64 receive; // Time before it was dispatched (i.e. before calling
834 // OnMessageReceived).
835 int64 dispatch; // Time after it was dispatched (i.e. after calling
836 // OnMessageReceived).
[email protected]e707d5e62009-02-12 04:00:08837 std::wstring message_name;
[email protected]7d5c3ac2009-02-04 08:58:19838 std::wstring params;
839};
840
841template <>
842struct ParamTraits<LogData> {
843 typedef LogData param_type;
844 static void Write(Message* m, const param_type& p) {
845 WriteParam(m, p.channel);
[email protected]8bef70e2009-04-14 19:11:24846 WriteParam(m, p.routing_id);
[email protected]7d5c3ac2009-02-04 08:58:19847 WriteParam(m, static_cast<int>(p.type));
848 WriteParam(m, p.flags);
849 WriteParam(m, p.sent);
850 WriteParam(m, p.receive);
851 WriteParam(m, p.dispatch);
852 WriteParam(m, p.params);
853 }
854 static bool Read(const Message* m, void** iter, param_type* r) {
855 int type;
856 bool result =
857 ReadParam(m, iter, &r->channel) &&
[email protected]25af92052010-03-26 22:21:17858 ReadParam(m, iter, &r->routing_id) &&
[email protected]7d5c3ac2009-02-04 08:58:19859 ReadParam(m, iter, &type) &&
860 ReadParam(m, iter, &r->flags) &&
861 ReadParam(m, iter, &r->sent) &&
862 ReadParam(m, iter, &r->receive) &&
863 ReadParam(m, iter, &r->dispatch) &&
864 ReadParam(m, iter, &r->params);
865 r->type = static_cast<uint16>(type);
866 return result;
867 }
868 static void Log(const param_type& p, std::wstring* l) {
869 // Doesn't make sense to implement this!
870 }
871};
872
[email protected]eb47a132009-03-04 00:39:56873template <>
[email protected]503683f2009-02-26 09:13:01874struct ParamTraits<Message> {
875 static void Write(Message* m, const Message& p) {
876 m->WriteInt(p.size());
877 m->WriteData(reinterpret_cast<const char*>(p.data()), p.size());
878 }
879 static bool Read(const Message* m, void** iter, Message* r) {
880 int size;
881 if (!m->ReadInt(iter, &size))
882 return false;
883 const char* data;
884 if (!m->ReadData(iter, &data, &size))
885 return false;
886 *r = Message(data, size);
887 return true;
888 }
889 static void Log(const Message& p, std::wstring* l) {
890 l->append(L"<IPC::Message>");
891 }
892};
893
894template <>
[email protected]7d5c3ac2009-02-04 08:58:19895struct ParamTraits<Tuple0> {
896 typedef Tuple0 param_type;
897 static void Write(Message* m, const param_type& p) {
898 }
899 static bool Read(const Message* m, void** iter, param_type* r) {
900 return true;
901 }
902 static void Log(const param_type& p, std::wstring* l) {
903 }
904};
905
906template <class A>
907struct ParamTraits< Tuple1<A> > {
908 typedef Tuple1<A> param_type;
909 static void Write(Message* m, const param_type& p) {
910 WriteParam(m, p.a);
911 }
912 static bool Read(const Message* m, void** iter, param_type* r) {
913 return ReadParam(m, iter, &r->a);
914 }
915 static void Log(const param_type& p, std::wstring* l) {
916 LogParam(p.a, l);
917 }
918};
919
920template <class A, class B>
921struct ParamTraits< Tuple2<A, B> > {
922 typedef Tuple2<A, B> param_type;
923 static void Write(Message* m, const param_type& p) {
924 WriteParam(m, p.a);
925 WriteParam(m, p.b);
926 }
927 static bool Read(const Message* m, void** iter, param_type* r) {
928 return (ReadParam(m, iter, &r->a) &&
929 ReadParam(m, iter, &r->b));
930 }
931 static void Log(const param_type& p, std::wstring* l) {
932 LogParam(p.a, l);
933 l->append(L", ");
934 LogParam(p.b, l);
935 }
936};
937
938template <class A, class B, class C>
939struct ParamTraits< Tuple3<A, B, C> > {
940 typedef Tuple3<A, B, C> param_type;
941 static void Write(Message* m, const param_type& p) {
942 WriteParam(m, p.a);
943 WriteParam(m, p.b);
944 WriteParam(m, p.c);
945 }
946 static bool Read(const Message* m, void** iter, param_type* r) {
947 return (ReadParam(m, iter, &r->a) &&
948 ReadParam(m, iter, &r->b) &&
949 ReadParam(m, iter, &r->c));
950 }
951 static void Log(const param_type& p, std::wstring* l) {
952 LogParam(p.a, l);
953 l->append(L", ");
954 LogParam(p.b, l);
955 l->append(L", ");
956 LogParam(p.c, l);
957 }
958};
959
960template <class A, class B, class C, class D>
961struct ParamTraits< Tuple4<A, B, C, D> > {
962 typedef Tuple4<A, B, C, D> param_type;
963 static void Write(Message* m, const param_type& p) {
964 WriteParam(m, p.a);
965 WriteParam(m, p.b);
966 WriteParam(m, p.c);
967 WriteParam(m, p.d);
968 }
969 static bool Read(const Message* m, void** iter, param_type* r) {
970 return (ReadParam(m, iter, &r->a) &&
971 ReadParam(m, iter, &r->b) &&
972 ReadParam(m, iter, &r->c) &&
973 ReadParam(m, iter, &r->d));
974 }
975 static void Log(const param_type& p, std::wstring* l) {
976 LogParam(p.a, l);
977 l->append(L", ");
978 LogParam(p.b, l);
979 l->append(L", ");
980 LogParam(p.c, l);
981 l->append(L", ");
982 LogParam(p.d, l);
983 }
984};
985
986template <class A, class B, class C, class D, class E>
987struct ParamTraits< Tuple5<A, B, C, D, E> > {
988 typedef Tuple5<A, B, C, D, E> param_type;
989 static void Write(Message* m, const param_type& p) {
990 WriteParam(m, p.a);
991 WriteParam(m, p.b);
992 WriteParam(m, p.c);
993 WriteParam(m, p.d);
994 WriteParam(m, p.e);
995 }
996 static bool Read(const Message* m, void** iter, param_type* r) {
997 return (ReadParam(m, iter, &r->a) &&
998 ReadParam(m, iter, &r->b) &&
999 ReadParam(m, iter, &r->c) &&
1000 ReadParam(m, iter, &r->d) &&
1001 ReadParam(m, iter, &r->e));
1002 }
1003 static void Log(const param_type& p, std::wstring* l) {
1004 LogParam(p.a, l);
1005 l->append(L", ");
1006 LogParam(p.b, l);
1007 l->append(L", ");
1008 LogParam(p.c, l);
1009 l->append(L", ");
1010 LogParam(p.d, l);
1011 l->append(L", ");
1012 LogParam(p.e, l);
1013 }
1014};
1015
[email protected]7d5c3ac2009-02-04 08:58:191016//-----------------------------------------------------------------------------
initial.commit09911bf2008-07-26 23:55:291017// Generic message subclasses
1018
1019// Used for asynchronous messages.
[email protected]81a34412009-01-05 19:17:241020template <class ParamType>
initial.commit09911bf2008-07-26 23:55:291021class MessageWithTuple : public Message {
1022 public:
[email protected]81a34412009-01-05 19:17:241023 typedef ParamType Param;
[email protected]c2fe31542009-05-20 18:24:141024 typedef typename ParamType::ParamTuple RefParam;
[email protected]81a34412009-01-05 19:17:241025
[email protected]168ae922009-12-04 18:08:451026 MessageWithTuple(int32 routing_id, uint32 type, const RefParam& p)
initial.commit09911bf2008-07-26 23:55:291027 : Message(routing_id, type, PRIORITY_NORMAL) {
1028 WriteParam(this, p);
1029 }
1030
[email protected]7d5c3ac2009-02-04 08:58:191031 static bool Read(const Message* msg, Param* p) {
initial.commit09911bf2008-07-26 23:55:291032 void* iter = NULL;
[email protected]3b8463962009-07-16 06:27:381033 if (ReadParam(msg, &iter, p))
1034 return true;
1035 NOTREACHED() << "Error deserializing message " << msg->type();
1036 return false;
initial.commit09911bf2008-07-26 23:55:291037 }
1038
1039 // Generic dispatcher. Should cover most cases.
1040 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191041 static bool Dispatch(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291042 Param p;
1043 if (Read(msg, &p)) {
1044 DispatchToMethod(obj, func, p);
1045 return true;
1046 }
1047 return false;
1048 }
1049
1050 // The following dispatchers exist for the case where the callback function
1051 // needs the message as well. They assume that "Param" is a type of Tuple
1052 // (except the one arg case, as there is no Tuple1).
1053 template<class T, typename TA>
[email protected]7d5c3ac2009-02-04 08:58:191054 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291055 void (T::*func)(const Message&, TA)) {
1056 Param p;
1057 if (Read(msg, &p)) {
[email protected]c2fe31542009-05-20 18:24:141058 (obj->*func)(*msg, p.a);
initial.commit09911bf2008-07-26 23:55:291059 return true;
1060 }
1061 return false;
1062 }
1063
1064 template<class T, typename TA, typename TB>
[email protected]7d5c3ac2009-02-04 08:58:191065 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291066 void (T::*func)(const Message&, TA, TB)) {
1067 Param p;
1068 if (Read(msg, &p)) {
1069 (obj->*func)(*msg, p.a, p.b);
1070 return true;
1071 }
1072 return false;
1073 }
1074
1075 template<class T, typename TA, typename TB, typename TC>
[email protected]7d5c3ac2009-02-04 08:58:191076 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291077 void (T::*func)(const Message&, TA, TB, TC)) {
1078 Param p;
1079 if (Read(msg, &p)) {
1080 (obj->*func)(*msg, p.a, p.b, p.c);
1081 return true;
1082 }
1083 return false;
1084 }
1085
1086 template<class T, typename TA, typename TB, typename TC, typename TD>
[email protected]7d5c3ac2009-02-04 08:58:191087 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291088 void (T::*func)(const Message&, TA, TB, TC, TD)) {
1089 Param p;
1090 if (Read(msg, &p)) {
1091 (obj->*func)(*msg, p.a, p.b, p.c, p.d);
1092 return true;
1093 }
1094 return false;
1095 }
1096
1097 template<class T, typename TA, typename TB, typename TC, typename TD,
1098 typename TE>
[email protected]7d5c3ac2009-02-04 08:58:191099 static bool Dispatch(const Message* msg, T* obj,
initial.commit09911bf2008-07-26 23:55:291100 void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
1101 Param p;
1102 if (Read(msg, &p)) {
1103 (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
1104 return true;
1105 }
1106 return false;
1107 }
1108
[email protected]7d5c3ac2009-02-04 08:58:191109 static void Log(const Message* msg, std::wstring* l) {
initial.commit09911bf2008-07-26 23:55:291110 Param p;
1111 if (Read(msg, &p))
1112 LogParam(p, l);
1113 }
[email protected]deb57402009-02-06 01:35:301114
1115 // Functions used to do manual unpacking. Only used by the automation code,
1116 // these should go away once that code uses SyncChannel.
1117 template<typename TA, typename TB>
1118 static bool Read(const IPC::Message* msg, TA* a, TB* b) {
1119 ParamType params;
1120 if (!Read(msg, &params))
1121 return false;
1122 *a = params.a;
1123 *b = params.b;
1124 return true;
1125 }
1126
1127 template<typename TA, typename TB, typename TC>
1128 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
1129 ParamType params;
1130 if (!Read(msg, &params))
1131 return false;
1132 *a = params.a;
1133 *b = params.b;
1134 *c = params.c;
1135 return true;
1136 }
1137
1138 template<typename TA, typename TB, typename TC, typename TD>
1139 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
1140 ParamType params;
1141 if (!Read(msg, &params))
1142 return false;
1143 *a = params.a;
1144 *b = params.b;
1145 *c = params.c;
1146 *d = params.d;
1147 return true;
1148 }
1149
1150 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1151 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
1152 ParamType params;
1153 if (!Read(msg, &params))
1154 return false;
1155 *a = params.a;
1156 *b = params.b;
1157 *c = params.c;
1158 *d = params.d;
1159 *e = params.e;
1160 return true;
1161 }
initial.commit09911bf2008-07-26 23:55:291162};
1163
1164// This class assumes that its template argument is a RefTuple (a Tuple with
1165// reference elements).
1166template <class RefTuple>
1167class ParamDeserializer : public MessageReplyDeserializer {
1168 public:
[email protected]e1981f432008-08-12 15:22:131169 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
initial.commit09911bf2008-07-26 23:55:291170
1171 bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
1172 return ReadParam(&msg, &iter, &out_);
1173 }
1174
1175 RefTuple out_;
1176};
1177
1178// defined in ipc_logging.cc
[email protected]9a3a293b2009-06-04 22:28:161179void GenerateLogData(const std::string& channel, const Message& message,
initial.commit09911bf2008-07-26 23:55:291180 LogData* data);
1181
1182// Used for synchronous messages.
[email protected]75e5a872009-04-02 23:56:111183template <class SendParamType, class ReplyParamType>
initial.commit09911bf2008-07-26 23:55:291184class MessageWithReply : public SyncMessage {
1185 public:
[email protected]75e5a872009-04-02 23:56:111186 typedef SendParamType SendParam;
[email protected]c2fe31542009-05-20 18:24:141187 typedef typename SendParam::ParamTuple RefSendParam;
[email protected]75e5a872009-04-02 23:56:111188 typedef ReplyParamType ReplyParam;
1189
[email protected]168ae922009-12-04 18:08:451190 MessageWithReply(int32 routing_id, uint32 type,
[email protected]c2fe31542009-05-20 18:24:141191 const RefSendParam& send, const ReplyParam& reply)
initial.commit09911bf2008-07-26 23:55:291192 : SyncMessage(routing_id, type, PRIORITY_NORMAL,
1193 new ParamDeserializer<ReplyParam>(reply)) {
1194 WriteParam(this, send);
1195 }
1196
[email protected]7d5c3ac2009-02-04 08:58:191197 static void Log(const Message* msg, std::wstring* l) {
initial.commit09911bf2008-07-26 23:55:291198 if (msg->is_sync()) {
1199 SendParam p;
1200 void* iter = SyncMessage::GetDataIterator(msg);
[email protected]1e86aa62009-04-24 21:22:331201 if (ReadParam(msg, &iter, &p))
1202 LogParam(p, l);
initial.commit09911bf2008-07-26 23:55:291203
[email protected]1156f7b2008-12-04 19:13:591204#if defined(IPC_MESSAGE_LOG_ENABLED)
initial.commit09911bf2008-07-26 23:55:291205 const std::wstring& output_params = msg->output_params();
1206 if (!l->empty() && !output_params.empty())
1207 l->append(L", ");
1208
1209 l->append(output_params);
[email protected]2a34f9c2008-12-04 19:12:041210#endif
initial.commit09911bf2008-07-26 23:55:291211 } else {
1212 // This is an outgoing reply. Now that we have the output parameters, we
1213 // can finally log the message.
[email protected]d4651ff2008-12-02 16:51:581214 typename ReplyParam::ValueTuple p;
initial.commit09911bf2008-07-26 23:55:291215 void* iter = SyncMessage::GetDataIterator(msg);
[email protected]1e86aa62009-04-24 21:22:331216 if (ReadParam(msg, &iter, &p))
1217 LogParam(p, l);
initial.commit09911bf2008-07-26 23:55:291218 }
1219 }
1220
1221 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191222 static bool Dispatch(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291223 SendParam send_params;
1224 void* iter = GetDataIterator(msg);
1225 Message* reply = GenerateReply(msg);
1226 bool error;
1227 if (ReadParam(msg, &iter, &send_params)) {
[email protected]d4651ff2008-12-02 16:51:581228 typename ReplyParam::ValueTuple reply_params;
initial.commit09911bf2008-07-26 23:55:291229 DispatchToMethod(obj, func, send_params, &reply_params);
1230 WriteParam(reply, reply_params);
1231 error = false;
1232#ifdef IPC_MESSAGE_LOG_ENABLED
1233 if (msg->received_time() != 0) {
1234 std::wstring output_params;
1235 LogParam(reply_params, &output_params);
1236 msg->set_output_params(output_params);
1237 }
1238#endif
1239 } else {
1240 NOTREACHED() << "Error deserializing message " << msg->type();
1241 reply->set_reply_error();
1242 error = true;
1243 }
1244
1245 obj->Send(reply);
1246 return !error;
1247 }
1248
1249 template<class T, class Method>
[email protected]7d5c3ac2009-02-04 08:58:191250 static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
initial.commit09911bf2008-07-26 23:55:291251 SendParam send_params;
1252 void* iter = GetDataIterator(msg);
1253 Message* reply = GenerateReply(msg);
1254 bool error;
1255 if (ReadParam(msg, &iter, &send_params)) {
1256 Tuple1<Message&> t = MakeRefTuple(*reply);
1257
1258#ifdef IPC_MESSAGE_LOG_ENABLED
1259 if (msg->sent_time()) {
1260 // Don't log the sync message after dispatch, as we don't have the
1261 // output parameters at that point. Instead, save its data and log it
1262 // with the outgoing reply message when it's sent.
1263 LogData* data = new LogData;
[email protected]9a3a293b2009-06-04 22:28:161264 GenerateLogData("", *msg, data);
initial.commit09911bf2008-07-26 23:55:291265 msg->set_dont_log();
1266 reply->set_sync_log_data(data);
1267 }
1268#endif
1269 DispatchToMethod(obj, func, send_params, &t);
1270 error = false;
1271 } else {
1272 NOTREACHED() << "Error deserializing message " << msg->type();
1273 reply->set_reply_error();
1274 obj->Send(reply);
1275 error = true;
1276 }
1277 return !error;
1278 }
1279
1280 template<typename TA>
1281 static void WriteReplyParams(Message* reply, TA a) {
1282 ReplyParam p(a);
1283 WriteParam(reply, p);
1284 }
1285
1286 template<typename TA, typename TB>
1287 static void WriteReplyParams(Message* reply, TA a, TB b) {
1288 ReplyParam p(a, b);
1289 WriteParam(reply, p);
1290 }
1291
1292 template<typename TA, typename TB, typename TC>
1293 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
1294 ReplyParam p(a, b, c);
1295 WriteParam(reply, p);
1296 }
1297
1298 template<typename TA, typename TB, typename TC, typename TD>
1299 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
1300 ReplyParam p(a, b, c, d);
1301 WriteParam(reply, p);
1302 }
1303
1304 template<typename TA, typename TB, typename TC, typename TD, typename TE>
1305 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
1306 ReplyParam p(a, b, c, d, e);
1307 WriteParam(reply, p);
1308 }
1309};
1310
[email protected]7d5c3ac2009-02-04 08:58:191311//-----------------------------------------------------------------------------
1312
[email protected]3178f4e22008-08-05 21:20:411313} // namespace IPC
initial.commit09911bf2008-07-26 23:55:291314
[email protected]946d1b22009-07-22 23:57:211315#endif // IPC_IPC_MESSAGE_UTILS_H_