ipc/chromium/src/chrome/common/ipc_message_utils.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #ifndef CHROME_COMMON_IPC_MESSAGE_UTILS_H_
michael@0 6 #define CHROME_COMMON_IPC_MESSAGE_UTILS_H_
michael@0 7
michael@0 8 #include <string>
michael@0 9 #include <vector>
michael@0 10 #include <map>
michael@0 11
michael@0 12 #include "base/file_path.h"
michael@0 13 #include "base/string_util.h"
michael@0 14 #include "base/string16.h"
michael@0 15 #include "base/tuple.h"
michael@0 16 #include "base/time.h"
michael@0 17
michael@0 18 #if defined(OS_POSIX)
michael@0 19 #include "chrome/common/file_descriptor_set_posix.h"
michael@0 20 #endif
michael@0 21 #include "chrome/common/ipc_sync_message.h"
michael@0 22 #include "chrome/common/transport_dib.h"
michael@0 23
michael@0 24 namespace IPC {
michael@0 25
michael@0 26 //-----------------------------------------------------------------------------
michael@0 27 // An iterator class for reading the fields contained within a Message.
michael@0 28
michael@0 29 class MessageIterator {
michael@0 30 public:
michael@0 31 explicit MessageIterator(const Message& m) : msg_(m), iter_(NULL) {
michael@0 32 }
michael@0 33 int NextInt() const {
michael@0 34 int val;
michael@0 35 if (!msg_.ReadInt(&iter_, &val))
michael@0 36 NOTREACHED();
michael@0 37 return val;
michael@0 38 }
michael@0 39 intptr_t NextIntPtr() const {
michael@0 40 intptr_t val;
michael@0 41 if (!msg_.ReadIntPtr(&iter_, &val))
michael@0 42 NOTREACHED();
michael@0 43 return val;
michael@0 44 }
michael@0 45 const std::string NextString() const {
michael@0 46 std::string val;
michael@0 47 if (!msg_.ReadString(&iter_, &val))
michael@0 48 NOTREACHED();
michael@0 49 return val;
michael@0 50 }
michael@0 51 const std::wstring NextWString() const {
michael@0 52 std::wstring val;
michael@0 53 if (!msg_.ReadWString(&iter_, &val))
michael@0 54 NOTREACHED();
michael@0 55 return val;
michael@0 56 }
michael@0 57 const void NextData(const char** data, int* length) const {
michael@0 58 if (!msg_.ReadData(&iter_, data, length)) {
michael@0 59 NOTREACHED();
michael@0 60 }
michael@0 61 }
michael@0 62 private:
michael@0 63 const Message& msg_;
michael@0 64 mutable void* iter_;
michael@0 65 };
michael@0 66
michael@0 67 //-----------------------------------------------------------------------------
michael@0 68 // ParamTraits specializations, etc.
michael@0 69 //
michael@0 70 // The full set of types ParamTraits is specialized upon contains *possibly*
michael@0 71 // repeated types: unsigned long may be uint32_t or size_t, unsigned long long
michael@0 72 // may be uint64_t or size_t, nsresult may be uint32_t, and so on. You can't
michael@0 73 // have ParamTraits<unsigned int> *and* ParamTraits<uint32_t> if unsigned int
michael@0 74 // is uint32_t -- that's multiple definitions, and you can only have one.
michael@0 75 //
michael@0 76 // You could use #ifs and macro conditions to avoid duplicates, but they'd be
michael@0 77 // hairy: heavily dependent upon OS and compiler author choices, forced to
michael@0 78 // address all conflicts by hand. Happily there's a better way. The basic
michael@0 79 // idea looks like this, where T -> U represents T inheriting from U:
michael@0 80 //
michael@0 81 // class ParamTraits<P>
michael@0 82 // |
michael@0 83 // --> class ParamTraits1<P>
michael@0 84 // |
michael@0 85 // --> class ParamTraits2<P>
michael@0 86 // |
michael@0 87 // --> class ParamTraitsN<P> // or however many levels
michael@0 88 //
michael@0 89 // The default specialization of ParamTraits{M}<P> is an empty class that
michael@0 90 // inherits from ParamTraits{M + 1}<P> (or nothing in the base case).
michael@0 91 //
michael@0 92 // Now partition the set of parameter types into sets without duplicates.
michael@0 93 // Assign each set of types to a level M. Then specialize ParamTraitsM for
michael@0 94 // each of those types. A reference to ParamTraits<P> will consist of some
michael@0 95 // number of empty classes inheriting in sequence, ending in a non-empty
michael@0 96 // ParamTraits{N}<P>. It's okay for the parameter types to be duplicative:
michael@0 97 // either name of a type will resolve to the same ParamTraits{N}<P>.
michael@0 98 //
michael@0 99 // The nice thing is that because templates are instantiated lazily, if we
michael@0 100 // indeed have uint32_t == unsigned int, say, with the former in level N and
michael@0 101 // the latter in M > N, ParamTraitsM<unsigned int> won't be created (as long as
michael@0 102 // nobody uses ParamTraitsM<unsigned int>, but why would you), and no duplicate
michael@0 103 // code will be compiled or extra symbols generated. It's as efficient at
michael@0 104 // runtime as manually figuring out and avoiding conflicts by #ifs.
michael@0 105 //
michael@0 106 // The scheme we follow below names the various classes according to the types
michael@0 107 // in them, and the number of ParamTraits levels is larger, but otherwise it's
michael@0 108 // exactly the above idea.
michael@0 109 //
michael@0 110
michael@0 111 template <class P> struct ParamTraits;
michael@0 112
michael@0 113 template <class P>
michael@0 114 static inline void WriteParam(Message* m, const P& p) {
michael@0 115 ParamTraits<P>::Write(m, p);
michael@0 116 }
michael@0 117
michael@0 118 template <class P>
michael@0 119 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, void** iter,
michael@0 120 P* p) {
michael@0 121 return ParamTraits<P>::Read(m, iter, p);
michael@0 122 }
michael@0 123
michael@0 124 template <class P>
michael@0 125 static inline void LogParam(const P& p, std::wstring* l) {
michael@0 126 ParamTraits<P>::Log(p, l);
michael@0 127 }
michael@0 128
michael@0 129 // Fundamental types.
michael@0 130
michael@0 131 template <class P>
michael@0 132 struct ParamTraitsFundamental {};
michael@0 133
michael@0 134 template <>
michael@0 135 struct ParamTraitsFundamental<bool> {
michael@0 136 typedef bool param_type;
michael@0 137 static void Write(Message* m, const param_type& p) {
michael@0 138 m->WriteBool(p);
michael@0 139 }
michael@0 140 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 141 return m->ReadBool(iter, r);
michael@0 142 }
michael@0 143 static void Log(const param_type& p, std::wstring* l) {
michael@0 144 l->append(p ? L"true" : L"false");
michael@0 145 }
michael@0 146 };
michael@0 147
michael@0 148 template <>
michael@0 149 struct ParamTraitsFundamental<int> {
michael@0 150 typedef int param_type;
michael@0 151 static void Write(Message* m, const param_type& p) {
michael@0 152 m->WriteInt(p);
michael@0 153 }
michael@0 154 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 155 return m->ReadInt(iter, r);
michael@0 156 }
michael@0 157 static void Log(const param_type& p, std::wstring* l) {
michael@0 158 l->append(StringPrintf(L"%d", p));
michael@0 159 }
michael@0 160 };
michael@0 161
michael@0 162 template <>
michael@0 163 struct ParamTraitsFundamental<long> {
michael@0 164 typedef long param_type;
michael@0 165 static void Write(Message* m, const param_type& p) {
michael@0 166 m->WriteLong(p);
michael@0 167 }
michael@0 168 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 169 return m->ReadLong(iter, r);
michael@0 170 }
michael@0 171 static void Log(const param_type& p, std::wstring* l) {
michael@0 172 l->append(StringPrintf(L"%l", p));
michael@0 173 }
michael@0 174 };
michael@0 175
michael@0 176 template <>
michael@0 177 struct ParamTraitsFundamental<unsigned long> {
michael@0 178 typedef unsigned long param_type;
michael@0 179 static void Write(Message* m, const param_type& p) {
michael@0 180 m->WriteULong(p);
michael@0 181 }
michael@0 182 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 183 return m->ReadULong(iter, r);
michael@0 184 }
michael@0 185 static void Log(const param_type& p, std::wstring* l) {
michael@0 186 l->append(StringPrintf(L"%ul", p));
michael@0 187 }
michael@0 188 };
michael@0 189
michael@0 190 template <>
michael@0 191 struct ParamTraitsFundamental<long long> {
michael@0 192 typedef long long param_type;
michael@0 193 static void Write(Message* m, const param_type& p) {
michael@0 194 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
michael@0 195 }
michael@0 196 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 197 const char *data;
michael@0 198 int data_size = 0;
michael@0 199 bool result = m->ReadData(iter, &data, &data_size);
michael@0 200 if (result && data_size == sizeof(param_type)) {
michael@0 201 memcpy(r, data, sizeof(param_type));
michael@0 202 } else {
michael@0 203 result = false;
michael@0 204 NOTREACHED();
michael@0 205 }
michael@0 206 return result;
michael@0 207 }
michael@0 208 static void Log(const param_type& p, std::wstring* l) {
michael@0 209 l->append(StringPrintf(L"%ll", p));
michael@0 210 }
michael@0 211 };
michael@0 212
michael@0 213 template <>
michael@0 214 struct ParamTraitsFundamental<unsigned long long> {
michael@0 215 typedef unsigned long long param_type;
michael@0 216 static void Write(Message* m, const param_type& p) {
michael@0 217 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
michael@0 218 }
michael@0 219 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 220 const char *data;
michael@0 221 int data_size = 0;
michael@0 222 bool result = m->ReadData(iter, &data, &data_size);
michael@0 223 if (result && data_size == sizeof(param_type)) {
michael@0 224 memcpy(r, data, sizeof(param_type));
michael@0 225 } else {
michael@0 226 result = false;
michael@0 227 NOTREACHED();
michael@0 228 }
michael@0 229 return result;
michael@0 230 }
michael@0 231 static void Log(const param_type& p, std::wstring* l) {
michael@0 232 l->append(StringPrintf(L"%ull", p));
michael@0 233 }
michael@0 234 };
michael@0 235
michael@0 236 template <>
michael@0 237 struct ParamTraitsFundamental<double> {
michael@0 238 typedef double param_type;
michael@0 239 static void Write(Message* m, const param_type& p) {
michael@0 240 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(param_type));
michael@0 241 }
michael@0 242 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 243 const char *data;
michael@0 244 int data_size = 0;
michael@0 245 bool result = m->ReadData(iter, &data, &data_size);
michael@0 246 if (result && data_size == sizeof(param_type)) {
michael@0 247 memcpy(r, data, sizeof(param_type));
michael@0 248 } else {
michael@0 249 result = false;
michael@0 250 NOTREACHED();
michael@0 251 }
michael@0 252
michael@0 253 return result;
michael@0 254 }
michael@0 255 static void Log(const param_type& p, std::wstring* l) {
michael@0 256 l->append(StringPrintf(L"e", p));
michael@0 257 }
michael@0 258 };
michael@0 259
michael@0 260 // Fixed-size <stdint.h> types.
michael@0 261
michael@0 262 template <class P>
michael@0 263 struct ParamTraitsFixed : ParamTraitsFundamental<P> {};
michael@0 264
michael@0 265 template <>
michael@0 266 struct ParamTraitsFixed<int16_t> {
michael@0 267 typedef int16_t param_type;
michael@0 268 static void Write(Message* m, const param_type& p) {
michael@0 269 m->WriteInt16(p);
michael@0 270 }
michael@0 271 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 272 return m->ReadInt16(iter, r);
michael@0 273 }
michael@0 274 static void Log(const param_type& p, std::wstring* l) {
michael@0 275 l->append(StringPrintf(L"%hd", p));
michael@0 276 }
michael@0 277 };
michael@0 278
michael@0 279 template <>
michael@0 280 struct ParamTraitsFixed<uint16_t> {
michael@0 281 typedef uint16_t param_type;
michael@0 282 static void Write(Message* m, const param_type& p) {
michael@0 283 m->WriteUInt16(p);
michael@0 284 }
michael@0 285 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 286 return m->ReadUInt16(iter, r);
michael@0 287 }
michael@0 288 static void Log(const param_type& p, std::wstring* l) {
michael@0 289 l->append(StringPrintf(L"%hu", p));
michael@0 290 }
michael@0 291 };
michael@0 292
michael@0 293 template <>
michael@0 294 struct ParamTraitsFixed<uint32_t> {
michael@0 295 typedef uint32_t param_type;
michael@0 296 static void Write(Message* m, const param_type& p) {
michael@0 297 m->WriteUInt32(p);
michael@0 298 }
michael@0 299 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 300 return m->ReadUInt32(iter, r);
michael@0 301 }
michael@0 302 static void Log(const param_type& p, std::wstring* l) {
michael@0 303 l->append(StringPrintf(L"%u", p));
michael@0 304 }
michael@0 305 };
michael@0 306
michael@0 307 template <>
michael@0 308 struct ParamTraitsFixed<int64_t> {
michael@0 309 typedef int64_t param_type;
michael@0 310 static void Write(Message* m, const param_type& p) {
michael@0 311 m->WriteInt64(p);
michael@0 312 }
michael@0 313 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 314 return m->ReadInt64(iter, r);
michael@0 315 }
michael@0 316 static void Log(const param_type& p, std::wstring* l) {
michael@0 317 l->append(StringPrintf(L"%" PRId64L, p));
michael@0 318 }
michael@0 319 };
michael@0 320
michael@0 321 template <>
michael@0 322 struct ParamTraitsFixed<uint64_t> {
michael@0 323 typedef uint64_t param_type;
michael@0 324 static void Write(Message* m, const param_type& p) {
michael@0 325 m->WriteInt64(static_cast<int64_t>(p));
michael@0 326 }
michael@0 327 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 328 return m->ReadInt64(iter, reinterpret_cast<int64_t*>(r));
michael@0 329 }
michael@0 330 static void Log(const param_type& p, std::wstring* l) {
michael@0 331 l->append(StringPrintf(L"%" PRIu64L, p));
michael@0 332 }
michael@0 333 };
michael@0 334
michael@0 335 // Other standard C types.
michael@0 336
michael@0 337 template <class P>
michael@0 338 struct ParamTraitsLibC : ParamTraitsFixed<P> {};
michael@0 339
michael@0 340 template <>
michael@0 341 struct ParamTraitsLibC<size_t> {
michael@0 342 typedef size_t param_type;
michael@0 343 static void Write(Message* m, const param_type& p) {
michael@0 344 m->WriteSize(p);
michael@0 345 }
michael@0 346 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 347 return m->ReadSize(iter, r);
michael@0 348 }
michael@0 349 static void Log(const param_type& p, std::wstring* l) {
michael@0 350 l->append(StringPrintf(L"%u", p));
michael@0 351 }
michael@0 352 };
michael@0 353
michael@0 354 // std::* types.
michael@0 355
michael@0 356 template <class P>
michael@0 357 struct ParamTraitsStd : ParamTraitsLibC<P> {};
michael@0 358
michael@0 359 template <>
michael@0 360 struct ParamTraitsStd<std::string> {
michael@0 361 typedef std::string param_type;
michael@0 362 static void Write(Message* m, const param_type& p) {
michael@0 363 m->WriteString(p);
michael@0 364 }
michael@0 365 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 366 return m->ReadString(iter, r);
michael@0 367 }
michael@0 368 static void Log(const param_type& p, std::wstring* l) {
michael@0 369 l->append(UTF8ToWide(p));
michael@0 370 }
michael@0 371 };
michael@0 372
michael@0 373 template <>
michael@0 374 struct ParamTraitsStd<std::wstring> {
michael@0 375 typedef std::wstring param_type;
michael@0 376 static void Write(Message* m, const param_type& p) {
michael@0 377 m->WriteWString(p);
michael@0 378 }
michael@0 379 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 380 return m->ReadWString(iter, r);
michael@0 381 }
michael@0 382 static void Log(const param_type& p, std::wstring* l) {
michael@0 383 l->append(p);
michael@0 384 }
michael@0 385 };
michael@0 386
michael@0 387 template <>
michael@0 388 struct ParamTraitsStd<std::vector<unsigned char> > {
michael@0 389 typedef std::vector<unsigned char> param_type;
michael@0 390 static void Write(Message* m, const param_type& p) {
michael@0 391 if (p.size() == 0) {
michael@0 392 m->WriteData(NULL, 0);
michael@0 393 } else {
michael@0 394 m->WriteData(reinterpret_cast<const char*>(&p.front()),
michael@0 395 static_cast<int>(p.size()));
michael@0 396 }
michael@0 397 }
michael@0 398 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 399 const char *data;
michael@0 400 int data_size = 0;
michael@0 401 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
michael@0 402 return false;
michael@0 403 r->resize(data_size);
michael@0 404 if (data_size)
michael@0 405 memcpy(&r->front(), data, data_size);
michael@0 406 return true;
michael@0 407 }
michael@0 408 static void Log(const param_type& p, std::wstring* l) {
michael@0 409 for (size_t i = 0; i < p.size(); ++i)
michael@0 410 l->push_back(p[i]);
michael@0 411 }
michael@0 412 };
michael@0 413
michael@0 414 template <>
michael@0 415 struct ParamTraitsStd<std::vector<char> > {
michael@0 416 typedef std::vector<char> param_type;
michael@0 417 static void Write(Message* m, const param_type& p) {
michael@0 418 if (p.size() == 0) {
michael@0 419 m->WriteData(NULL, 0);
michael@0 420 } else {
michael@0 421 m->WriteData(&p.front(), static_cast<int>(p.size()));
michael@0 422 }
michael@0 423 }
michael@0 424 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 425 const char *data;
michael@0 426 int data_size = 0;
michael@0 427 if (!m->ReadData(iter, &data, &data_size) || data_size < 0)
michael@0 428 return false;
michael@0 429 r->resize(data_size);
michael@0 430 if (data_size)
michael@0 431 memcpy(&r->front(), data, data_size);
michael@0 432 return true;
michael@0 433 }
michael@0 434 static void Log(const param_type& p, std::wstring* l) {
michael@0 435 for (size_t i = 0; i < p.size(); ++i)
michael@0 436 l->push_back(p[i]);
michael@0 437 }
michael@0 438 };
michael@0 439
michael@0 440 template <class P>
michael@0 441 struct ParamTraitsStd<std::vector<P> > {
michael@0 442 typedef std::vector<P> param_type;
michael@0 443 static void Write(Message* m, const param_type& p) {
michael@0 444 WriteParam(m, static_cast<int>(p.size()));
michael@0 445 for (size_t i = 0; i < p.size(); i++)
michael@0 446 WriteParam(m, p[i]);
michael@0 447 }
michael@0 448 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 449 int size;
michael@0 450 if (!m->ReadLength(iter, &size))
michael@0 451 return false;
michael@0 452 // Resizing beforehand is not safe, see BUG 1006367 for details.
michael@0 453 if (m->IteratorHasRoomFor(*iter, size * sizeof(P))) {
michael@0 454 r->resize(size);
michael@0 455 for (int i = 0; i < size; i++) {
michael@0 456 if (!ReadParam(m, iter, &(*r)[i]))
michael@0 457 return false;
michael@0 458 }
michael@0 459 } else {
michael@0 460 for (int i = 0; i < size; i++) {
michael@0 461 P element;
michael@0 462 if (!ReadParam(m, iter, &element))
michael@0 463 return false;
michael@0 464 r->push_back(element);
michael@0 465 }
michael@0 466 }
michael@0 467 return true;
michael@0 468 }
michael@0 469 static void Log(const param_type& p, std::wstring* l) {
michael@0 470 for (size_t i = 0; i < p.size(); ++i) {
michael@0 471 if (i != 0)
michael@0 472 l->append(L" ");
michael@0 473
michael@0 474 LogParam((p[i]), l);
michael@0 475 }
michael@0 476 }
michael@0 477 };
michael@0 478
michael@0 479 template <class K, class V>
michael@0 480 struct ParamTraitsStd<std::map<K, V> > {
michael@0 481 typedef std::map<K, V> param_type;
michael@0 482 static void Write(Message* m, const param_type& p) {
michael@0 483 WriteParam(m, static_cast<int>(p.size()));
michael@0 484 typename param_type::const_iterator iter;
michael@0 485 for (iter = p.begin(); iter != p.end(); ++iter) {
michael@0 486 WriteParam(m, iter->first);
michael@0 487 WriteParam(m, iter->second);
michael@0 488 }
michael@0 489 }
michael@0 490 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 491 int size;
michael@0 492 if (!ReadParam(m, iter, &size) || size < 0)
michael@0 493 return false;
michael@0 494 for (int i = 0; i < size; ++i) {
michael@0 495 K k;
michael@0 496 if (!ReadParam(m, iter, &k))
michael@0 497 return false;
michael@0 498 V& value = (*r)[k];
michael@0 499 if (!ReadParam(m, iter, &value))
michael@0 500 return false;
michael@0 501 }
michael@0 502 return true;
michael@0 503 }
michael@0 504 static void Log(const param_type& p, std::wstring* l) {
michael@0 505 l->append(L"<std::map>");
michael@0 506 }
michael@0 507 };
michael@0 508
michael@0 509 // Windows-specific types.
michael@0 510
michael@0 511 template <class P>
michael@0 512 struct ParamTraitsWindows : ParamTraitsStd<P> {};
michael@0 513
michael@0 514 #if defined(OS_WIN)
michael@0 515 template <>
michael@0 516 struct ParamTraitsWindows<LOGFONT> {
michael@0 517 typedef LOGFONT param_type;
michael@0 518 static void Write(Message* m, const param_type& p) {
michael@0 519 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
michael@0 520 }
michael@0 521 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 522 const char *data;
michael@0 523 int data_size = 0;
michael@0 524 bool result = m->ReadData(iter, &data, &data_size);
michael@0 525 if (result && data_size == sizeof(LOGFONT)) {
michael@0 526 memcpy(r, data, sizeof(LOGFONT));
michael@0 527 } else {
michael@0 528 result = false;
michael@0 529 NOTREACHED();
michael@0 530 }
michael@0 531
michael@0 532 return result;
michael@0 533 }
michael@0 534 static void Log(const param_type& p, std::wstring* l) {
michael@0 535 l->append(StringPrintf(L"<LOGFONT>"));
michael@0 536 }
michael@0 537 };
michael@0 538
michael@0 539 template <>
michael@0 540 struct ParamTraitsWindows<MSG> {
michael@0 541 typedef MSG param_type;
michael@0 542 static void Write(Message* m, const param_type& p) {
michael@0 543 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
michael@0 544 }
michael@0 545 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 546 const char *data;
michael@0 547 int data_size = 0;
michael@0 548 bool result = m->ReadData(iter, &data, &data_size);
michael@0 549 if (result && data_size == sizeof(MSG)) {
michael@0 550 memcpy(r, data, sizeof(MSG));
michael@0 551 } else {
michael@0 552 result = false;
michael@0 553 NOTREACHED();
michael@0 554 }
michael@0 555
michael@0 556 return result;
michael@0 557 }
michael@0 558 };
michael@0 559
michael@0 560 template <>
michael@0 561 struct ParamTraitsWindows<HANDLE> {
michael@0 562 typedef HANDLE param_type;
michael@0 563 static void Write(Message* m, const param_type& p) {
michael@0 564 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
michael@0 565 }
michael@0 566 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 567 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
michael@0 568 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
michael@0 569 }
michael@0 570 static void Log(const param_type& p, std::wstring* l) {
michael@0 571 l->append(StringPrintf(L"0x%X", p));
michael@0 572 }
michael@0 573 };
michael@0 574
michael@0 575 template <>
michael@0 576 struct ParamTraitsWindows<HCURSOR> {
michael@0 577 typedef HCURSOR param_type;
michael@0 578 static void Write(Message* m, const param_type& p) {
michael@0 579 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
michael@0 580 }
michael@0 581 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 582 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
michael@0 583 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
michael@0 584 }
michael@0 585 static void Log(const param_type& p, std::wstring* l) {
michael@0 586 l->append(StringPrintf(L"0x%X", p));
michael@0 587 }
michael@0 588 };
michael@0 589
michael@0 590 template <>
michael@0 591 struct ParamTraitsWindows<HWND> {
michael@0 592 typedef HWND param_type;
michael@0 593 static void Write(Message* m, const param_type& p) {
michael@0 594 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
michael@0 595 }
michael@0 596 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 597 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
michael@0 598 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
michael@0 599 }
michael@0 600 static void Log(const param_type& p, std::wstring* l) {
michael@0 601 l->append(StringPrintf(L"0x%X", p));
michael@0 602 }
michael@0 603 };
michael@0 604
michael@0 605 template <>
michael@0 606 struct ParamTraitsWindows<HACCEL> {
michael@0 607 typedef HACCEL param_type;
michael@0 608 static void Write(Message* m, const param_type& p) {
michael@0 609 m->WriteIntPtr(reinterpret_cast<intptr_t>(p));
michael@0 610 }
michael@0 611 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 612 DCHECK_EQ(sizeof(param_type), sizeof(intptr_t));
michael@0 613 return m->ReadIntPtr(iter, reinterpret_cast<intptr_t*>(r));
michael@0 614 }
michael@0 615 };
michael@0 616
michael@0 617 template <>
michael@0 618 struct ParamTraitsWindows<POINT> {
michael@0 619 typedef POINT param_type;
michael@0 620 static void Write(Message* m, const param_type& p) {
michael@0 621 m->WriteInt(p.x);
michael@0 622 m->WriteInt(p.y);
michael@0 623 }
michael@0 624 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 625 int x, y;
michael@0 626 if (!m->ReadInt(iter, &x) || !m->ReadInt(iter, &y))
michael@0 627 return false;
michael@0 628 r->x = x;
michael@0 629 r->y = y;
michael@0 630 return true;
michael@0 631 }
michael@0 632 static void Log(const param_type& p, std::wstring* l) {
michael@0 633 l->append(StringPrintf(L"(%d, %d)", p.x, p.y));
michael@0 634 }
michael@0 635 };
michael@0 636
michael@0 637 template <>
michael@0 638 struct ParamTraitsWindows<XFORM> {
michael@0 639 typedef XFORM param_type;
michael@0 640 static void Write(Message* m, const param_type& p) {
michael@0 641 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(XFORM));
michael@0 642 }
michael@0 643 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 644 const char *data;
michael@0 645 int data_size = 0;
michael@0 646 bool result = m->ReadData(iter, &data, &data_size);
michael@0 647 if (result && data_size == sizeof(XFORM)) {
michael@0 648 memcpy(r, data, sizeof(XFORM));
michael@0 649 } else {
michael@0 650 result = false;
michael@0 651 NOTREACHED();
michael@0 652 }
michael@0 653
michael@0 654 return result;
michael@0 655 }
michael@0 656 static void Log(const param_type& p, std::wstring* l) {
michael@0 657 l->append(L"<XFORM>");
michael@0 658 }
michael@0 659 };
michael@0 660 #endif // defined(OS_WIN)
michael@0 661
michael@0 662 // Various ipc/chromium types.
michael@0 663
michael@0 664 template <class P>
michael@0 665 struct ParamTraitsIPC : ParamTraitsWindows<P> {};
michael@0 666
michael@0 667 template <>
michael@0 668 struct ParamTraitsIPC<base::Time> {
michael@0 669 typedef base::Time param_type;
michael@0 670 static inline void Write(Message* m, const param_type& p);
michael@0 671 static inline bool Read(const Message* m, void** iter, param_type* r);
michael@0 672 static inline void Log(const param_type& p, std::wstring* l);
michael@0 673 };
michael@0 674
michael@0 675 #if defined(OS_POSIX)
michael@0 676 // FileDescriptors may be serialised over IPC channels on POSIX. On the
michael@0 677 // receiving side, the FileDescriptor is a valid duplicate of the file
michael@0 678 // descriptor which was transmitted: *it is not just a copy of the integer like
michael@0 679 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In
michael@0 680 // this case, the receiving end will see a value of -1. *Zero is a valid file
michael@0 681 // descriptor*.
michael@0 682 //
michael@0 683 // The received file descriptor will have the |auto_close| flag set to true. The
michael@0 684 // code which handles the message is responsible for taking ownership of it.
michael@0 685 // File descriptors are OS resources and must be closed when no longer needed.
michael@0 686 //
michael@0 687 // When sending a file descriptor, the file descriptor must be valid at the time
michael@0 688 // of transmission. Since transmission is not synchronous, one should consider
michael@0 689 // dup()ing any file descriptors to be transmitted and setting the |auto_close|
michael@0 690 // flag, which causes the file descriptor to be closed after writing.
michael@0 691 template<>
michael@0 692 struct ParamTraitsIPC<base::FileDescriptor> {
michael@0 693 typedef base::FileDescriptor param_type;
michael@0 694 static void Write(Message* m, const param_type& p) {
michael@0 695 const bool valid = p.fd >= 0;
michael@0 696 WriteParam(m, valid);
michael@0 697
michael@0 698 if (valid) {
michael@0 699 if (!m->WriteFileDescriptor(p)) {
michael@0 700 NOTREACHED() << "Too many file descriptors for one message!";
michael@0 701 }
michael@0 702 }
michael@0 703 }
michael@0 704 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 705 bool valid;
michael@0 706 if (!ReadParam(m, iter, &valid))
michael@0 707 return false;
michael@0 708
michael@0 709 if (!valid) {
michael@0 710 r->fd = -1;
michael@0 711 r->auto_close = false;
michael@0 712 return true;
michael@0 713 }
michael@0 714
michael@0 715 return m->ReadFileDescriptor(iter, r);
michael@0 716 }
michael@0 717 static void Log(const param_type& p, std::wstring* l) {
michael@0 718 if (p.auto_close) {
michael@0 719 l->append(StringPrintf(L"FD(%d auto-close)", p.fd));
michael@0 720 } else {
michael@0 721 l->append(StringPrintf(L"FD(%d)", p.fd));
michael@0 722 }
michael@0 723 }
michael@0 724 };
michael@0 725 #endif // defined(OS_POSIX)
michael@0 726
michael@0 727 template <>
michael@0 728 struct ParamTraitsIPC<FilePath> {
michael@0 729 typedef FilePath param_type;
michael@0 730 static void Write(Message* m, const param_type& p);
michael@0 731 static bool Read(const Message* m, void** iter, param_type* r);
michael@0 732 static void Log(const param_type& p, std::wstring* l);
michael@0 733 };
michael@0 734
michael@0 735 struct LogData {
michael@0 736 std::wstring channel;
michael@0 737 int32_t routing_id;
michael@0 738 uint16_t type;
michael@0 739 std::wstring flags;
michael@0 740 int64_t sent; // Time that the message was sent (i.e. at Send()).
michael@0 741 int64_t receive; // Time before it was dispatched (i.e. before calling
michael@0 742 // OnMessageReceived).
michael@0 743 int64_t dispatch; // Time after it was dispatched (i.e. after calling
michael@0 744 // OnMessageReceived).
michael@0 745 std::wstring message_name;
michael@0 746 std::wstring params;
michael@0 747 };
michael@0 748
michael@0 749 template <>
michael@0 750 struct ParamTraitsIPC<LogData> {
michael@0 751 typedef LogData param_type;
michael@0 752 static void Write(Message* m, const param_type& p) {
michael@0 753 WriteParam(m, p.channel);
michael@0 754 WriteParam(m, p.routing_id);
michael@0 755 WriteParam(m, static_cast<int>(p.type));
michael@0 756 WriteParam(m, p.flags);
michael@0 757 WriteParam(m, p.sent);
michael@0 758 WriteParam(m, p.receive);
michael@0 759 WriteParam(m, p.dispatch);
michael@0 760 WriteParam(m, p.params);
michael@0 761 }
michael@0 762 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 763 int type = 0;
michael@0 764 bool result =
michael@0 765 ReadParam(m, iter, &r->channel) &&
michael@0 766 ReadParam(m, iter, &r->routing_id) &&
michael@0 767 ReadParam(m, iter, &type) &&
michael@0 768 ReadParam(m, iter, &r->flags) &&
michael@0 769 ReadParam(m, iter, &r->sent) &&
michael@0 770 ReadParam(m, iter, &r->receive) &&
michael@0 771 ReadParam(m, iter, &r->dispatch) &&
michael@0 772 ReadParam(m, iter, &r->params);
michael@0 773 r->type = static_cast<uint16_t>(type);
michael@0 774 return result;
michael@0 775 }
michael@0 776 static void Log(const param_type& p, std::wstring* l) {
michael@0 777 // Doesn't make sense to implement this!
michael@0 778 }
michael@0 779 };
michael@0 780
michael@0 781 #if defined(OS_WIN)
michael@0 782 template<>
michael@0 783 struct ParamTraitsIPC<TransportDIB::Id> {
michael@0 784 typedef TransportDIB::Id param_type;
michael@0 785 static void Write(Message* m, const param_type& p) {
michael@0 786 WriteParam(m, p.handle);
michael@0 787 WriteParam(m, p.sequence_num);
michael@0 788 }
michael@0 789 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 790 return (ReadParam(m, iter, &r->handle) &&
michael@0 791 ReadParam(m, iter, &r->sequence_num));
michael@0 792 }
michael@0 793 static void Log(const param_type& p, std::wstring* l) {
michael@0 794 l->append(L"TransportDIB(");
michael@0 795 LogParam(p.handle, l);
michael@0 796 l->append(L", ");
michael@0 797 LogParam(p.sequence_num, l);
michael@0 798 l->append(L")");
michael@0 799 }
michael@0 800 };
michael@0 801 #endif
michael@0 802
michael@0 803 template <>
michael@0 804 struct ParamTraitsIPC<Message> {
michael@0 805 static void Write(Message* m, const Message& p) {
michael@0 806 m->WriteInt(p.size());
michael@0 807 m->WriteData(reinterpret_cast<const char*>(p.data()), p.size());
michael@0 808 }
michael@0 809 static bool Read(const Message* m, void** iter, Message* r) {
michael@0 810 int size;
michael@0 811 if (!m->ReadInt(iter, &size))
michael@0 812 return false;
michael@0 813 const char* data;
michael@0 814 if (!m->ReadData(iter, &data, &size))
michael@0 815 return false;
michael@0 816 *r = Message(data, size);
michael@0 817 return true;
michael@0 818 }
michael@0 819 static void Log(const Message& p, std::wstring* l) {
michael@0 820 l->append(L"<IPC::Message>");
michael@0 821 }
michael@0 822 };
michael@0 823
michael@0 824 template <>
michael@0 825 struct ParamTraitsIPC<Tuple0> {
michael@0 826 typedef Tuple0 param_type;
michael@0 827 static void Write(Message* m, const param_type& p) {
michael@0 828 }
michael@0 829 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 830 return true;
michael@0 831 }
michael@0 832 static void Log(const param_type& p, std::wstring* l) {
michael@0 833 }
michael@0 834 };
michael@0 835
michael@0 836 template <class A>
michael@0 837 struct ParamTraitsIPC< Tuple1<A> > {
michael@0 838 typedef Tuple1<A> param_type;
michael@0 839 static void Write(Message* m, const param_type& p) {
michael@0 840 WriteParam(m, p.a);
michael@0 841 }
michael@0 842 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 843 return ReadParam(m, iter, &r->a);
michael@0 844 }
michael@0 845 static void Log(const param_type& p, std::wstring* l) {
michael@0 846 LogParam(p.a, l);
michael@0 847 }
michael@0 848 };
michael@0 849
michael@0 850 template <class A, class B>
michael@0 851 struct ParamTraitsIPC< Tuple2<A, B> > {
michael@0 852 typedef Tuple2<A, B> param_type;
michael@0 853 static void Write(Message* m, const param_type& p) {
michael@0 854 WriteParam(m, p.a);
michael@0 855 WriteParam(m, p.b);
michael@0 856 }
michael@0 857 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 858 return (ReadParam(m, iter, &r->a) &&
michael@0 859 ReadParam(m, iter, &r->b));
michael@0 860 }
michael@0 861 static void Log(const param_type& p, std::wstring* l) {
michael@0 862 LogParam(p.a, l);
michael@0 863 l->append(L", ");
michael@0 864 LogParam(p.b, l);
michael@0 865 }
michael@0 866 };
michael@0 867
michael@0 868 template <class A, class B, class C>
michael@0 869 struct ParamTraitsIPC< Tuple3<A, B, C> > {
michael@0 870 typedef Tuple3<A, B, C> param_type;
michael@0 871 static void Write(Message* m, const param_type& p) {
michael@0 872 WriteParam(m, p.a);
michael@0 873 WriteParam(m, p.b);
michael@0 874 WriteParam(m, p.c);
michael@0 875 }
michael@0 876 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 877 return (ReadParam(m, iter, &r->a) &&
michael@0 878 ReadParam(m, iter, &r->b) &&
michael@0 879 ReadParam(m, iter, &r->c));
michael@0 880 }
michael@0 881 static void Log(const param_type& p, std::wstring* l) {
michael@0 882 LogParam(p.a, l);
michael@0 883 l->append(L", ");
michael@0 884 LogParam(p.b, l);
michael@0 885 l->append(L", ");
michael@0 886 LogParam(p.c, l);
michael@0 887 }
michael@0 888 };
michael@0 889
michael@0 890 template <class A, class B, class C, class D>
michael@0 891 struct ParamTraitsIPC< Tuple4<A, B, C, D> > {
michael@0 892 typedef Tuple4<A, B, C, D> param_type;
michael@0 893 static void Write(Message* m, const param_type& p) {
michael@0 894 WriteParam(m, p.a);
michael@0 895 WriteParam(m, p.b);
michael@0 896 WriteParam(m, p.c);
michael@0 897 WriteParam(m, p.d);
michael@0 898 }
michael@0 899 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 900 return (ReadParam(m, iter, &r->a) &&
michael@0 901 ReadParam(m, iter, &r->b) &&
michael@0 902 ReadParam(m, iter, &r->c) &&
michael@0 903 ReadParam(m, iter, &r->d));
michael@0 904 }
michael@0 905 static void Log(const param_type& p, std::wstring* l) {
michael@0 906 LogParam(p.a, l);
michael@0 907 l->append(L", ");
michael@0 908 LogParam(p.b, l);
michael@0 909 l->append(L", ");
michael@0 910 LogParam(p.c, l);
michael@0 911 l->append(L", ");
michael@0 912 LogParam(p.d, l);
michael@0 913 }
michael@0 914 };
michael@0 915
michael@0 916 template <class A, class B, class C, class D, class E>
michael@0 917 struct ParamTraitsIPC< Tuple5<A, B, C, D, E> > {
michael@0 918 typedef Tuple5<A, B, C, D, E> param_type;
michael@0 919 static void Write(Message* m, const param_type& p) {
michael@0 920 WriteParam(m, p.a);
michael@0 921 WriteParam(m, p.b);
michael@0 922 WriteParam(m, p.c);
michael@0 923 WriteParam(m, p.d);
michael@0 924 WriteParam(m, p.e);
michael@0 925 }
michael@0 926 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 927 return (ReadParam(m, iter, &r->a) &&
michael@0 928 ReadParam(m, iter, &r->b) &&
michael@0 929 ReadParam(m, iter, &r->c) &&
michael@0 930 ReadParam(m, iter, &r->d) &&
michael@0 931 ReadParam(m, iter, &r->e));
michael@0 932 }
michael@0 933 static void Log(const param_type& p, std::wstring* l) {
michael@0 934 LogParam(p.a, l);
michael@0 935 l->append(L", ");
michael@0 936 LogParam(p.b, l);
michael@0 937 l->append(L", ");
michael@0 938 LogParam(p.c, l);
michael@0 939 l->append(L", ");
michael@0 940 LogParam(p.d, l);
michael@0 941 l->append(L", ");
michael@0 942 LogParam(p.e, l);
michael@0 943 }
michael@0 944 };
michael@0 945
michael@0 946 template <class A, class B, class C, class D, class E, class F>
michael@0 947 struct ParamTraitsIPC< Tuple6<A, B, C, D, E, F> > {
michael@0 948 typedef Tuple6<A, B, C, D, E, F> param_type;
michael@0 949 static void Write(Message* m, const param_type& p) {
michael@0 950 WriteParam(m, p.a);
michael@0 951 WriteParam(m, p.b);
michael@0 952 WriteParam(m, p.c);
michael@0 953 WriteParam(m, p.d);
michael@0 954 WriteParam(m, p.e);
michael@0 955 WriteParam(m, p.f);
michael@0 956 }
michael@0 957 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 958 return (ReadParam(m, iter, &r->a) &&
michael@0 959 ReadParam(m, iter, &r->b) &&
michael@0 960 ReadParam(m, iter, &r->c) &&
michael@0 961 ReadParam(m, iter, &r->d) &&
michael@0 962 ReadParam(m, iter, &r->e) &&
michael@0 963 ReadParam(m, iter, &r->f));
michael@0 964 }
michael@0 965 static void Log(const param_type& p, std::wstring* l) {
michael@0 966 LogParam(p.a, l);
michael@0 967 l->append(L", ");
michael@0 968 LogParam(p.b, l);
michael@0 969 l->append(L", ");
michael@0 970 LogParam(p.c, l);
michael@0 971 l->append(L", ");
michael@0 972 LogParam(p.d, l);
michael@0 973 l->append(L", ");
michael@0 974 LogParam(p.e, l);
michael@0 975 l->append(L", ");
michael@0 976 LogParam(p.f, l);
michael@0 977 }
michael@0 978 };
michael@0 979
michael@0 980 // Mozilla-specific types.
michael@0 981
michael@0 982 template <class P>
michael@0 983 struct ParamTraitsMozilla : ParamTraitsIPC<P> {};
michael@0 984
michael@0 985 template <>
michael@0 986 struct ParamTraitsMozilla<nsresult> {
michael@0 987 typedef nsresult param_type;
michael@0 988 static void Write(Message* m, const param_type& p) {
michael@0 989 m->WriteUInt32(static_cast<uint32_t>(p));
michael@0 990 }
michael@0 991 static bool Read(const Message* m, void** iter, param_type* r) {
michael@0 992 return m->ReadUInt32(iter, reinterpret_cast<uint32_t*>(r));
michael@0 993 }
michael@0 994 static void Log(const param_type& p, std::wstring* l) {
michael@0 995 l->append(StringPrintf(L"%u", static_cast<uint32_t>(p)));
michael@0 996 }
michael@0 997 };
michael@0 998
michael@0 999 // Finally, ParamTraits itself.
michael@0 1000
michael@0 1001 template <class P> struct ParamTraits : ParamTraitsMozilla<P> {};
michael@0 1002
michael@0 1003 // Now go back and define inlines dependent upon various ParamTraits<P>.
michael@0 1004 inline void
michael@0 1005 ParamTraitsIPC<base::Time>::Write(Message* m, const param_type& p) {
michael@0 1006 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
michael@0 1007 }
michael@0 1008 inline bool
michael@0 1009 ParamTraitsIPC<base::Time>::Read(const Message* m, void** iter, param_type* r) {
michael@0 1010 int64_t value;
michael@0 1011 if (!ParamTraits<int64_t>::Read(m, iter, &value))
michael@0 1012 return false;
michael@0 1013 *r = base::Time::FromInternalValue(value);
michael@0 1014 return true;
michael@0 1015 }
michael@0 1016 inline void
michael@0 1017 ParamTraitsIPC<base::Time>::Log(const param_type& p, std::wstring* l) {
michael@0 1018 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
michael@0 1019 }
michael@0 1020
michael@0 1021 inline void
michael@0 1022 ParamTraitsIPC<FilePath>::Write(Message* m, const param_type& p) {
michael@0 1023 ParamTraits<FilePath::StringType>::Write(m, p.value());
michael@0 1024 }
michael@0 1025 inline bool
michael@0 1026 ParamTraitsIPC<FilePath>::Read(const Message* m, void** iter, param_type* r) {
michael@0 1027 FilePath::StringType value;
michael@0 1028 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
michael@0 1029 return false;
michael@0 1030 *r = FilePath(value);
michael@0 1031 return true;
michael@0 1032 }
michael@0 1033 inline void
michael@0 1034 ParamTraitsIPC<FilePath>::Log(const param_type& p, std::wstring* l) {
michael@0 1035 ParamTraits<FilePath::StringType>::Log(p.value(), l);
michael@0 1036 }
michael@0 1037
michael@0 1038 //-----------------------------------------------------------------------------
michael@0 1039 // Generic message subclasses
michael@0 1040
michael@0 1041 // Used for asynchronous messages.
michael@0 1042 template <class ParamType>
michael@0 1043 class MessageWithTuple : public Message {
michael@0 1044 public:
michael@0 1045 typedef ParamType Param;
michael@0 1046
michael@0 1047 MessageWithTuple(int32_t routing_id, uint16_t type, const Param& p)
michael@0 1048 : Message(routing_id, type, PRIORITY_NORMAL) {
michael@0 1049 WriteParam(this, p);
michael@0 1050 }
michael@0 1051
michael@0 1052 static bool Read(const Message* msg, Param* p) {
michael@0 1053 void* iter = NULL;
michael@0 1054 bool rv = ReadParam(msg, &iter, p);
michael@0 1055 DCHECK(rv) << "Error deserializing message " << msg->type();
michael@0 1056 return rv;
michael@0 1057 }
michael@0 1058
michael@0 1059 // Generic dispatcher. Should cover most cases.
michael@0 1060 template<class T, class Method>
michael@0 1061 static bool Dispatch(const Message* msg, T* obj, Method func) {
michael@0 1062 Param p;
michael@0 1063 if (Read(msg, &p)) {
michael@0 1064 DispatchToMethod(obj, func, p);
michael@0 1065 return true;
michael@0 1066 }
michael@0 1067 return false;
michael@0 1068 }
michael@0 1069
michael@0 1070 // The following dispatchers exist for the case where the callback function
michael@0 1071 // needs the message as well. They assume that "Param" is a type of Tuple
michael@0 1072 // (except the one arg case, as there is no Tuple1).
michael@0 1073 template<class T, typename TA>
michael@0 1074 static bool Dispatch(const Message* msg, T* obj,
michael@0 1075 void (T::*func)(const Message&, TA)) {
michael@0 1076 Param p;
michael@0 1077 if (Read(msg, &p)) {
michael@0 1078 (obj->*func)(*msg, p);
michael@0 1079 return true;
michael@0 1080 }
michael@0 1081 return false;
michael@0 1082 }
michael@0 1083
michael@0 1084 template<class T, typename TA, typename TB>
michael@0 1085 static bool Dispatch(const Message* msg, T* obj,
michael@0 1086 void (T::*func)(const Message&, TA, TB)) {
michael@0 1087 Param p;
michael@0 1088 if (Read(msg, &p)) {
michael@0 1089 (obj->*func)(*msg, p.a, p.b);
michael@0 1090 return true;
michael@0 1091 }
michael@0 1092 return false;
michael@0 1093 }
michael@0 1094
michael@0 1095 template<class T, typename TA, typename TB, typename TC>
michael@0 1096 static bool Dispatch(const Message* msg, T* obj,
michael@0 1097 void (T::*func)(const Message&, TA, TB, TC)) {
michael@0 1098 Param p;
michael@0 1099 if (Read(msg, &p)) {
michael@0 1100 (obj->*func)(*msg, p.a, p.b, p.c);
michael@0 1101 return true;
michael@0 1102 }
michael@0 1103 return false;
michael@0 1104 }
michael@0 1105
michael@0 1106 template<class T, typename TA, typename TB, typename TC, typename TD>
michael@0 1107 static bool Dispatch(const Message* msg, T* obj,
michael@0 1108 void (T::*func)(const Message&, TA, TB, TC, TD)) {
michael@0 1109 Param p;
michael@0 1110 if (Read(msg, &p)) {
michael@0 1111 (obj->*func)(*msg, p.a, p.b, p.c, p.d);
michael@0 1112 return true;
michael@0 1113 }
michael@0 1114 return false;
michael@0 1115 }
michael@0 1116
michael@0 1117 template<class T, typename TA, typename TB, typename TC, typename TD,
michael@0 1118 typename TE>
michael@0 1119 static bool Dispatch(const Message* msg, T* obj,
michael@0 1120 void (T::*func)(const Message&, TA, TB, TC, TD, TE)) {
michael@0 1121 Param p;
michael@0 1122 if (Read(msg, &p)) {
michael@0 1123 (obj->*func)(*msg, p.a, p.b, p.c, p.d, p.e);
michael@0 1124 return true;
michael@0 1125 }
michael@0 1126 return false;
michael@0 1127 }
michael@0 1128
michael@0 1129 static void Log(const Message* msg, std::wstring* l) {
michael@0 1130 Param p;
michael@0 1131 if (Read(msg, &p))
michael@0 1132 LogParam(p, l);
michael@0 1133 }
michael@0 1134
michael@0 1135 // Functions used to do manual unpacking. Only used by the automation code,
michael@0 1136 // these should go away once that code uses SyncChannel.
michael@0 1137 template<typename TA, typename TB>
michael@0 1138 static bool Read(const IPC::Message* msg, TA* a, TB* b) {
michael@0 1139 ParamType params;
michael@0 1140 if (!Read(msg, &params))
michael@0 1141 return false;
michael@0 1142 *a = params.a;
michael@0 1143 *b = params.b;
michael@0 1144 return true;
michael@0 1145 }
michael@0 1146
michael@0 1147 template<typename TA, typename TB, typename TC>
michael@0 1148 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c) {
michael@0 1149 ParamType params;
michael@0 1150 if (!Read(msg, &params))
michael@0 1151 return false;
michael@0 1152 *a = params.a;
michael@0 1153 *b = params.b;
michael@0 1154 *c = params.c;
michael@0 1155 return true;
michael@0 1156 }
michael@0 1157
michael@0 1158 template<typename TA, typename TB, typename TC, typename TD>
michael@0 1159 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d) {
michael@0 1160 ParamType params;
michael@0 1161 if (!Read(msg, &params))
michael@0 1162 return false;
michael@0 1163 *a = params.a;
michael@0 1164 *b = params.b;
michael@0 1165 *c = params.c;
michael@0 1166 *d = params.d;
michael@0 1167 return true;
michael@0 1168 }
michael@0 1169
michael@0 1170 template<typename TA, typename TB, typename TC, typename TD, typename TE>
michael@0 1171 static bool Read(const IPC::Message* msg, TA* a, TB* b, TC* c, TD* d, TE* e) {
michael@0 1172 ParamType params;
michael@0 1173 if (!Read(msg, &params))
michael@0 1174 return false;
michael@0 1175 *a = params.a;
michael@0 1176 *b = params.b;
michael@0 1177 *c = params.c;
michael@0 1178 *d = params.d;
michael@0 1179 *e = params.e;
michael@0 1180 return true;
michael@0 1181 }
michael@0 1182 };
michael@0 1183
michael@0 1184 // This class assumes that its template argument is a RefTuple (a Tuple with
michael@0 1185 // reference elements).
michael@0 1186 template <class RefTuple>
michael@0 1187 class ParamDeserializer : public MessageReplyDeserializer {
michael@0 1188 public:
michael@0 1189 explicit ParamDeserializer(const RefTuple& out) : out_(out) { }
michael@0 1190
michael@0 1191 bool SerializeOutputParameters(const IPC::Message& msg, void* iter) {
michael@0 1192 return ReadParam(&msg, &iter, &out_);
michael@0 1193 }
michael@0 1194
michael@0 1195 RefTuple out_;
michael@0 1196 };
michael@0 1197
michael@0 1198 // defined in ipc_logging.cc
michael@0 1199 void GenerateLogData(const std::wstring& channel, const Message& message,
michael@0 1200 LogData* data);
michael@0 1201
michael@0 1202 // Used for synchronous messages.
michael@0 1203 template <class SendParamType, class ReplyParamType>
michael@0 1204 class MessageWithReply : public SyncMessage {
michael@0 1205 public:
michael@0 1206 typedef SendParamType SendParam;
michael@0 1207 typedef ReplyParamType ReplyParam;
michael@0 1208
michael@0 1209 MessageWithReply(int32_t routing_id, uint16_t type,
michael@0 1210 const SendParam& send, const ReplyParam& reply)
michael@0 1211 : SyncMessage(routing_id, type, PRIORITY_NORMAL,
michael@0 1212 new ParamDeserializer<ReplyParam>(reply)) {
michael@0 1213 WriteParam(this, send);
michael@0 1214 }
michael@0 1215
michael@0 1216 static void Log(const Message* msg, std::wstring* l) {
michael@0 1217 if (msg->is_sync()) {
michael@0 1218 SendParam p;
michael@0 1219 void* iter = SyncMessage::GetDataIterator(msg);
michael@0 1220 if (ReadParam(msg, &iter, &p))
michael@0 1221 LogParam(p, l);
michael@0 1222
michael@0 1223 #if defined(IPC_MESSAGE_LOG_ENABLED)
michael@0 1224 const std::wstring& output_params = msg->output_params();
michael@0 1225 if (!l->empty() && !output_params.empty())
michael@0 1226 l->append(L", ");
michael@0 1227
michael@0 1228 l->append(output_params);
michael@0 1229 #endif
michael@0 1230 } else {
michael@0 1231 // This is an outgoing reply. Now that we have the output parameters, we
michael@0 1232 // can finally log the message.
michael@0 1233 typename ReplyParam::ValueTuple p;
michael@0 1234 void* iter = SyncMessage::GetDataIterator(msg);
michael@0 1235 if (ReadParam(msg, &iter, &p))
michael@0 1236 LogParam(p, l);
michael@0 1237 }
michael@0 1238 }
michael@0 1239
michael@0 1240 template<class T, class Method>
michael@0 1241 static bool Dispatch(const Message* msg, T* obj, Method func) {
michael@0 1242 SendParam send_params;
michael@0 1243 void* iter = GetDataIterator(msg);
michael@0 1244 Message* reply = GenerateReply(msg);
michael@0 1245 bool error;
michael@0 1246 if (ReadParam(msg, &iter, &send_params)) {
michael@0 1247 typename ReplyParam::ValueTuple reply_params;
michael@0 1248 DispatchToMethod(obj, func, send_params, &reply_params);
michael@0 1249 WriteParam(reply, reply_params);
michael@0 1250 error = false;
michael@0 1251 #ifdef IPC_MESSAGE_LOG_ENABLED
michael@0 1252 if (msg->received_time() != 0) {
michael@0 1253 std::wstring output_params;
michael@0 1254 LogParam(reply_params, &output_params);
michael@0 1255 msg->set_output_params(output_params);
michael@0 1256 }
michael@0 1257 #endif
michael@0 1258 } else {
michael@0 1259 NOTREACHED() << "Error deserializing message " << msg->type();
michael@0 1260 reply->set_reply_error();
michael@0 1261 error = true;
michael@0 1262 }
michael@0 1263
michael@0 1264 obj->Send(reply);
michael@0 1265 return !error;
michael@0 1266 }
michael@0 1267
michael@0 1268 template<class T, class Method>
michael@0 1269 static bool DispatchDelayReply(const Message* msg, T* obj, Method func) {
michael@0 1270 SendParam send_params;
michael@0 1271 void* iter = GetDataIterator(msg);
michael@0 1272 Message* reply = GenerateReply(msg);
michael@0 1273 bool error;
michael@0 1274 if (ReadParam(msg, &iter, &send_params)) {
michael@0 1275 Tuple1<Message&> t = MakeRefTuple(*reply);
michael@0 1276
michael@0 1277 #ifdef IPC_MESSAGE_LOG_ENABLED
michael@0 1278 if (msg->sent_time()) {
michael@0 1279 // Don't log the sync message after dispatch, as we don't have the
michael@0 1280 // output parameters at that point. Instead, save its data and log it
michael@0 1281 // with the outgoing reply message when it's sent.
michael@0 1282 LogData* data = new LogData;
michael@0 1283 GenerateLogData(L"", *msg, data);
michael@0 1284 msg->set_dont_log();
michael@0 1285 reply->set_sync_log_data(data);
michael@0 1286 }
michael@0 1287 #endif
michael@0 1288 DispatchToMethod(obj, func, send_params, &t);
michael@0 1289 error = false;
michael@0 1290 } else {
michael@0 1291 NOTREACHED() << "Error deserializing message " << msg->type();
michael@0 1292 reply->set_reply_error();
michael@0 1293 obj->Send(reply);
michael@0 1294 error = true;
michael@0 1295 }
michael@0 1296 return !error;
michael@0 1297 }
michael@0 1298
michael@0 1299 template<typename TA>
michael@0 1300 static void WriteReplyParams(Message* reply, TA a) {
michael@0 1301 ReplyParam p(a);
michael@0 1302 WriteParam(reply, p);
michael@0 1303 }
michael@0 1304
michael@0 1305 template<typename TA, typename TB>
michael@0 1306 static void WriteReplyParams(Message* reply, TA a, TB b) {
michael@0 1307 ReplyParam p(a, b);
michael@0 1308 WriteParam(reply, p);
michael@0 1309 }
michael@0 1310
michael@0 1311 template<typename TA, typename TB, typename TC>
michael@0 1312 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) {
michael@0 1313 ReplyParam p(a, b, c);
michael@0 1314 WriteParam(reply, p);
michael@0 1315 }
michael@0 1316
michael@0 1317 template<typename TA, typename TB, typename TC, typename TD>
michael@0 1318 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) {
michael@0 1319 ReplyParam p(a, b, c, d);
michael@0 1320 WriteParam(reply, p);
michael@0 1321 }
michael@0 1322
michael@0 1323 template<typename TA, typename TB, typename TC, typename TD, typename TE>
michael@0 1324 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) {
michael@0 1325 ReplyParam p(a, b, c, d, e);
michael@0 1326 WriteParam(reply, p);
michael@0 1327 }
michael@0 1328 };
michael@0 1329
michael@0 1330 //-----------------------------------------------------------------------------
michael@0 1331
michael@0 1332 } // namespace IPC
michael@0 1333
michael@0 1334 #endif // CHROME_COMMON_IPC_MESSAGE_UTILS_H_

mercurial