1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef IPC_IPC_MESSAGE_UTILS_H_ 6 #define IPC_IPC_MESSAGE_UTILS_H_ 7 8 #include <algorithm> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <vector> 13 14 #include "base/format_macros.h" 15 #include "base/memory/scoped_vector.h" 16 #include "base/platform_file.h" 17 #include "base/strings/string16.h" 18 #include "base/strings/string_util.h" 19 #include "base/strings/stringprintf.h" 20 #include "base/tuple.h" 21 #include "ipc/ipc_message_start.h" 22 #include "ipc/ipc_param_traits.h" 23 #include "ipc/ipc_sync_message.h" 24 25 #if defined(COMPILER_GCC) 26 // GCC "helpfully" tries to inline template methods in release mode. Except we 27 // want the majority of the template junk being expanded once in the 28 // implementation file (and only provide the definitions in 29 // ipc_message_utils_impl.h in those files) and exported, instead of expanded 30 // at every call site. Special note: GCC happily accepts the attribute before 31 // the method declaration, but only acts on it if it is after. 32 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40500 33 // Starting in gcc 4.5, the noinline no longer implies the concept covered by 34 // the introduced noclone attribute, which will create specialized versions of 35 // functions/methods when certain types are constant. 36 // www.gnu.org/software/gcc/gcc-4.5/changes.html 37 #define IPC_MSG_NOINLINE __attribute__((noinline, noclone)); 38 #else 39 #define IPC_MSG_NOINLINE __attribute__((noinline)); 40 #endif 41 #elif defined(COMPILER_MSVC) 42 // MSVC++ doesn't do this. 43 #define IPC_MSG_NOINLINE 44 #else 45 #error "Please add the noinline property for your new compiler here." 46 #endif 47 48 namespace base { 49 class DictionaryValue; 50 class FilePath; 51 class ListValue; 52 class NullableString16; 53 class Time; 54 class TimeDelta; 55 class TimeTicks; 56 struct FileDescriptor; 57 } 58 59 namespace IPC { 60 61 struct ChannelHandle; 62 63 // ----------------------------------------------------------------------------- 64 // How we send IPC message logs across channels. 65 struct IPC_EXPORT LogData { 66 LogData(); 67 ~LogData(); 68 69 std::string channel; 70 int32 routing_id; 71 uint32 type; // "User-defined" message type, from ipc_message.h. 72 std::string flags; 73 int64 sent; // Time that the message was sent (i.e. at Send()). 74 int64 receive; // Time before it was dispatched (i.e. before calling 75 // OnMessageReceived). 76 int64 dispatch; // Time after it was dispatched (i.e. after calling 77 // OnMessageReceived). 78 std::string message_name; 79 std::string params; 80 }; 81 82 //----------------------------------------------------------------------------- 83 84 // A dummy struct to place first just to allow leading commas for all 85 // members in the macro-generated constructor initializer lists. 86 struct NoParams { 87 }; 88 89 template <class P> 90 static inline void WriteParam(Message* m, const P& p) { 91 typedef typename SimilarTypeTraits<P>::Type Type; 92 ParamTraits<Type>::Write(m, static_cast<const Type& >(p)); 93 } 94 95 template <class P> 96 static inline bool WARN_UNUSED_RESULT ReadParam(const Message* m, 97 PickleIterator* iter, 98 P* p) { 99 typedef typename SimilarTypeTraits<P>::Type Type; 100 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p)); 101 } 102 103 template <class P> 104 static inline void LogParam(const P& p, std::string* l) { 105 typedef typename SimilarTypeTraits<P>::Type Type; 106 ParamTraits<Type>::Log(static_cast<const Type& >(p), l); 107 } 108 109 // Primitive ParamTraits ------------------------------------------------------- 110 111 template <> 112 struct ParamTraits<bool> { 113 typedef bool param_type; 114 static void Write(Message* m, const param_type& p) { 115 m->WriteBool(p); 116 } 117 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 118 return m->ReadBool(iter, r); 119 } 120 IPC_EXPORT static void Log(const param_type& p, std::string* l); 121 }; 122 123 template <> 124 struct IPC_EXPORT ParamTraits<unsigned char> { 125 typedef unsigned char param_type; 126 static void Write(Message* m, const param_type& p); 127 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 128 static void Log(const param_type& p, std::string* l); 129 }; 130 131 template <> 132 struct IPC_EXPORT ParamTraits<unsigned short> { 133 typedef unsigned short param_type; 134 static void Write(Message* m, const param_type& p); 135 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 136 static void Log(const param_type& p, std::string* l); 137 }; 138 139 template <> 140 struct ParamTraits<int> { 141 typedef int param_type; 142 static void Write(Message* m, const param_type& p) { 143 m->WriteInt(p); 144 } 145 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 146 return m->ReadInt(iter, r); 147 } 148 IPC_EXPORT static void Log(const param_type& p, std::string* l); 149 }; 150 151 template <> 152 struct ParamTraits<unsigned int> { 153 typedef unsigned int param_type; 154 static void Write(Message* m, const param_type& p) { 155 m->WriteInt(p); 156 } 157 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 158 return m->ReadInt(iter, reinterpret_cast<int*>(r)); 159 } 160 IPC_EXPORT static void Log(const param_type& p, std::string* l); 161 }; 162 163 template <> 164 struct ParamTraits<long> { 165 typedef long param_type; 166 static void Write(Message* m, const param_type& p) { 167 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p); 168 } 169 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 170 return m->ReadLong(iter, r); 171 } 172 IPC_EXPORT static void Log(const param_type& p, std::string* l); 173 }; 174 175 template <> 176 struct ParamTraits<unsigned long> { 177 typedef unsigned long param_type; 178 static void Write(Message* m, const param_type& p) { 179 m->WriteLongUsingDangerousNonPortableLessPersistableForm(p); 180 } 181 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 182 return m->ReadLong(iter, reinterpret_cast<long*>(r)); 183 } 184 IPC_EXPORT static void Log(const param_type& p, std::string* l); 185 }; 186 187 template <> 188 struct ParamTraits<long long> { 189 typedef long long param_type; 190 static void Write(Message* m, const param_type& p) { 191 m->WriteInt64(static_cast<int64>(p)); 192 } 193 static bool Read(const Message* m, PickleIterator* iter, 194 param_type* r) { 195 return m->ReadInt64(iter, reinterpret_cast<int64*>(r)); 196 } 197 IPC_EXPORT static void Log(const param_type& p, std::string* l); 198 }; 199 200 template <> 201 struct ParamTraits<unsigned long long> { 202 typedef unsigned long long param_type; 203 static void Write(Message* m, const param_type& p) { 204 m->WriteInt64(p); 205 } 206 static bool Read(const Message* m, PickleIterator* iter, 207 param_type* r) { 208 return m->ReadInt64(iter, reinterpret_cast<int64*>(r)); 209 } 210 IPC_EXPORT static void Log(const param_type& p, std::string* l); 211 }; 212 213 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients 214 // should be sure to check the sanity of these values after receiving them over 215 // IPC. 216 template <> 217 struct IPC_EXPORT ParamTraits<float> { 218 typedef float param_type; 219 static void Write(Message* m, const param_type& p) { 220 m->WriteFloat(p); 221 } 222 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 223 return m->ReadFloat(iter, r); 224 } 225 static void Log(const param_type& p, std::string* l); 226 }; 227 228 template <> 229 struct IPC_EXPORT ParamTraits<double> { 230 typedef double param_type; 231 static void Write(Message* m, const param_type& p); 232 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 233 static void Log(const param_type& p, std::string* l); 234 }; 235 236 // STL ParamTraits ------------------------------------------------------------- 237 238 template <> 239 struct ParamTraits<std::string> { 240 typedef std::string param_type; 241 static void Write(Message* m, const param_type& p) { 242 m->WriteString(p); 243 } 244 static bool Read(const Message* m, PickleIterator* iter, 245 param_type* r) { 246 return m->ReadString(iter, r); 247 } 248 IPC_EXPORT static void Log(const param_type& p, std::string* l); 249 }; 250 251 template <> 252 struct ParamTraits<std::wstring> { 253 typedef std::wstring param_type; 254 static void Write(Message* m, const param_type& p) { 255 m->WriteWString(p); 256 } 257 static bool Read(const Message* m, PickleIterator* iter, 258 param_type* r) { 259 return m->ReadWString(iter, r); 260 } 261 IPC_EXPORT static void Log(const param_type& p, std::string* l); 262 }; 263 264 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't 265 // need this trait. 266 #if !defined(WCHAR_T_IS_UTF16) 267 template <> 268 struct ParamTraits<base::string16> { 269 typedef base::string16 param_type; 270 static void Write(Message* m, const param_type& p) { 271 m->WriteString16(p); 272 } 273 static bool Read(const Message* m, PickleIterator* iter, 274 param_type* r) { 275 return m->ReadString16(iter, r); 276 } 277 IPC_EXPORT static void Log(const param_type& p, std::string* l); 278 }; 279 #endif 280 281 template <> 282 struct IPC_EXPORT ParamTraits<std::vector<char> > { 283 typedef std::vector<char> param_type; 284 static void Write(Message* m, const param_type& p); 285 static bool Read(const Message*, PickleIterator* iter, param_type* r); 286 static void Log(const param_type& p, std::string* l); 287 }; 288 289 template <> 290 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > { 291 typedef std::vector<unsigned char> param_type; 292 static void Write(Message* m, const param_type& p); 293 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 294 static void Log(const param_type& p, std::string* l); 295 }; 296 297 template <> 298 struct IPC_EXPORT ParamTraits<std::vector<bool> > { 299 typedef std::vector<bool> param_type; 300 static void Write(Message* m, const param_type& p); 301 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 302 static void Log(const param_type& p, std::string* l); 303 }; 304 305 template <class P> 306 struct ParamTraits<std::vector<P> > { 307 typedef std::vector<P> param_type; 308 static void Write(Message* m, const param_type& p) { 309 WriteParam(m, static_cast<int>(p.size())); 310 for (size_t i = 0; i < p.size(); i++) 311 WriteParam(m, p[i]); 312 } 313 static bool Read(const Message* m, PickleIterator* iter, 314 param_type* r) { 315 int size; 316 // ReadLength() checks for < 0 itself. 317 if (!m->ReadLength(iter, &size)) 318 return false; 319 // Resizing beforehand is not safe, see BUG 1006367 for details. 320 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size)) 321 return false; 322 r->resize(size); 323 for (int i = 0; i < size; i++) { 324 if (!ReadParam(m, iter, &(*r)[i])) 325 return false; 326 } 327 return true; 328 } 329 static void Log(const param_type& p, std::string* l) { 330 for (size_t i = 0; i < p.size(); ++i) { 331 if (i != 0) 332 l->append(" "); 333 LogParam((p[i]), l); 334 } 335 } 336 }; 337 338 template <class P> 339 struct ParamTraits<std::set<P> > { 340 typedef std::set<P> param_type; 341 static void Write(Message* m, const param_type& p) { 342 WriteParam(m, static_cast<int>(p.size())); 343 typename param_type::const_iterator iter; 344 for (iter = p.begin(); iter != p.end(); ++iter) 345 WriteParam(m, *iter); 346 } 347 static bool Read(const Message* m, PickleIterator* iter, 348 param_type* r) { 349 int size; 350 if (!m->ReadLength(iter, &size)) 351 return false; 352 for (int i = 0; i < size; ++i) { 353 P item; 354 if (!ReadParam(m, iter, &item)) 355 return false; 356 r->insert(item); 357 } 358 return true; 359 } 360 static void Log(const param_type& p, std::string* l) { 361 l->append("<std::set>"); 362 } 363 }; 364 365 template <class K, class V> 366 struct ParamTraits<std::map<K, V> > { 367 typedef std::map<K, V> param_type; 368 static void Write(Message* m, const param_type& p) { 369 WriteParam(m, static_cast<int>(p.size())); 370 typename param_type::const_iterator iter; 371 for (iter = p.begin(); iter != p.end(); ++iter) { 372 WriteParam(m, iter->first); 373 WriteParam(m, iter->second); 374 } 375 } 376 static bool Read(const Message* m, PickleIterator* iter, 377 param_type* r) { 378 int size; 379 if (!ReadParam(m, iter, &size) || size < 0) 380 return false; 381 for (int i = 0; i < size; ++i) { 382 K k; 383 if (!ReadParam(m, iter, &k)) 384 return false; 385 V& value = (*r)[k]; 386 if (!ReadParam(m, iter, &value)) 387 return false; 388 } 389 return true; 390 } 391 static void Log(const param_type& p, std::string* l) { 392 l->append("<std::map>"); 393 } 394 }; 395 396 template <class A, class B> 397 struct ParamTraits<std::pair<A, B> > { 398 typedef std::pair<A, B> param_type; 399 static void Write(Message* m, const param_type& p) { 400 WriteParam(m, p.first); 401 WriteParam(m, p.second); 402 } 403 static bool Read(const Message* m, PickleIterator* iter, 404 param_type* r) { 405 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second); 406 } 407 static void Log(const param_type& p, std::string* l) { 408 l->append("("); 409 LogParam(p.first, l); 410 l->append(", "); 411 LogParam(p.second, l); 412 l->append(")"); 413 } 414 }; 415 416 // Base ParamTraits ------------------------------------------------------------ 417 418 template <> 419 struct IPC_EXPORT ParamTraits<base::DictionaryValue> { 420 typedef base::DictionaryValue param_type; 421 static void Write(Message* m, const param_type& p); 422 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 423 static void Log(const param_type& p, std::string* l); 424 }; 425 426 #if defined(OS_POSIX) 427 // FileDescriptors may be serialised over IPC channels on POSIX. On the 428 // receiving side, the FileDescriptor is a valid duplicate of the file 429 // descriptor which was transmitted: *it is not just a copy of the integer like 430 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In 431 // this case, the receiving end will see a value of -1. *Zero is a valid file 432 // descriptor*. 433 // 434 // The received file descriptor will have the |auto_close| flag set to true. The 435 // code which handles the message is responsible for taking ownership of it. 436 // File descriptors are OS resources and must be closed when no longer needed. 437 // 438 // When sending a file descriptor, the file descriptor must be valid at the time 439 // of transmission. Since transmission is not synchronous, one should consider 440 // dup()ing any file descriptors to be transmitted and setting the |auto_close| 441 // flag, which causes the file descriptor to be closed after writing. 442 template<> 443 struct IPC_EXPORT ParamTraits<base::FileDescriptor> { 444 typedef base::FileDescriptor param_type; 445 static void Write(Message* m, const param_type& p); 446 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 447 static void Log(const param_type& p, std::string* l); 448 }; 449 #endif // defined(OS_POSIX) 450 451 template <> 452 struct IPC_EXPORT ParamTraits<base::FilePath> { 453 typedef base::FilePath param_type; 454 static void Write(Message* m, const param_type& p); 455 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 456 static void Log(const param_type& p, std::string* l); 457 }; 458 459 template <> 460 struct IPC_EXPORT ParamTraits<base::ListValue> { 461 typedef base::ListValue param_type; 462 static void Write(Message* m, const param_type& p); 463 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 464 static void Log(const param_type& p, std::string* l); 465 }; 466 467 template <> 468 struct IPC_EXPORT ParamTraits<base::NullableString16> { 469 typedef base::NullableString16 param_type; 470 static void Write(Message* m, const param_type& p); 471 static bool Read(const Message* m, PickleIterator* iter, 472 param_type* r); 473 static void Log(const param_type& p, std::string* l); 474 }; 475 476 template <> 477 struct IPC_EXPORT ParamTraits<base::PlatformFileInfo> { 478 typedef base::PlatformFileInfo param_type; 479 static void Write(Message* m, const param_type& p); 480 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 481 static void Log(const param_type& p, std::string* l); 482 }; 483 484 template <> 485 struct SimilarTypeTraits<base::PlatformFileError> { 486 typedef int Type; 487 }; 488 489 #if defined(OS_WIN) 490 template <> 491 struct SimilarTypeTraits<HWND> { 492 typedef HANDLE Type; 493 }; 494 #endif // defined(OS_WIN) 495 496 template <> 497 struct IPC_EXPORT ParamTraits<base::Time> { 498 typedef base::Time param_type; 499 static void Write(Message* m, const param_type& p); 500 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 501 static void Log(const param_type& p, std::string* l); 502 }; 503 504 template <> 505 struct IPC_EXPORT ParamTraits<base::TimeDelta> { 506 typedef base::TimeDelta param_type; 507 static void Write(Message* m, const param_type& p); 508 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 509 static void Log(const param_type& p, std::string* l); 510 }; 511 512 template <> 513 struct IPC_EXPORT ParamTraits<base::TimeTicks> { 514 typedef base::TimeTicks param_type; 515 static void Write(Message* m, const param_type& p); 516 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 517 static void Log(const param_type& p, std::string* l); 518 }; 519 520 template <> 521 struct ParamTraits<Tuple0> { 522 typedef Tuple0 param_type; 523 static void Write(Message* m, const param_type& p) { 524 } 525 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 526 return true; 527 } 528 static void Log(const param_type& p, std::string* l) { 529 } 530 }; 531 532 template <class A> 533 struct ParamTraits< Tuple1<A> > { 534 typedef Tuple1<A> param_type; 535 static void Write(Message* m, const param_type& p) { 536 WriteParam(m, p.a); 537 } 538 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 539 return ReadParam(m, iter, &r->a); 540 } 541 static void Log(const param_type& p, std::string* l) { 542 LogParam(p.a, l); 543 } 544 }; 545 546 template <class A, class B> 547 struct ParamTraits< Tuple2<A, B> > { 548 typedef Tuple2<A, B> param_type; 549 static void Write(Message* m, const param_type& p) { 550 WriteParam(m, p.a); 551 WriteParam(m, p.b); 552 } 553 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 554 return (ReadParam(m, iter, &r->a) && 555 ReadParam(m, iter, &r->b)); 556 } 557 static void Log(const param_type& p, std::string* l) { 558 LogParam(p.a, l); 559 l->append(", "); 560 LogParam(p.b, l); 561 } 562 }; 563 564 template <class A, class B, class C> 565 struct ParamTraits< Tuple3<A, B, C> > { 566 typedef Tuple3<A, B, C> param_type; 567 static void Write(Message* m, const param_type& p) { 568 WriteParam(m, p.a); 569 WriteParam(m, p.b); 570 WriteParam(m, p.c); 571 } 572 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 573 return (ReadParam(m, iter, &r->a) && 574 ReadParam(m, iter, &r->b) && 575 ReadParam(m, iter, &r->c)); 576 } 577 static void Log(const param_type& p, std::string* l) { 578 LogParam(p.a, l); 579 l->append(", "); 580 LogParam(p.b, l); 581 l->append(", "); 582 LogParam(p.c, l); 583 } 584 }; 585 586 template <class A, class B, class C, class D> 587 struct ParamTraits< Tuple4<A, B, C, D> > { 588 typedef Tuple4<A, B, C, D> param_type; 589 static void Write(Message* m, const param_type& p) { 590 WriteParam(m, p.a); 591 WriteParam(m, p.b); 592 WriteParam(m, p.c); 593 WriteParam(m, p.d); 594 } 595 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 596 return (ReadParam(m, iter, &r->a) && 597 ReadParam(m, iter, &r->b) && 598 ReadParam(m, iter, &r->c) && 599 ReadParam(m, iter, &r->d)); 600 } 601 static void Log(const param_type& p, std::string* l) { 602 LogParam(p.a, l); 603 l->append(", "); 604 LogParam(p.b, l); 605 l->append(", "); 606 LogParam(p.c, l); 607 l->append(", "); 608 LogParam(p.d, l); 609 } 610 }; 611 612 template <class A, class B, class C, class D, class E> 613 struct ParamTraits< Tuple5<A, B, C, D, E> > { 614 typedef Tuple5<A, B, C, D, E> param_type; 615 static void Write(Message* m, const param_type& p) { 616 WriteParam(m, p.a); 617 WriteParam(m, p.b); 618 WriteParam(m, p.c); 619 WriteParam(m, p.d); 620 WriteParam(m, p.e); 621 } 622 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 623 return (ReadParam(m, iter, &r->a) && 624 ReadParam(m, iter, &r->b) && 625 ReadParam(m, iter, &r->c) && 626 ReadParam(m, iter, &r->d) && 627 ReadParam(m, iter, &r->e)); 628 } 629 static void Log(const param_type& p, std::string* l) { 630 LogParam(p.a, l); 631 l->append(", "); 632 LogParam(p.b, l); 633 l->append(", "); 634 LogParam(p.c, l); 635 l->append(", "); 636 LogParam(p.d, l); 637 l->append(", "); 638 LogParam(p.e, l); 639 } 640 }; 641 642 template<class P> 643 struct ParamTraits<ScopedVector<P> > { 644 typedef ScopedVector<P> param_type; 645 static void Write(Message* m, const param_type& p) { 646 WriteParam(m, static_cast<int>(p.size())); 647 for (size_t i = 0; i < p.size(); i++) 648 WriteParam(m, *p[i]); 649 } 650 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 651 int size = 0; 652 if (!m->ReadLength(iter, &size)) 653 return false; 654 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size)) 655 return false; 656 r->resize(size); 657 for (int i = 0; i < size; i++) { 658 (*r)[i] = new P(); 659 if (!ReadParam(m, iter, (*r)[i])) 660 return false; 661 } 662 return true; 663 } 664 static void Log(const param_type& p, std::string* l) { 665 for (size_t i = 0; i < p.size(); ++i) { 666 if (i != 0) 667 l->append(" "); 668 LogParam(*p[i], l); 669 } 670 } 671 }; 672 673 // IPC types ParamTraits ------------------------------------------------------- 674 675 // A ChannelHandle is basically a platform-inspecific wrapper around the 676 // fact that IPC endpoints are handled specially on POSIX. See above comments 677 // on FileDescriptor for more background. 678 template<> 679 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> { 680 typedef ChannelHandle param_type; 681 static void Write(Message* m, const param_type& p); 682 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 683 static void Log(const param_type& p, std::string* l); 684 }; 685 686 template <> 687 struct IPC_EXPORT ParamTraits<LogData> { 688 typedef LogData param_type; 689 static void Write(Message* m, const param_type& p); 690 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 691 static void Log(const param_type& p, std::string* l); 692 }; 693 694 template <> 695 struct IPC_EXPORT ParamTraits<Message> { 696 static void Write(Message* m, const Message& p); 697 static bool Read(const Message* m, PickleIterator* iter, Message* r); 698 static void Log(const Message& p, std::string* l); 699 }; 700 701 // Windows ParamTraits --------------------------------------------------------- 702 703 #if defined(OS_WIN) 704 template <> 705 struct IPC_EXPORT ParamTraits<HANDLE> { 706 typedef HANDLE param_type; 707 static void Write(Message* m, const param_type& p); 708 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 709 static void Log(const param_type& p, std::string* l); 710 }; 711 712 template <> 713 struct IPC_EXPORT ParamTraits<LOGFONT> { 714 typedef LOGFONT param_type; 715 static void Write(Message* m, const param_type& p); 716 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 717 static void Log(const param_type& p, std::string* l); 718 }; 719 720 template <> 721 struct IPC_EXPORT ParamTraits<MSG> { 722 typedef MSG param_type; 723 static void Write(Message* m, const param_type& p); 724 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 725 static void Log(const param_type& p, std::string* l); 726 }; 727 #endif // defined(OS_WIN) 728 729 //----------------------------------------------------------------------------- 730 // Generic message subclasses 731 732 // Used for asynchronous messages. 733 template <class ParamType> 734 class MessageSchema { 735 public: 736 typedef ParamType Param; 737 typedef typename TupleTypes<ParamType>::ParamTuple RefParam; 738 739 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE; 740 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE; 741 }; 742 743 // defined in ipc_logging.cc 744 IPC_EXPORT void GenerateLogData(const std::string& channel, 745 const Message& message, 746 LogData* data, bool get_params); 747 748 749 #if defined(IPC_MESSAGE_LOG_ENABLED) 750 inline void AddOutputParamsToLog(const Message* msg, std::string* l) { 751 const std::string& output_params = msg->output_params(); 752 if (!l->empty() && !output_params.empty()) 753 l->append(", "); 754 755 l->append(output_params); 756 } 757 758 template <class ReplyParamType> 759 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, 760 const Message* msg) { 761 if (msg->received_time() != 0) { 762 std::string output_params; 763 LogParam(reply_params, &output_params); 764 msg->set_output_params(output_params); 765 } 766 } 767 768 inline void ConnectMessageAndReply(const Message* msg, Message* reply) { 769 if (msg->sent_time()) { 770 // Don't log the sync message after dispatch, as we don't have the 771 // output parameters at that point. Instead, save its data and log it 772 // with the outgoing reply message when it's sent. 773 LogData* data = new LogData; 774 GenerateLogData("", *msg, data, true); 775 msg->set_dont_log(); 776 reply->set_sync_log_data(data); 777 } 778 } 779 #else 780 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {} 781 782 template <class ReplyParamType> 783 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, 784 const Message* msg) {} 785 786 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {} 787 #endif 788 789 // This class assumes that its template argument is a RefTuple (a Tuple with 790 // reference elements). This would go into ipc_message_utils_impl.h, but it is 791 // also used by chrome_frame. 792 template <class RefTuple> 793 class ParamDeserializer : public MessageReplyDeserializer { 794 public: 795 explicit ParamDeserializer(const RefTuple& out) : out_(out) { } 796 797 bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) { 798 return ReadParam(&msg, &iter, &out_); 799 } 800 801 RefTuple out_; 802 }; 803 804 // Used for synchronous messages. 805 template <class SendParamType, class ReplyParamType> 806 class SyncMessageSchema { 807 public: 808 typedef SendParamType SendParam; 809 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam; 810 typedef ReplyParamType ReplyParam; 811 812 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE; 813 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE; 814 static bool ReadReplyParam( 815 const Message* msg, 816 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE; 817 818 template<class T, class S, class Method> 819 static bool DispatchWithSendParams(bool ok, const SendParam& send_params, 820 const Message* msg, T* obj, S* sender, 821 Method func) { 822 Message* reply = SyncMessage::GenerateReply(msg); 823 if (ok) { 824 typename TupleTypes<ReplyParam>::ValueTuple reply_params; 825 DispatchToMethod(obj, func, send_params, &reply_params); 826 WriteParam(reply, reply_params); 827 LogReplyParamsToMessage(reply_params, msg); 828 } else { 829 NOTREACHED() << "Error deserializing message " << msg->type(); 830 reply->set_reply_error(); 831 } 832 sender->Send(reply); 833 return ok; 834 } 835 836 template<class T, class Method> 837 static bool DispatchDelayReplyWithSendParams(bool ok, 838 const SendParam& send_params, 839 const Message* msg, T* obj, 840 Method func) { 841 Message* reply = SyncMessage::GenerateReply(msg); 842 if (ok) { 843 Tuple1<Message&> t = MakeRefTuple(*reply); 844 ConnectMessageAndReply(msg, reply); 845 DispatchToMethod(obj, func, send_params, &t); 846 } else { 847 NOTREACHED() << "Error deserializing message " << msg->type(); 848 reply->set_reply_error(); 849 obj->Send(reply); 850 } 851 return ok; 852 } 853 854 template<typename TA> 855 static void WriteReplyParams(Message* reply, TA a) { 856 ReplyParam p(a); 857 WriteParam(reply, p); 858 } 859 860 template<typename TA, typename TB> 861 static void WriteReplyParams(Message* reply, TA a, TB b) { 862 ReplyParam p(a, b); 863 WriteParam(reply, p); 864 } 865 866 template<typename TA, typename TB, typename TC> 867 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) { 868 ReplyParam p(a, b, c); 869 WriteParam(reply, p); 870 } 871 872 template<typename TA, typename TB, typename TC, typename TD> 873 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) { 874 ReplyParam p(a, b, c, d); 875 WriteParam(reply, p); 876 } 877 878 template<typename TA, typename TB, typename TC, typename TD, typename TE> 879 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) { 880 ReplyParam p(a, b, c, d, e); 881 WriteParam(reply, p); 882 } 883 }; 884 885 } // namespace IPC 886 887 #endif // IPC_IPC_MESSAGE_UTILS_H_ 888