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 <limits.h> 9 #include <stddef.h> 10 #include <stdint.h> 11 12 #include <algorithm> 13 #include <map> 14 #include <memory> 15 #include <set> 16 #include <string> 17 #include <tuple> 18 #include <vector> 19 20 #include "base/containers/small_map.h" 21 #include "base/containers/stack_container.h" 22 #include "base/files/file.h" 23 #include "base/format_macros.h" 24 #include "base/memory/scoped_vector.h" 25 #include "base/optional.h" 26 #include "base/strings/string16.h" 27 #include "base/strings/string_util.h" 28 #include "base/strings/stringprintf.h" 29 #include "build/build_config.h" 30 #include "ipc/brokerable_attachment.h" 31 #include "ipc/ipc_message_start.h" 32 #include "ipc/ipc_param_traits.h" 33 #include "ipc/ipc_sync_message.h" 34 35 namespace base { 36 class DictionaryValue; 37 class FilePath; 38 class ListValue; 39 class NullableString16; 40 class Time; 41 class TimeDelta; 42 class TimeTicks; 43 struct FileDescriptor; 44 45 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) 46 class SharedMemoryHandle; 47 #endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) 48 } 49 50 namespace IPC { 51 52 struct ChannelHandle; 53 54 // ----------------------------------------------------------------------------- 55 // How we send IPC message logs across channels. 56 struct IPC_EXPORT LogData { 57 LogData(); 58 LogData(const LogData& other); 59 ~LogData(); 60 61 std::string channel; 62 int32_t routing_id; 63 uint32_t type; // "User-defined" message type, from ipc_message.h. 64 std::string flags; 65 int64_t sent; // Time that the message was sent (i.e. at Send()). 66 int64_t receive; // Time before it was dispatched (i.e. before calling 67 // OnMessageReceived). 68 int64_t dispatch; // Time after it was dispatched (i.e. after calling 69 // OnMessageReceived). 70 std::string message_name; 71 std::string params; 72 }; 73 74 //----------------------------------------------------------------------------- 75 76 // A dummy struct to place first just to allow leading commas for all 77 // members in the macro-generated constructor initializer lists. 78 struct NoParams { 79 }; 80 81 // Specializations are checked by 'IPC checker' part of find-bad-constructs 82 // Clang plugin (see WriteParam() below for the details). 83 template <typename... Ts> 84 struct CheckedTuple { 85 typedef std::tuple<Ts...> Tuple; 86 }; 87 88 template <class P> 89 static inline void GetParamSize(base::PickleSizer* sizer, const P& p) { 90 typedef typename SimilarTypeTraits<P>::Type Type; 91 ParamTraits<Type>::GetSize(sizer, static_cast<const Type&>(p)); 92 } 93 94 // This function is checked by 'IPC checker' part of find-bad-constructs 95 // Clang plugin to make it's not called on the following types: 96 // 1. long / unsigned long (but not typedefs to) 97 // 2. intmax_t, uintmax_t, intptr_t, uintptr_t, wint_t, 98 // size_t, rsize_t, ssize_t, ptrdiff_t, dev_t, off_t, clock_t, 99 // time_t, suseconds_t (including typedefs to) 100 // 3. Any template referencing types above (e.g. std::vector<size_t>) 101 template <class P> 102 static inline void WriteParam(base::Pickle* m, const P& p) { 103 typedef typename SimilarTypeTraits<P>::Type Type; 104 ParamTraits<Type>::Write(m, static_cast<const Type& >(p)); 105 } 106 107 template <class P> 108 static inline bool WARN_UNUSED_RESULT ReadParam(const base::Pickle* m, 109 base::PickleIterator* iter, 110 P* p) { 111 typedef typename SimilarTypeTraits<P>::Type Type; 112 return ParamTraits<Type>::Read(m, iter, reinterpret_cast<Type* >(p)); 113 } 114 115 template <class P> 116 static inline void LogParam(const P& p, std::string* l) { 117 typedef typename SimilarTypeTraits<P>::Type Type; 118 ParamTraits<Type>::Log(static_cast<const Type& >(p), l); 119 } 120 121 // Primitive ParamTraits ------------------------------------------------------- 122 123 template <> 124 struct ParamTraits<bool> { 125 typedef bool param_type; 126 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 127 sizer->AddBool(); 128 } 129 static void Write(base::Pickle* m, const param_type& p) { m->WriteBool(p); } 130 static bool Read(const base::Pickle* m, 131 base::PickleIterator* iter, 132 param_type* r) { 133 return iter->ReadBool(r); 134 } 135 IPC_EXPORT static void Log(const param_type& p, std::string* l); 136 }; 137 138 template <> 139 struct IPC_EXPORT ParamTraits<signed char> { 140 typedef signed char param_type; 141 static void GetSize(base::PickleSizer* sizer, const param_type& p); 142 static void Write(base::Pickle* m, const param_type& p); 143 static bool Read(const base::Pickle* m, 144 base::PickleIterator* iter, 145 param_type* r); 146 static void Log(const param_type& p, std::string* l); 147 }; 148 149 template <> 150 struct IPC_EXPORT ParamTraits<unsigned char> { 151 typedef unsigned char param_type; 152 static void GetSize(base::PickleSizer* sizer, const param_type& p); 153 static void Write(base::Pickle* m, const param_type& p); 154 static bool Read(const base::Pickle* m, 155 base::PickleIterator* iter, 156 param_type* r); 157 static void Log(const param_type& p, std::string* l); 158 }; 159 160 template <> 161 struct IPC_EXPORT ParamTraits<unsigned short> { 162 typedef unsigned short param_type; 163 static void GetSize(base::PickleSizer* sizer, const param_type& p); 164 static void Write(base::Pickle* m, const param_type& p); 165 static bool Read(const base::Pickle* m, 166 base::PickleIterator* iter, 167 param_type* r); 168 static void Log(const param_type& p, std::string* l); 169 }; 170 171 template <> 172 struct ParamTraits<int> { 173 typedef int param_type; 174 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 175 sizer->AddInt(); 176 } 177 static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); } 178 static bool Read(const base::Pickle* m, 179 base::PickleIterator* iter, 180 param_type* r) { 181 return iter->ReadInt(r); 182 } 183 IPC_EXPORT static void Log(const param_type& p, std::string* l); 184 }; 185 186 template <> 187 struct ParamTraits<unsigned int> { 188 typedef unsigned int param_type; 189 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 190 sizer->AddInt(); 191 } 192 static void Write(base::Pickle* m, const param_type& p) { m->WriteInt(p); } 193 static bool Read(const base::Pickle* m, 194 base::PickleIterator* iter, 195 param_type* r) { 196 return iter->ReadInt(reinterpret_cast<int*>(r)); 197 } 198 IPC_EXPORT static void Log(const param_type& p, std::string* l); 199 }; 200 201 // long isn't safe to send over IPC because it's 4 bytes on 32 bit builds but 202 // 8 bytes on 64 bit builds. So if a 32 bit and 64 bit process have a channel 203 // that would cause problem. 204 // We need to keep this on for a few configs: 205 // 1) Windows because DWORD is typedef'd to it, which is fine because we have 206 // very few IPCs that cross this boundary. 207 // 2) We also need to keep it for Linux for two reasons: int64_t is typedef'd 208 // to long, and gfx::PluginWindow is long and is used in one GPU IPC. 209 // 3) Android 64 bit also has int64_t typedef'd to long. 210 // Since we want to support Android 32<>64 bit IPC, as long as we don't have 211 // these traits for 32 bit ARM then that'll catch any errors. 212 #if defined(OS_WIN) || defined(OS_LINUX) || \ 213 (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS)) 214 template <> 215 struct ParamTraits<long> { 216 typedef long param_type; 217 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 218 sizer->AddLong(); 219 } 220 static void Write(base::Pickle* m, const param_type& p) { 221 m->WriteLong(p); 222 } 223 static bool Read(const base::Pickle* m, 224 base::PickleIterator* iter, 225 param_type* r) { 226 return iter->ReadLong(r); 227 } 228 IPC_EXPORT static void Log(const param_type& p, std::string* l); 229 }; 230 231 template <> 232 struct ParamTraits<unsigned long> { 233 typedef unsigned long param_type; 234 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 235 sizer->AddLong(); 236 } 237 static void Write(base::Pickle* m, const param_type& p) { 238 m->WriteLong(p); 239 } 240 static bool Read(const base::Pickle* m, 241 base::PickleIterator* iter, 242 param_type* r) { 243 return iter->ReadLong(reinterpret_cast<long*>(r)); 244 } 245 IPC_EXPORT static void Log(const param_type& p, std::string* l); 246 }; 247 #endif 248 249 template <> 250 struct ParamTraits<long long> { 251 typedef long long param_type; 252 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 253 sizer->AddInt64(); 254 } 255 static void Write(base::Pickle* m, const param_type& p) { 256 m->WriteInt64(static_cast<int64_t>(p)); 257 } 258 static bool Read(const base::Pickle* m, 259 base::PickleIterator* iter, 260 param_type* r) { 261 return iter->ReadInt64(reinterpret_cast<int64_t*>(r)); 262 } 263 IPC_EXPORT static void Log(const param_type& p, std::string* l); 264 }; 265 266 template <> 267 struct ParamTraits<unsigned long long> { 268 typedef unsigned long long param_type; 269 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 270 sizer->AddInt64(); 271 } 272 static void Write(base::Pickle* m, const param_type& p) { m->WriteInt64(p); } 273 static bool Read(const base::Pickle* m, 274 base::PickleIterator* iter, 275 param_type* r) { 276 return iter->ReadInt64(reinterpret_cast<int64_t*>(r)); 277 } 278 IPC_EXPORT static void Log(const param_type& p, std::string* l); 279 }; 280 281 // Note that the IPC layer doesn't sanitize NaNs and +/- INF values. Clients 282 // should be sure to check the sanity of these values after receiving them over 283 // IPC. 284 template <> 285 struct IPC_EXPORT ParamTraits<float> { 286 typedef float param_type; 287 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 288 sizer->AddFloat(); 289 } 290 static void Write(base::Pickle* m, const param_type& p) { m->WriteFloat(p); } 291 static bool Read(const base::Pickle* m, 292 base::PickleIterator* iter, 293 param_type* r) { 294 return iter->ReadFloat(r); 295 } 296 static void Log(const param_type& p, std::string* l); 297 }; 298 299 template <> 300 struct IPC_EXPORT ParamTraits<double> { 301 typedef double param_type; 302 static void GetSize(base::PickleSizer* sizer, const param_type& p); 303 static void Write(base::Pickle* m, const param_type& p); 304 static bool Read(const base::Pickle* m, 305 base::PickleIterator* iter, 306 param_type* r); 307 static void Log(const param_type& p, std::string* l); 308 }; 309 310 // STL ParamTraits ------------------------------------------------------------- 311 312 template <> 313 struct ParamTraits<std::string> { 314 typedef std::string param_type; 315 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 316 sizer->AddString(p); 317 } 318 static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); } 319 static bool Read(const base::Pickle* m, 320 base::PickleIterator* iter, 321 param_type* r) { 322 return iter->ReadString(r); 323 } 324 IPC_EXPORT static void Log(const param_type& p, std::string* l); 325 }; 326 327 template <> 328 struct ParamTraits<base::string16> { 329 typedef base::string16 param_type; 330 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 331 sizer->AddString16(p); 332 } 333 static void Write(base::Pickle* m, const param_type& p) { 334 m->WriteString16(p); 335 } 336 static bool Read(const base::Pickle* m, 337 base::PickleIterator* iter, 338 param_type* r) { 339 return iter->ReadString16(r); 340 } 341 IPC_EXPORT static void Log(const param_type& p, std::string* l); 342 }; 343 344 template <> 345 struct IPC_EXPORT ParamTraits<std::vector<char> > { 346 typedef std::vector<char> param_type; 347 static void GetSize(base::PickleSizer* sizer, const param_type& p); 348 static void Write(base::Pickle* m, const param_type& p); 349 static bool Read(const base::Pickle*, 350 base::PickleIterator* iter, 351 param_type* r); 352 static void Log(const param_type& p, std::string* l); 353 }; 354 355 template <> 356 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > { 357 typedef std::vector<unsigned char> param_type; 358 static void GetSize(base::PickleSizer* sizer, const param_type& p); 359 static void Write(base::Pickle* m, const param_type& p); 360 static bool Read(const base::Pickle* m, 361 base::PickleIterator* iter, 362 param_type* r); 363 static void Log(const param_type& p, std::string* l); 364 }; 365 366 template <> 367 struct IPC_EXPORT ParamTraits<std::vector<bool> > { 368 typedef std::vector<bool> param_type; 369 static void GetSize(base::PickleSizer* sizer, const param_type& p); 370 static void Write(base::Pickle* m, const param_type& p); 371 static bool Read(const base::Pickle* m, 372 base::PickleIterator* iter, 373 param_type* r); 374 static void Log(const param_type& p, std::string* l); 375 }; 376 377 template <class P> 378 struct ParamTraits<std::vector<P>> { 379 typedef std::vector<P> param_type; 380 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 381 GetParamSize(sizer, static_cast<int>(p.size())); 382 for (size_t i = 0; i < p.size(); i++) 383 GetParamSize(sizer, p[i]); 384 } 385 static void Write(base::Pickle* m, const param_type& p) { 386 WriteParam(m, static_cast<int>(p.size())); 387 for (size_t i = 0; i < p.size(); i++) 388 WriteParam(m, p[i]); 389 } 390 static bool Read(const base::Pickle* m, 391 base::PickleIterator* iter, 392 param_type* r) { 393 int size; 394 // ReadLength() checks for < 0 itself. 395 if (!iter->ReadLength(&size)) 396 return false; 397 // Resizing beforehand is not safe, see BUG 1006367 for details. 398 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size)) 399 return false; 400 r->resize(size); 401 for (int i = 0; i < size; i++) { 402 if (!ReadParam(m, iter, &(*r)[i])) 403 return false; 404 } 405 return true; 406 } 407 static void Log(const param_type& p, std::string* l) { 408 for (size_t i = 0; i < p.size(); ++i) { 409 if (i != 0) 410 l->append(" "); 411 LogParam((p[i]), l); 412 } 413 } 414 }; 415 416 template <class P> 417 struct ParamTraits<std::set<P> > { 418 typedef std::set<P> param_type; 419 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 420 GetParamSize(sizer, static_cast<int>(p.size())); 421 typename param_type::const_iterator iter; 422 for (iter = p.begin(); iter != p.end(); ++iter) 423 GetParamSize(sizer, *iter); 424 } 425 static void Write(base::Pickle* m, const param_type& p) { 426 WriteParam(m, static_cast<int>(p.size())); 427 typename param_type::const_iterator iter; 428 for (iter = p.begin(); iter != p.end(); ++iter) 429 WriteParam(m, *iter); 430 } 431 static bool Read(const base::Pickle* m, 432 base::PickleIterator* iter, 433 param_type* r) { 434 int size; 435 if (!iter->ReadLength(&size)) 436 return false; 437 for (int i = 0; i < size; ++i) { 438 P item; 439 if (!ReadParam(m, iter, &item)) 440 return false; 441 r->insert(item); 442 } 443 return true; 444 } 445 static void Log(const param_type& p, std::string* l) { 446 l->append("<std::set>"); 447 } 448 }; 449 450 template <class K, class V, class C, class A> 451 struct ParamTraits<std::map<K, V, C, A> > { 452 typedef std::map<K, V, C, A> param_type; 453 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 454 GetParamSize(sizer, static_cast<int>(p.size())); 455 typename param_type::const_iterator iter; 456 for (iter = p.begin(); iter != p.end(); ++iter) { 457 GetParamSize(sizer, iter->first); 458 GetParamSize(sizer, iter->second); 459 } 460 } 461 static void Write(base::Pickle* m, const param_type& p) { 462 WriteParam(m, static_cast<int>(p.size())); 463 typename param_type::const_iterator iter; 464 for (iter = p.begin(); iter != p.end(); ++iter) { 465 WriteParam(m, iter->first); 466 WriteParam(m, iter->second); 467 } 468 } 469 static bool Read(const base::Pickle* m, 470 base::PickleIterator* iter, 471 param_type* r) { 472 int size; 473 if (!ReadParam(m, iter, &size) || size < 0) 474 return false; 475 for (int i = 0; i < size; ++i) { 476 K k; 477 if (!ReadParam(m, iter, &k)) 478 return false; 479 V& value = (*r)[k]; 480 if (!ReadParam(m, iter, &value)) 481 return false; 482 } 483 return true; 484 } 485 static void Log(const param_type& p, std::string* l) { 486 l->append("<std::map>"); 487 } 488 }; 489 490 template <class A, class B> 491 struct ParamTraits<std::pair<A, B> > { 492 typedef std::pair<A, B> param_type; 493 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 494 GetParamSize(sizer, p.first); 495 GetParamSize(sizer, p.second); 496 } 497 static void Write(base::Pickle* m, const param_type& p) { 498 WriteParam(m, p.first); 499 WriteParam(m, p.second); 500 } 501 static bool Read(const base::Pickle* m, 502 base::PickleIterator* iter, 503 param_type* r) { 504 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second); 505 } 506 static void Log(const param_type& p, std::string* l) { 507 l->append("("); 508 LogParam(p.first, l); 509 l->append(", "); 510 LogParam(p.second, l); 511 l->append(")"); 512 } 513 }; 514 515 // IPC ParamTraits ------------------------------------------------------------- 516 template <> 517 struct IPC_EXPORT ParamTraits<BrokerableAttachment::AttachmentId> { 518 typedef BrokerableAttachment::AttachmentId param_type; 519 static void Write(base::Pickle* m, const param_type& p); 520 static bool Read(const base::Pickle* m, 521 base::PickleIterator* iter, 522 param_type* r); 523 static void Log(const param_type& p, std::string* l); 524 }; 525 526 // Base ParamTraits ------------------------------------------------------------ 527 528 template <> 529 struct IPC_EXPORT ParamTraits<base::DictionaryValue> { 530 typedef base::DictionaryValue param_type; 531 static void GetSize(base::PickleSizer* sizer, const param_type& p); 532 static void Write(base::Pickle* m, const param_type& p); 533 static bool Read(const base::Pickle* m, 534 base::PickleIterator* iter, 535 param_type* r); 536 static void Log(const param_type& p, std::string* l); 537 }; 538 539 #if defined(OS_POSIX) 540 // FileDescriptors may be serialised over IPC channels on POSIX. On the 541 // receiving side, the FileDescriptor is a valid duplicate of the file 542 // descriptor which was transmitted: *it is not just a copy of the integer like 543 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In 544 // this case, the receiving end will see a value of -1. *Zero is a valid file 545 // descriptor*. 546 // 547 // The received file descriptor will have the |auto_close| flag set to true. The 548 // code which handles the message is responsible for taking ownership of it. 549 // File descriptors are OS resources and must be closed when no longer needed. 550 // 551 // When sending a file descriptor, the file descriptor must be valid at the time 552 // of transmission. Since transmission is not synchronous, one should consider 553 // dup()ing any file descriptors to be transmitted and setting the |auto_close| 554 // flag, which causes the file descriptor to be closed after writing. 555 template<> 556 struct IPC_EXPORT ParamTraits<base::FileDescriptor> { 557 typedef base::FileDescriptor param_type; 558 static void GetSize(base::PickleSizer* sizer, const param_type& p); 559 static void Write(base::Pickle* m, const param_type& p); 560 static bool Read(const base::Pickle* m, 561 base::PickleIterator* iter, 562 param_type* r); 563 static void Log(const param_type& p, std::string* l); 564 }; 565 #endif // defined(OS_POSIX) 566 567 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) 568 template <> 569 struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> { 570 typedef base::SharedMemoryHandle param_type; 571 static void GetSize(base::PickleSizer* sizer, const param_type& p); 572 static void Write(base::Pickle* m, const param_type& p); 573 static bool Read(const base::Pickle* m, 574 base::PickleIterator* iter, 575 param_type* r); 576 static void Log(const param_type& p, std::string* l); 577 }; 578 #endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) 579 580 template <> 581 struct IPC_EXPORT ParamTraits<base::FilePath> { 582 typedef base::FilePath param_type; 583 static void GetSize(base::PickleSizer* sizer, const param_type& p); 584 static void Write(base::Pickle* m, const param_type& p); 585 static bool Read(const base::Pickle* m, 586 base::PickleIterator* iter, 587 param_type* r); 588 static void Log(const param_type& p, std::string* l); 589 }; 590 591 template <> 592 struct IPC_EXPORT ParamTraits<base::ListValue> { 593 typedef base::ListValue param_type; 594 static void GetSize(base::PickleSizer* sizer, const param_type& p); 595 static void Write(base::Pickle* m, const param_type& p); 596 static bool Read(const base::Pickle* m, 597 base::PickleIterator* iter, 598 param_type* r); 599 static void Log(const param_type& p, std::string* l); 600 }; 601 602 template <> 603 struct IPC_EXPORT ParamTraits<base::NullableString16> { 604 typedef base::NullableString16 param_type; 605 static void GetSize(base::PickleSizer* sizer, const param_type& p); 606 static void Write(base::Pickle* m, const param_type& p); 607 static bool Read(const base::Pickle* m, 608 base::PickleIterator* iter, 609 param_type* r); 610 static void Log(const param_type& p, std::string* l); 611 }; 612 613 template <> 614 struct IPC_EXPORT ParamTraits<base::File::Info> { 615 typedef base::File::Info param_type; 616 static void GetSize(base::PickleSizer* sizer, const param_type& p); 617 static void Write(base::Pickle* m, const param_type& p); 618 static bool Read(const base::Pickle* m, 619 base::PickleIterator* iter, 620 param_type* r); 621 static void Log(const param_type& p, std::string* l); 622 }; 623 624 template <> 625 struct SimilarTypeTraits<base::File::Error> { 626 typedef int Type; 627 }; 628 629 #if defined(OS_WIN) 630 template <> 631 struct SimilarTypeTraits<HWND> { 632 typedef HANDLE Type; 633 }; 634 #endif // defined(OS_WIN) 635 636 template <> 637 struct IPC_EXPORT ParamTraits<base::Time> { 638 typedef base::Time param_type; 639 static void GetSize(base::PickleSizer* sizer, const param_type& p); 640 static void Write(base::Pickle* m, const param_type& p); 641 static bool Read(const base::Pickle* m, 642 base::PickleIterator* iter, 643 param_type* r); 644 static void Log(const param_type& p, std::string* l); 645 }; 646 647 template <> 648 struct IPC_EXPORT ParamTraits<base::TimeDelta> { 649 typedef base::TimeDelta param_type; 650 static void GetSize(base::PickleSizer* sizer, const param_type& p); 651 static void Write(base::Pickle* m, const param_type& p); 652 static bool Read(const base::Pickle* m, 653 base::PickleIterator* iter, 654 param_type* r); 655 static void Log(const param_type& p, std::string* l); 656 }; 657 658 template <> 659 struct IPC_EXPORT ParamTraits<base::TimeTicks> { 660 typedef base::TimeTicks param_type; 661 static void GetSize(base::PickleSizer* sizer, const param_type& p); 662 static void Write(base::Pickle* m, const param_type& p); 663 static bool Read(const base::Pickle* m, 664 base::PickleIterator* iter, 665 param_type* r); 666 static void Log(const param_type& p, std::string* l); 667 }; 668 669 template <> 670 struct ParamTraits<std::tuple<>> { 671 typedef std::tuple<> param_type; 672 static void GetSize(base::PickleSizer* sizer, const param_type& p) {} 673 static void Write(base::Pickle* m, const param_type& p) {} 674 static bool Read(const base::Pickle* m, 675 base::PickleIterator* iter, 676 param_type* r) { 677 return true; 678 } 679 static void Log(const param_type& p, std::string* l) { 680 } 681 }; 682 683 template <class A> 684 struct ParamTraits<std::tuple<A>> { 685 typedef std::tuple<A> param_type; 686 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 687 GetParamSize(sizer, std::get<0>(p)); 688 } 689 static void Write(base::Pickle* m, const param_type& p) { 690 WriteParam(m, std::get<0>(p)); 691 } 692 static bool Read(const base::Pickle* m, 693 base::PickleIterator* iter, 694 param_type* r) { 695 return ReadParam(m, iter, &std::get<0>(*r)); 696 } 697 static void Log(const param_type& p, std::string* l) { 698 LogParam(std::get<0>(p), l); 699 } 700 }; 701 702 template <class A, class B> 703 struct ParamTraits<std::tuple<A, B>> { 704 typedef std::tuple<A, B> param_type; 705 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 706 GetParamSize(sizer, std::get<0>(p)); 707 GetParamSize(sizer, std::get<1>(p)); 708 } 709 static void Write(base::Pickle* m, const param_type& p) { 710 WriteParam(m, std::get<0>(p)); 711 WriteParam(m, std::get<1>(p)); 712 } 713 static bool Read(const base::Pickle* m, 714 base::PickleIterator* iter, 715 param_type* r) { 716 return (ReadParam(m, iter, &std::get<0>(*r)) && 717 ReadParam(m, iter, &std::get<1>(*r))); 718 } 719 static void Log(const param_type& p, std::string* l) { 720 LogParam(std::get<0>(p), l); 721 l->append(", "); 722 LogParam(std::get<1>(p), l); 723 } 724 }; 725 726 template <class A, class B, class C> 727 struct ParamTraits<std::tuple<A, B, C>> { 728 typedef std::tuple<A, B, C> param_type; 729 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 730 GetParamSize(sizer, std::get<0>(p)); 731 GetParamSize(sizer, std::get<1>(p)); 732 GetParamSize(sizer, std::get<2>(p)); 733 } 734 static void Write(base::Pickle* m, const param_type& p) { 735 WriteParam(m, std::get<0>(p)); 736 WriteParam(m, std::get<1>(p)); 737 WriteParam(m, std::get<2>(p)); 738 } 739 static bool Read(const base::Pickle* m, 740 base::PickleIterator* iter, 741 param_type* r) { 742 return (ReadParam(m, iter, &std::get<0>(*r)) && 743 ReadParam(m, iter, &std::get<1>(*r)) && 744 ReadParam(m, iter, &std::get<2>(*r))); 745 } 746 static void Log(const param_type& p, std::string* l) { 747 LogParam(std::get<0>(p), l); 748 l->append(", "); 749 LogParam(std::get<1>(p), l); 750 l->append(", "); 751 LogParam(std::get<2>(p), l); 752 } 753 }; 754 755 template <class A, class B, class C, class D> 756 struct ParamTraits<std::tuple<A, B, C, D>> { 757 typedef std::tuple<A, B, C, D> param_type; 758 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 759 GetParamSize(sizer, std::get<0>(p)); 760 GetParamSize(sizer, std::get<1>(p)); 761 GetParamSize(sizer, std::get<2>(p)); 762 GetParamSize(sizer, std::get<3>(p)); 763 } 764 static void Write(base::Pickle* m, const param_type& p) { 765 WriteParam(m, std::get<0>(p)); 766 WriteParam(m, std::get<1>(p)); 767 WriteParam(m, std::get<2>(p)); 768 WriteParam(m, std::get<3>(p)); 769 } 770 static bool Read(const base::Pickle* m, 771 base::PickleIterator* iter, 772 param_type* r) { 773 return (ReadParam(m, iter, &std::get<0>(*r)) && 774 ReadParam(m, iter, &std::get<1>(*r)) && 775 ReadParam(m, iter, &std::get<2>(*r)) && 776 ReadParam(m, iter, &std::get<3>(*r))); 777 } 778 static void Log(const param_type& p, std::string* l) { 779 LogParam(std::get<0>(p), l); 780 l->append(", "); 781 LogParam(std::get<1>(p), l); 782 l->append(", "); 783 LogParam(std::get<2>(p), l); 784 l->append(", "); 785 LogParam(std::get<3>(p), l); 786 } 787 }; 788 789 template <class A, class B, class C, class D, class E> 790 struct ParamTraits<std::tuple<A, B, C, D, E>> { 791 typedef std::tuple<A, B, C, D, E> param_type; 792 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 793 GetParamSize(sizer, std::get<0>(p)); 794 GetParamSize(sizer, std::get<1>(p)); 795 GetParamSize(sizer, std::get<2>(p)); 796 GetParamSize(sizer, std::get<3>(p)); 797 GetParamSize(sizer, std::get<4>(p)); 798 } 799 static void Write(base::Pickle* m, const param_type& p) { 800 WriteParam(m, std::get<0>(p)); 801 WriteParam(m, std::get<1>(p)); 802 WriteParam(m, std::get<2>(p)); 803 WriteParam(m, std::get<3>(p)); 804 WriteParam(m, std::get<4>(p)); 805 } 806 static bool Read(const base::Pickle* m, 807 base::PickleIterator* iter, 808 param_type* r) { 809 return (ReadParam(m, iter, &std::get<0>(*r)) && 810 ReadParam(m, iter, &std::get<1>(*r)) && 811 ReadParam(m, iter, &std::get<2>(*r)) && 812 ReadParam(m, iter, &std::get<3>(*r)) && 813 ReadParam(m, iter, &std::get<4>(*r))); 814 } 815 static void Log(const param_type& p, std::string* l) { 816 LogParam(std::get<0>(p), l); 817 l->append(", "); 818 LogParam(std::get<1>(p), l); 819 l->append(", "); 820 LogParam(std::get<2>(p), l); 821 l->append(", "); 822 LogParam(std::get<3>(p), l); 823 l->append(", "); 824 LogParam(std::get<4>(p), l); 825 } 826 }; 827 828 template<class P> 829 struct ParamTraits<ScopedVector<P> > { 830 typedef ScopedVector<P> param_type; 831 static void Write(base::Pickle* m, const param_type& p) { 832 WriteParam(m, static_cast<int>(p.size())); 833 for (size_t i = 0; i < p.size(); i++) 834 WriteParam(m, *p[i]); 835 } 836 static bool Read(const base::Pickle* m, 837 base::PickleIterator* iter, 838 param_type* r) { 839 int size = 0; 840 if (!iter->ReadLength(&size)) 841 return false; 842 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size)) 843 return false; 844 r->resize(size); 845 for (int i = 0; i < size; i++) { 846 (*r)[i] = new P(); 847 if (!ReadParam(m, iter, (*r)[i])) 848 return false; 849 } 850 return true; 851 } 852 static void Log(const param_type& p, std::string* l) { 853 for (size_t i = 0; i < p.size(); ++i) { 854 if (i != 0) 855 l->append(" "); 856 LogParam(*p[i], l); 857 } 858 } 859 }; 860 861 template <class P, size_t stack_capacity> 862 struct ParamTraits<base::StackVector<P, stack_capacity> > { 863 typedef base::StackVector<P, stack_capacity> param_type; 864 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 865 GetParamSize(sizer, static_cast<int>(p->size())); 866 for (size_t i = 0; i < p->size(); i++) 867 GetParamSize(sizer, p[i]); 868 } 869 static void Write(base::Pickle* m, const param_type& p) { 870 WriteParam(m, static_cast<int>(p->size())); 871 for (size_t i = 0; i < p->size(); i++) 872 WriteParam(m, p[i]); 873 } 874 static bool Read(const base::Pickle* m, 875 base::PickleIterator* iter, 876 param_type* r) { 877 int size; 878 // ReadLength() checks for < 0 itself. 879 if (!iter->ReadLength(&size)) 880 return false; 881 // Sanity check for the vector size. 882 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size)) 883 return false; 884 P value; 885 for (int i = 0; i < size; i++) { 886 if (!ReadParam(m, iter, &value)) 887 return false; 888 (*r)->push_back(value); 889 } 890 return true; 891 } 892 static void Log(const param_type& p, std::string* l) { 893 for (size_t i = 0; i < p->size(); ++i) { 894 if (i != 0) 895 l->append(" "); 896 LogParam((p[i]), l); 897 } 898 } 899 }; 900 901 template <typename NormalMap, 902 int kArraySize, 903 typename EqualKey, 904 typename MapInit> 905 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > { 906 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type; 907 typedef typename param_type::key_type K; 908 typedef typename param_type::data_type V; 909 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 910 GetParamSize(sizer, static_cast<int>(p.size())); 911 typename param_type::const_iterator iter; 912 for (iter = p.begin(); iter != p.end(); ++iter) { 913 GetParamSize(sizer, iter->first); 914 GetParamSize(sizer, iter->second); 915 } 916 } 917 static void Write(base::Pickle* m, const param_type& p) { 918 WriteParam(m, static_cast<int>(p.size())); 919 typename param_type::const_iterator iter; 920 for (iter = p.begin(); iter != p.end(); ++iter) { 921 WriteParam(m, iter->first); 922 WriteParam(m, iter->second); 923 } 924 } 925 static bool Read(const base::Pickle* m, 926 base::PickleIterator* iter, 927 param_type* r) { 928 int size; 929 if (!iter->ReadLength(&size)) 930 return false; 931 for (int i = 0; i < size; ++i) { 932 K key; 933 if (!ReadParam(m, iter, &key)) 934 return false; 935 V& value = (*r)[key]; 936 if (!ReadParam(m, iter, &value)) 937 return false; 938 } 939 return true; 940 } 941 static void Log(const param_type& p, std::string* l) { 942 l->append("<base::SmallMap>"); 943 } 944 }; 945 946 template <class P> 947 struct ParamTraits<std::unique_ptr<P>> { 948 typedef std::unique_ptr<P> param_type; 949 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 950 bool valid = !!p; 951 GetParamSize(sizer, valid); 952 if (valid) 953 GetParamSize(sizer, *p); 954 } 955 static void Write(base::Pickle* m, const param_type& p) { 956 bool valid = !!p; 957 WriteParam(m, valid); 958 if (valid) 959 WriteParam(m, *p); 960 } 961 static bool Read(const base::Pickle* m, 962 base::PickleIterator* iter, 963 param_type* r) { 964 bool valid = false; 965 if (!ReadParam(m, iter, &valid)) 966 return false; 967 968 if (!valid) { 969 r->reset(); 970 return true; 971 } 972 973 param_type temp(new P()); 974 if (!ReadParam(m, iter, temp.get())) 975 return false; 976 977 r->swap(temp); 978 return true; 979 } 980 static void Log(const param_type& p, std::string* l) { 981 if (p) 982 LogParam(*p, l); 983 else 984 l->append("NULL"); 985 } 986 }; 987 988 template <class P> 989 struct ParamTraits<base::Optional<P>> { 990 typedef base::Optional<P> param_type; 991 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 992 const bool is_set = static_cast<bool>(p); 993 GetParamSize(sizer, is_set); 994 if (is_set) 995 GetParamSize(sizer, p.value()); 996 } 997 static void Write(base::Pickle* m, const param_type& p) { 998 const bool is_set = static_cast<bool>(p); 999 WriteParam(m, is_set); 1000 if (is_set) 1001 WriteParam(m, p.value()); 1002 } 1003 static bool Read(const base::Pickle* m, 1004 base::PickleIterator* iter, 1005 param_type* r) { 1006 bool is_set = false; 1007 if (!iter->ReadBool(&is_set)) 1008 return false; 1009 if (is_set) { 1010 P value; 1011 if (!ReadParam(m, iter, &value)) 1012 return false; 1013 *r = std::move(value); 1014 } 1015 return true; 1016 } 1017 static void Log(const param_type& p, std::string* l) { 1018 if (p) 1019 LogParam(p.value(), l); 1020 else 1021 l->append("(unset)"); 1022 } 1023 }; 1024 1025 // IPC types ParamTraits ------------------------------------------------------- 1026 1027 // A ChannelHandle is basically a platform-inspecific wrapper around the 1028 // fact that IPC endpoints are handled specially on POSIX. See above comments 1029 // on FileDescriptor for more background. 1030 template<> 1031 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> { 1032 typedef ChannelHandle param_type; 1033 static void GetSize(base::PickleSizer* sizer, const param_type& p); 1034 static void Write(base::Pickle* m, const param_type& p); 1035 static bool Read(const base::Pickle* m, 1036 base::PickleIterator* iter, 1037 param_type* r); 1038 static void Log(const param_type& p, std::string* l); 1039 }; 1040 1041 template <> 1042 struct IPC_EXPORT ParamTraits<LogData> { 1043 typedef LogData param_type; 1044 static void GetSize(base::PickleSizer* sizer, const param_type& p); 1045 static void Write(base::Pickle* m, const param_type& p); 1046 static bool Read(const base::Pickle* m, 1047 base::PickleIterator* iter, 1048 param_type* r); 1049 static void Log(const param_type& p, std::string* l); 1050 }; 1051 1052 template <> 1053 struct IPC_EXPORT ParamTraits<Message> { 1054 static void Write(base::Pickle* m, const Message& p); 1055 static bool Read(const base::Pickle* m, 1056 base::PickleIterator* iter, 1057 Message* r); 1058 static void Log(const Message& p, std::string* l); 1059 }; 1060 1061 // Windows ParamTraits --------------------------------------------------------- 1062 1063 #if defined(OS_WIN) 1064 template <> 1065 struct IPC_EXPORT ParamTraits<HANDLE> { 1066 typedef HANDLE param_type; 1067 static void GetSize(base::PickleSizer* sizer, const param_type& p); 1068 static void Write(base::Pickle* m, const param_type& p); 1069 static bool Read(const base::Pickle* m, 1070 base::PickleIterator* iter, 1071 param_type* r); 1072 static void Log(const param_type& p, std::string* l); 1073 }; 1074 1075 template <> 1076 struct IPC_EXPORT ParamTraits<LOGFONT> { 1077 typedef LOGFONT param_type; 1078 static void GetSize(base::PickleSizer* sizer, const param_type& p); 1079 static void Write(base::Pickle* m, const param_type& p); 1080 static bool Read(const base::Pickle* m, 1081 base::PickleIterator* iter, 1082 param_type* r); 1083 static void Log(const param_type& p, std::string* l); 1084 }; 1085 1086 template <> 1087 struct IPC_EXPORT ParamTraits<MSG> { 1088 typedef MSG param_type; 1089 static void GetSize(base::PickleSizer* sizer, const param_type& p); 1090 static void Write(base::Pickle* m, const param_type& p); 1091 static bool Read(const base::Pickle* m, 1092 base::PickleIterator* iter, 1093 param_type* r); 1094 static void Log(const param_type& p, std::string* l); 1095 }; 1096 #endif // defined(OS_WIN) 1097 1098 //----------------------------------------------------------------------------- 1099 // Generic message subclasses 1100 1101 // defined in ipc_logging.cc 1102 IPC_EXPORT void GenerateLogData(const std::string& channel, 1103 const Message& message, 1104 LogData* data, bool get_params); 1105 1106 1107 #if defined(IPC_MESSAGE_LOG_ENABLED) 1108 inline void AddOutputParamsToLog(const Message* msg, std::string* l) { 1109 const std::string& output_params = msg->output_params(); 1110 if (!l->empty() && !output_params.empty()) 1111 l->append(", "); 1112 1113 l->append(output_params); 1114 } 1115 1116 template <class ReplyParamType> 1117 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, 1118 const Message* msg) { 1119 if (msg->received_time() != 0) { 1120 std::string output_params; 1121 LogParam(reply_params, &output_params); 1122 msg->set_output_params(output_params); 1123 } 1124 } 1125 1126 inline void ConnectMessageAndReply(const Message* msg, Message* reply) { 1127 if (msg->sent_time()) { 1128 // Don't log the sync message after dispatch, as we don't have the 1129 // output parameters at that point. Instead, save its data and log it 1130 // with the outgoing reply message when it's sent. 1131 LogData* data = new LogData; 1132 GenerateLogData("", *msg, data, true); 1133 msg->set_dont_log(); 1134 reply->set_sync_log_data(data); 1135 } 1136 } 1137 #else 1138 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {} 1139 1140 template <class ReplyParamType> 1141 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, 1142 const Message* msg) {} 1143 1144 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {} 1145 #endif 1146 1147 } // namespace IPC 1148 1149 #endif // IPC_IPC_MESSAGE_UTILS_H_ 1150