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 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 221 static void Log(const param_type& p, std::string* l); 222 }; 223 224 template <> 225 struct IPC_EXPORT ParamTraits<double> { 226 typedef double param_type; 227 static void Write(Message* m, const param_type& p); 228 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 229 static void Log(const param_type& p, std::string* l); 230 }; 231 232 // STL ParamTraits ------------------------------------------------------------- 233 234 template <> 235 struct ParamTraits<std::string> { 236 typedef std::string param_type; 237 static void Write(Message* m, const param_type& p) { 238 m->WriteString(p); 239 } 240 static bool Read(const Message* m, PickleIterator* iter, 241 param_type* r) { 242 return m->ReadString(iter, r); 243 } 244 IPC_EXPORT static void Log(const param_type& p, std::string* l); 245 }; 246 247 template <> 248 struct ParamTraits<std::wstring> { 249 typedef std::wstring param_type; 250 static void Write(Message* m, const param_type& p) { 251 m->WriteWString(p); 252 } 253 static bool Read(const Message* m, PickleIterator* iter, 254 param_type* r) { 255 return m->ReadWString(iter, r); 256 } 257 IPC_EXPORT static void Log(const param_type& p, std::string* l); 258 }; 259 260 // If WCHAR_T_IS_UTF16 is defined, then string16 is a std::wstring so we don't 261 // need this trait. 262 #if !defined(WCHAR_T_IS_UTF16) 263 template <> 264 struct ParamTraits<string16> { 265 typedef string16 param_type; 266 static void Write(Message* m, const param_type& p) { 267 m->WriteString16(p); 268 } 269 static bool Read(const Message* m, PickleIterator* iter, 270 param_type* r) { 271 return m->ReadString16(iter, r); 272 } 273 IPC_EXPORT static void Log(const param_type& p, std::string* l); 274 }; 275 #endif 276 277 template <> 278 struct IPC_EXPORT ParamTraits<std::vector<char> > { 279 typedef std::vector<char> param_type; 280 static void Write(Message* m, const param_type& p); 281 static bool Read(const Message*, PickleIterator* iter, param_type* r); 282 static void Log(const param_type& p, std::string* l); 283 }; 284 285 template <> 286 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > { 287 typedef std::vector<unsigned char> param_type; 288 static void Write(Message* m, const param_type& p); 289 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 290 static void Log(const param_type& p, std::string* l); 291 }; 292 293 template <> 294 struct IPC_EXPORT ParamTraits<std::vector<bool> > { 295 typedef std::vector<bool> param_type; 296 static void Write(Message* m, const param_type& p); 297 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 298 static void Log(const param_type& p, std::string* l); 299 }; 300 301 template <class P> 302 struct ParamTraits<std::vector<P> > { 303 typedef std::vector<P> param_type; 304 static void Write(Message* m, const param_type& p) { 305 WriteParam(m, static_cast<int>(p.size())); 306 for (size_t i = 0; i < p.size(); i++) 307 WriteParam(m, p[i]); 308 } 309 static bool Read(const Message* m, PickleIterator* iter, 310 param_type* r) { 311 int size; 312 // ReadLength() checks for < 0 itself. 313 if (!m->ReadLength(iter, &size)) 314 return false; 315 // Resizing beforehand is not safe, see BUG 1006367 for details. 316 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size)) 317 return false; 318 r->resize(size); 319 for (int i = 0; i < size; i++) { 320 if (!ReadParam(m, iter, &(*r)[i])) 321 return false; 322 } 323 return true; 324 } 325 static void Log(const param_type& p, std::string* l) { 326 for (size_t i = 0; i < p.size(); ++i) { 327 if (i != 0) 328 l->append(" "); 329 LogParam((p[i]), l); 330 } 331 } 332 }; 333 334 template <class P> 335 struct ParamTraits<std::set<P> > { 336 typedef std::set<P> param_type; 337 static void Write(Message* m, const param_type& p) { 338 WriteParam(m, static_cast<int>(p.size())); 339 typename param_type::const_iterator iter; 340 for (iter = p.begin(); iter != p.end(); ++iter) 341 WriteParam(m, *iter); 342 } 343 static bool Read(const Message* m, PickleIterator* iter, 344 param_type* r) { 345 int size; 346 if (!m->ReadLength(iter, &size)) 347 return false; 348 for (int i = 0; i < size; ++i) { 349 P item; 350 if (!ReadParam(m, iter, &item)) 351 return false; 352 r->insert(item); 353 } 354 return true; 355 } 356 static void Log(const param_type& p, std::string* l) { 357 l->append("<std::set>"); 358 } 359 }; 360 361 template <class K, class V> 362 struct ParamTraits<std::map<K, V> > { 363 typedef std::map<K, V> param_type; 364 static void Write(Message* m, const param_type& p) { 365 WriteParam(m, static_cast<int>(p.size())); 366 typename param_type::const_iterator iter; 367 for (iter = p.begin(); iter != p.end(); ++iter) { 368 WriteParam(m, iter->first); 369 WriteParam(m, iter->second); 370 } 371 } 372 static bool Read(const Message* m, PickleIterator* iter, 373 param_type* r) { 374 int size; 375 if (!ReadParam(m, iter, &size) || size < 0) 376 return false; 377 for (int i = 0; i < size; ++i) { 378 K k; 379 if (!ReadParam(m, iter, &k)) 380 return false; 381 V& value = (*r)[k]; 382 if (!ReadParam(m, iter, &value)) 383 return false; 384 } 385 return true; 386 } 387 static void Log(const param_type& p, std::string* l) { 388 l->append("<std::map>"); 389 } 390 }; 391 392 template <class A, class B> 393 struct ParamTraits<std::pair<A, B> > { 394 typedef std::pair<A, B> param_type; 395 static void Write(Message* m, const param_type& p) { 396 WriteParam(m, p.first); 397 WriteParam(m, p.second); 398 } 399 static bool Read(const Message* m, PickleIterator* iter, 400 param_type* r) { 401 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second); 402 } 403 static void Log(const param_type& p, std::string* l) { 404 l->append("("); 405 LogParam(p.first, l); 406 l->append(", "); 407 LogParam(p.second, l); 408 l->append(")"); 409 } 410 }; 411 412 // Base ParamTraits ------------------------------------------------------------ 413 414 template <> 415 struct IPC_EXPORT ParamTraits<base::DictionaryValue> { 416 typedef base::DictionaryValue param_type; 417 static void Write(Message* m, const param_type& p); 418 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 419 static void Log(const param_type& p, std::string* l); 420 }; 421 422 #if defined(OS_POSIX) 423 // FileDescriptors may be serialised over IPC channels on POSIX. On the 424 // receiving side, the FileDescriptor is a valid duplicate of the file 425 // descriptor which was transmitted: *it is not just a copy of the integer like 426 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In 427 // this case, the receiving end will see a value of -1. *Zero is a valid file 428 // descriptor*. 429 // 430 // The received file descriptor will have the |auto_close| flag set to true. The 431 // code which handles the message is responsible for taking ownership of it. 432 // File descriptors are OS resources and must be closed when no longer needed. 433 // 434 // When sending a file descriptor, the file descriptor must be valid at the time 435 // of transmission. Since transmission is not synchronous, one should consider 436 // dup()ing any file descriptors to be transmitted and setting the |auto_close| 437 // flag, which causes the file descriptor to be closed after writing. 438 template<> 439 struct IPC_EXPORT ParamTraits<base::FileDescriptor> { 440 typedef base::FileDescriptor param_type; 441 static void Write(Message* m, const param_type& p); 442 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 443 static void Log(const param_type& p, std::string* l); 444 }; 445 #endif // defined(OS_POSIX) 446 447 template <> 448 struct IPC_EXPORT ParamTraits<base::FilePath> { 449 typedef base::FilePath param_type; 450 static void Write(Message* m, const param_type& p); 451 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 452 static void Log(const param_type& p, std::string* l); 453 }; 454 455 template <> 456 struct IPC_EXPORT ParamTraits<base::ListValue> { 457 typedef base::ListValue param_type; 458 static void Write(Message* m, const param_type& p); 459 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 460 static void Log(const param_type& p, std::string* l); 461 }; 462 463 template <> 464 struct IPC_EXPORT ParamTraits<base::NullableString16> { 465 typedef base::NullableString16 param_type; 466 static void Write(Message* m, const param_type& p); 467 static bool Read(const Message* m, PickleIterator* iter, 468 param_type* r); 469 static void Log(const param_type& p, std::string* l); 470 }; 471 472 template <> 473 struct IPC_EXPORT ParamTraits<base::PlatformFileInfo> { 474 typedef base::PlatformFileInfo param_type; 475 static void Write(Message* m, const param_type& p); 476 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 477 static void Log(const param_type& p, std::string* l); 478 }; 479 480 template <> 481 struct SimilarTypeTraits<base::PlatformFileError> { 482 typedef int Type; 483 }; 484 485 #if defined(OS_WIN) 486 template <> 487 struct SimilarTypeTraits<HWND> { 488 typedef HANDLE Type; 489 }; 490 #endif // defined(OS_WIN) 491 492 template <> 493 struct IPC_EXPORT ParamTraits<base::Time> { 494 typedef base::Time param_type; 495 static void Write(Message* m, const param_type& p); 496 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 497 static void Log(const param_type& p, std::string* l); 498 }; 499 500 template <> 501 struct IPC_EXPORT ParamTraits<base::TimeDelta> { 502 typedef base::TimeDelta param_type; 503 static void Write(Message* m, const param_type& p); 504 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 505 static void Log(const param_type& p, std::string* l); 506 }; 507 508 template <> 509 struct IPC_EXPORT ParamTraits<base::TimeTicks> { 510 typedef base::TimeTicks param_type; 511 static void Write(Message* m, const param_type& p); 512 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 513 static void Log(const param_type& p, std::string* l); 514 }; 515 516 template <> 517 struct ParamTraits<Tuple0> { 518 typedef Tuple0 param_type; 519 static void Write(Message* m, const param_type& p) { 520 } 521 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 522 return true; 523 } 524 static void Log(const param_type& p, std::string* l) { 525 } 526 }; 527 528 template <class A> 529 struct ParamTraits< Tuple1<A> > { 530 typedef Tuple1<A> param_type; 531 static void Write(Message* m, const param_type& p) { 532 WriteParam(m, p.a); 533 } 534 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 535 return ReadParam(m, iter, &r->a); 536 } 537 static void Log(const param_type& p, std::string* l) { 538 LogParam(p.a, l); 539 } 540 }; 541 542 template <class A, class B> 543 struct ParamTraits< Tuple2<A, B> > { 544 typedef Tuple2<A, B> param_type; 545 static void Write(Message* m, const param_type& p) { 546 WriteParam(m, p.a); 547 WriteParam(m, p.b); 548 } 549 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 550 return (ReadParam(m, iter, &r->a) && 551 ReadParam(m, iter, &r->b)); 552 } 553 static void Log(const param_type& p, std::string* l) { 554 LogParam(p.a, l); 555 l->append(", "); 556 LogParam(p.b, l); 557 } 558 }; 559 560 template <class A, class B, class C> 561 struct ParamTraits< Tuple3<A, B, C> > { 562 typedef Tuple3<A, B, C> param_type; 563 static void Write(Message* m, const param_type& p) { 564 WriteParam(m, p.a); 565 WriteParam(m, p.b); 566 WriteParam(m, p.c); 567 } 568 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 569 return (ReadParam(m, iter, &r->a) && 570 ReadParam(m, iter, &r->b) && 571 ReadParam(m, iter, &r->c)); 572 } 573 static void Log(const param_type& p, std::string* l) { 574 LogParam(p.a, l); 575 l->append(", "); 576 LogParam(p.b, l); 577 l->append(", "); 578 LogParam(p.c, l); 579 } 580 }; 581 582 template <class A, class B, class C, class D> 583 struct ParamTraits< Tuple4<A, B, C, D> > { 584 typedef Tuple4<A, B, C, D> param_type; 585 static void Write(Message* m, const param_type& p) { 586 WriteParam(m, p.a); 587 WriteParam(m, p.b); 588 WriteParam(m, p.c); 589 WriteParam(m, p.d); 590 } 591 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 592 return (ReadParam(m, iter, &r->a) && 593 ReadParam(m, iter, &r->b) && 594 ReadParam(m, iter, &r->c) && 595 ReadParam(m, iter, &r->d)); 596 } 597 static void Log(const param_type& p, std::string* l) { 598 LogParam(p.a, l); 599 l->append(", "); 600 LogParam(p.b, l); 601 l->append(", "); 602 LogParam(p.c, l); 603 l->append(", "); 604 LogParam(p.d, l); 605 } 606 }; 607 608 template <class A, class B, class C, class D, class E> 609 struct ParamTraits< Tuple5<A, B, C, D, E> > { 610 typedef Tuple5<A, B, C, D, E> param_type; 611 static void Write(Message* m, const param_type& p) { 612 WriteParam(m, p.a); 613 WriteParam(m, p.b); 614 WriteParam(m, p.c); 615 WriteParam(m, p.d); 616 WriteParam(m, p.e); 617 } 618 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 619 return (ReadParam(m, iter, &r->a) && 620 ReadParam(m, iter, &r->b) && 621 ReadParam(m, iter, &r->c) && 622 ReadParam(m, iter, &r->d) && 623 ReadParam(m, iter, &r->e)); 624 } 625 static void Log(const param_type& p, std::string* l) { 626 LogParam(p.a, l); 627 l->append(", "); 628 LogParam(p.b, l); 629 l->append(", "); 630 LogParam(p.c, l); 631 l->append(", "); 632 LogParam(p.d, l); 633 l->append(", "); 634 LogParam(p.e, l); 635 } 636 }; 637 638 template<class P> 639 struct ParamTraits<ScopedVector<P> > { 640 typedef ScopedVector<P> param_type; 641 static void Write(Message* m, const param_type& p) { 642 WriteParam(m, static_cast<int>(p.size())); 643 for (size_t i = 0; i < p.size(); i++) 644 WriteParam(m, *p[i]); 645 } 646 static bool Read(const Message* m, PickleIterator* iter, param_type* r) { 647 int size = 0; 648 if (!m->ReadLength(iter, &size)) 649 return false; 650 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size)) 651 return false; 652 r->resize(size); 653 for (int i = 0; i < size; i++) { 654 (*r)[i] = new P(); 655 if (!ReadParam(m, iter, (*r)[i])) 656 return false; 657 } 658 return true; 659 } 660 static void Log(const param_type& p, std::string* l) { 661 for (size_t i = 0; i < p.size(); ++i) { 662 if (i != 0) 663 l->append(" "); 664 LogParam(*p[i], l); 665 } 666 } 667 }; 668 669 // IPC types ParamTraits ------------------------------------------------------- 670 671 // A ChannelHandle is basically a platform-inspecific wrapper around the 672 // fact that IPC endpoints are handled specially on POSIX. See above comments 673 // on FileDescriptor for more background. 674 template<> 675 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> { 676 typedef ChannelHandle param_type; 677 static void Write(Message* m, const param_type& p); 678 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 679 static void Log(const param_type& p, std::string* l); 680 }; 681 682 template <> 683 struct IPC_EXPORT ParamTraits<LogData> { 684 typedef LogData param_type; 685 static void Write(Message* m, const param_type& p); 686 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 687 static void Log(const param_type& p, std::string* l); 688 }; 689 690 template <> 691 struct IPC_EXPORT ParamTraits<Message> { 692 static void Write(Message* m, const Message& p); 693 static bool Read(const Message* m, PickleIterator* iter, Message* r); 694 static void Log(const Message& p, std::string* l); 695 }; 696 697 // Windows ParamTraits --------------------------------------------------------- 698 699 #if defined(OS_WIN) 700 template <> 701 struct IPC_EXPORT ParamTraits<HANDLE> { 702 typedef HANDLE param_type; 703 static void Write(Message* m, const param_type& p); 704 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 705 static void Log(const param_type& p, std::string* l); 706 }; 707 708 template <> 709 struct IPC_EXPORT ParamTraits<LOGFONT> { 710 typedef LOGFONT param_type; 711 static void Write(Message* m, const param_type& p); 712 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 713 static void Log(const param_type& p, std::string* l); 714 }; 715 716 template <> 717 struct IPC_EXPORT ParamTraits<MSG> { 718 typedef MSG param_type; 719 static void Write(Message* m, const param_type& p); 720 static bool Read(const Message* m, PickleIterator* iter, param_type* r); 721 static void Log(const param_type& p, std::string* l); 722 }; 723 #endif // defined(OS_WIN) 724 725 //----------------------------------------------------------------------------- 726 // Generic message subclasses 727 728 // Used for asynchronous messages. 729 template <class ParamType> 730 class MessageSchema { 731 public: 732 typedef ParamType Param; 733 typedef typename TupleTypes<ParamType>::ParamTuple RefParam; 734 735 static void Write(Message* msg, const RefParam& p) IPC_MSG_NOINLINE; 736 static bool Read(const Message* msg, Param* p) IPC_MSG_NOINLINE; 737 }; 738 739 // defined in ipc_logging.cc 740 IPC_EXPORT void GenerateLogData(const std::string& channel, 741 const Message& message, 742 LogData* data, bool get_params); 743 744 745 #if defined(IPC_MESSAGE_LOG_ENABLED) 746 inline void AddOutputParamsToLog(const Message* msg, std::string* l) { 747 const std::string& output_params = msg->output_params(); 748 if (!l->empty() && !output_params.empty()) 749 l->append(", "); 750 751 l->append(output_params); 752 } 753 754 template <class ReplyParamType> 755 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, 756 const Message* msg) { 757 if (msg->received_time() != 0) { 758 std::string output_params; 759 LogParam(reply_params, &output_params); 760 msg->set_output_params(output_params); 761 } 762 } 763 764 inline void ConnectMessageAndReply(const Message* msg, Message* reply) { 765 if (msg->sent_time()) { 766 // Don't log the sync message after dispatch, as we don't have the 767 // output parameters at that point. Instead, save its data and log it 768 // with the outgoing reply message when it's sent. 769 LogData* data = new LogData; 770 GenerateLogData("", *msg, data, true); 771 msg->set_dont_log(); 772 reply->set_sync_log_data(data); 773 } 774 } 775 #else 776 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {} 777 778 template <class ReplyParamType> 779 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, 780 const Message* msg) {} 781 782 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {} 783 #endif 784 785 // This class assumes that its template argument is a RefTuple (a Tuple with 786 // reference elements). This would go into ipc_message_utils_impl.h, but it is 787 // also used by chrome_frame. 788 template <class RefTuple> 789 class ParamDeserializer : public MessageReplyDeserializer { 790 public: 791 explicit ParamDeserializer(const RefTuple& out) : out_(out) { } 792 793 bool SerializeOutputParameters(const IPC::Message& msg, PickleIterator iter) { 794 return ReadParam(&msg, &iter, &out_); 795 } 796 797 RefTuple out_; 798 }; 799 800 // Used for synchronous messages. 801 template <class SendParamType, class ReplyParamType> 802 class SyncMessageSchema { 803 public: 804 typedef SendParamType SendParam; 805 typedef typename TupleTypes<SendParam>::ParamTuple RefSendParam; 806 typedef ReplyParamType ReplyParam; 807 808 static void Write(Message* msg, const RefSendParam& send) IPC_MSG_NOINLINE; 809 static bool ReadSendParam(const Message* msg, SendParam* p) IPC_MSG_NOINLINE; 810 static bool ReadReplyParam( 811 const Message* msg, 812 typename TupleTypes<ReplyParam>::ValueTuple* p) IPC_MSG_NOINLINE; 813 814 template<class T, class S, class Method> 815 static bool DispatchWithSendParams(bool ok, const SendParam& send_params, 816 const Message* msg, T* obj, S* sender, 817 Method func) { 818 Message* reply = SyncMessage::GenerateReply(msg); 819 if (ok) { 820 typename TupleTypes<ReplyParam>::ValueTuple reply_params; 821 DispatchToMethod(obj, func, send_params, &reply_params); 822 WriteParam(reply, reply_params); 823 LogReplyParamsToMessage(reply_params, msg); 824 } else { 825 NOTREACHED() << "Error deserializing message " << msg->type(); 826 reply->set_reply_error(); 827 } 828 sender->Send(reply); 829 return ok; 830 } 831 832 template<class T, class Method> 833 static bool DispatchDelayReplyWithSendParams(bool ok, 834 const SendParam& send_params, 835 const Message* msg, T* obj, 836 Method func) { 837 Message* reply = SyncMessage::GenerateReply(msg); 838 if (ok) { 839 Tuple1<Message&> t = MakeRefTuple(*reply); 840 ConnectMessageAndReply(msg, reply); 841 DispatchToMethod(obj, func, send_params, &t); 842 } else { 843 NOTREACHED() << "Error deserializing message " << msg->type(); 844 reply->set_reply_error(); 845 obj->Send(reply); 846 } 847 return ok; 848 } 849 850 template<typename TA> 851 static void WriteReplyParams(Message* reply, TA a) { 852 ReplyParam p(a); 853 WriteParam(reply, p); 854 } 855 856 template<typename TA, typename TB> 857 static void WriteReplyParams(Message* reply, TA a, TB b) { 858 ReplyParam p(a, b); 859 WriteParam(reply, p); 860 } 861 862 template<typename TA, typename TB, typename TC> 863 static void WriteReplyParams(Message* reply, TA a, TB b, TC c) { 864 ReplyParam p(a, b, c); 865 WriteParam(reply, p); 866 } 867 868 template<typename TA, typename TB, typename TC, typename TD> 869 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d) { 870 ReplyParam p(a, b, c, d); 871 WriteParam(reply, p); 872 } 873 874 template<typename TA, typename TB, typename TC, typename TD, typename TE> 875 static void WriteReplyParams(Message* reply, TA a, TB b, TC c, TD d, TE e) { 876 ReplyParam p(a, b, c, d, e); 877 WriteParam(reply, p); 878 } 879 }; 880 881 } // namespace IPC 882 883 #endif // IPC_IPC_MESSAGE_UTILS_H_ 884