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