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/ipc_message_start.h" 31 #include "ipc/ipc_param_traits.h" 32 #include "ipc/ipc_sync_message.h" 33 34 namespace base { 35 class DictionaryValue; 36 class FilePath; 37 class ListValue; 38 class NullableString16; 39 class Time; 40 class TimeDelta; 41 class TimeTicks; 42 class UnguessableToken; 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 template <class P, size_t Size> 311 struct ParamTraits<P[Size]> { 312 using param_type = P[Size]; 313 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 314 for (const P& element : p) 315 GetParamSize(sizer, element); 316 } 317 static void Write(base::Pickle* m, const param_type& p) { 318 for (const P& element : p) 319 WriteParam(m, element); 320 } 321 static bool Read(const base::Pickle* m, 322 base::PickleIterator* iter, 323 param_type* r) { 324 for (P& element : *r) { 325 if (!ReadParam(m, iter, &element)) 326 return false; 327 } 328 return true; 329 } 330 static void Log(const param_type& p, std::string* l) { 331 l->append("["); 332 for (const P& element : p) { 333 if (&element != &p[0]) 334 l->append(" "); 335 LogParam(element, l); 336 } 337 l->append("]"); 338 } 339 }; 340 341 // STL ParamTraits ------------------------------------------------------------- 342 343 template <> 344 struct ParamTraits<std::string> { 345 typedef std::string param_type; 346 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 347 sizer->AddString(p); 348 } 349 static void Write(base::Pickle* m, const param_type& p) { m->WriteString(p); } 350 static bool Read(const base::Pickle* m, 351 base::PickleIterator* iter, 352 param_type* r) { 353 return iter->ReadString(r); 354 } 355 IPC_EXPORT static void Log(const param_type& p, std::string* l); 356 }; 357 358 template <> 359 struct ParamTraits<base::string16> { 360 typedef base::string16 param_type; 361 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 362 sizer->AddString16(p); 363 } 364 static void Write(base::Pickle* m, const param_type& p) { 365 m->WriteString16(p); 366 } 367 static bool Read(const base::Pickle* m, 368 base::PickleIterator* iter, 369 param_type* r) { 370 return iter->ReadString16(r); 371 } 372 IPC_EXPORT static void Log(const param_type& p, std::string* l); 373 }; 374 375 template <> 376 struct IPC_EXPORT ParamTraits<std::vector<char> > { 377 typedef std::vector<char> param_type; 378 static void GetSize(base::PickleSizer* sizer, const param_type& p); 379 static void Write(base::Pickle* m, const param_type& p); 380 static bool Read(const base::Pickle*, 381 base::PickleIterator* iter, 382 param_type* r); 383 static void Log(const param_type& p, std::string* l); 384 }; 385 386 template <> 387 struct IPC_EXPORT ParamTraits<std::vector<unsigned char> > { 388 typedef std::vector<unsigned char> param_type; 389 static void GetSize(base::PickleSizer* sizer, const param_type& p); 390 static void Write(base::Pickle* m, const param_type& p); 391 static bool Read(const base::Pickle* m, 392 base::PickleIterator* iter, 393 param_type* r); 394 static void Log(const param_type& p, std::string* l); 395 }; 396 397 template <> 398 struct IPC_EXPORT ParamTraits<std::vector<bool> > { 399 typedef std::vector<bool> param_type; 400 static void GetSize(base::PickleSizer* sizer, const param_type& p); 401 static void Write(base::Pickle* m, const param_type& p); 402 static bool Read(const base::Pickle* m, 403 base::PickleIterator* iter, 404 param_type* r); 405 static void Log(const param_type& p, std::string* l); 406 }; 407 408 template <class P> 409 struct ParamTraits<std::vector<P>> { 410 typedef std::vector<P> param_type; 411 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 412 GetParamSize(sizer, static_cast<int>(p.size())); 413 for (size_t i = 0; i < p.size(); i++) 414 GetParamSize(sizer, p[i]); 415 } 416 static void Write(base::Pickle* m, const param_type& p) { 417 WriteParam(m, static_cast<int>(p.size())); 418 for (size_t i = 0; i < p.size(); i++) 419 WriteParam(m, p[i]); 420 } 421 static bool Read(const base::Pickle* m, 422 base::PickleIterator* iter, 423 param_type* r) { 424 int size; 425 // ReadLength() checks for < 0 itself. 426 if (!iter->ReadLength(&size)) 427 return false; 428 // Resizing beforehand is not safe, see BUG 1006367 for details. 429 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size)) 430 return false; 431 r->resize(size); 432 for (int i = 0; i < size; i++) { 433 if (!ReadParam(m, iter, &(*r)[i])) 434 return false; 435 } 436 return true; 437 } 438 static void Log(const param_type& p, std::string* l) { 439 for (size_t i = 0; i < p.size(); ++i) { 440 if (i != 0) 441 l->append(" "); 442 LogParam((p[i]), l); 443 } 444 } 445 }; 446 447 template <class P> 448 struct ParamTraits<std::set<P> > { 449 typedef std::set<P> param_type; 450 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 451 GetParamSize(sizer, static_cast<int>(p.size())); 452 typename param_type::const_iterator iter; 453 for (iter = p.begin(); iter != p.end(); ++iter) 454 GetParamSize(sizer, *iter); 455 } 456 static void Write(base::Pickle* m, const param_type& p) { 457 WriteParam(m, static_cast<int>(p.size())); 458 typename param_type::const_iterator iter; 459 for (iter = p.begin(); iter != p.end(); ++iter) 460 WriteParam(m, *iter); 461 } 462 static bool Read(const base::Pickle* m, 463 base::PickleIterator* iter, 464 param_type* r) { 465 int size; 466 if (!iter->ReadLength(&size)) 467 return false; 468 for (int i = 0; i < size; ++i) { 469 P item; 470 if (!ReadParam(m, iter, &item)) 471 return false; 472 r->insert(item); 473 } 474 return true; 475 } 476 static void Log(const param_type& p, std::string* l) { 477 l->append("<std::set>"); 478 } 479 }; 480 481 template <class K, class V, class C, class A> 482 struct ParamTraits<std::map<K, V, C, A> > { 483 typedef std::map<K, V, C, A> param_type; 484 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 485 GetParamSize(sizer, static_cast<int>(p.size())); 486 typename param_type::const_iterator iter; 487 for (iter = p.begin(); iter != p.end(); ++iter) { 488 GetParamSize(sizer, iter->first); 489 GetParamSize(sizer, iter->second); 490 } 491 } 492 static void Write(base::Pickle* m, const param_type& p) { 493 WriteParam(m, static_cast<int>(p.size())); 494 typename param_type::const_iterator iter; 495 for (iter = p.begin(); iter != p.end(); ++iter) { 496 WriteParam(m, iter->first); 497 WriteParam(m, iter->second); 498 } 499 } 500 static bool Read(const base::Pickle* m, 501 base::PickleIterator* iter, 502 param_type* r) { 503 int size; 504 if (!ReadParam(m, iter, &size) || size < 0) 505 return false; 506 for (int i = 0; i < size; ++i) { 507 K k; 508 if (!ReadParam(m, iter, &k)) 509 return false; 510 V& value = (*r)[k]; 511 if (!ReadParam(m, iter, &value)) 512 return false; 513 } 514 return true; 515 } 516 static void Log(const param_type& p, std::string* l) { 517 l->append("<std::map>"); 518 } 519 }; 520 521 template <class A, class B> 522 struct ParamTraits<std::pair<A, B> > { 523 typedef std::pair<A, B> param_type; 524 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 525 GetParamSize(sizer, p.first); 526 GetParamSize(sizer, p.second); 527 } 528 static void Write(base::Pickle* m, const param_type& p) { 529 WriteParam(m, p.first); 530 WriteParam(m, p.second); 531 } 532 static bool Read(const base::Pickle* m, 533 base::PickleIterator* iter, 534 param_type* r) { 535 return ReadParam(m, iter, &r->first) && ReadParam(m, iter, &r->second); 536 } 537 static void Log(const param_type& p, std::string* l) { 538 l->append("("); 539 LogParam(p.first, l); 540 l->append(", "); 541 LogParam(p.second, l); 542 l->append(")"); 543 } 544 }; 545 546 // Base ParamTraits ------------------------------------------------------------ 547 548 template <> 549 struct IPC_EXPORT ParamTraits<base::DictionaryValue> { 550 typedef base::DictionaryValue param_type; 551 static void GetSize(base::PickleSizer* sizer, const param_type& p); 552 static void Write(base::Pickle* m, const param_type& p); 553 static bool Read(const base::Pickle* m, 554 base::PickleIterator* iter, 555 param_type* r); 556 static void Log(const param_type& p, std::string* l); 557 }; 558 559 #if defined(OS_POSIX) 560 // FileDescriptors may be serialised over IPC channels on POSIX. On the 561 // receiving side, the FileDescriptor is a valid duplicate of the file 562 // descriptor which was transmitted: *it is not just a copy of the integer like 563 // HANDLEs on Windows*. The only exception is if the file descriptor is < 0. In 564 // this case, the receiving end will see a value of -1. *Zero is a valid file 565 // descriptor*. 566 // 567 // The received file descriptor will have the |auto_close| flag set to true. The 568 // code which handles the message is responsible for taking ownership of it. 569 // File descriptors are OS resources and must be closed when no longer needed. 570 // 571 // When sending a file descriptor, the file descriptor must be valid at the time 572 // of transmission. Since transmission is not synchronous, one should consider 573 // dup()ing any file descriptors to be transmitted and setting the |auto_close| 574 // flag, which causes the file descriptor to be closed after writing. 575 template<> 576 struct IPC_EXPORT ParamTraits<base::FileDescriptor> { 577 typedef base::FileDescriptor param_type; 578 static void GetSize(base::PickleSizer* sizer, const param_type& p); 579 static void Write(base::Pickle* m, const param_type& p); 580 static bool Read(const base::Pickle* m, 581 base::PickleIterator* iter, 582 param_type* r); 583 static void Log(const param_type& p, std::string* l); 584 }; 585 #endif // defined(OS_POSIX) 586 587 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) 588 template <> 589 struct IPC_EXPORT ParamTraits<base::SharedMemoryHandle> { 590 typedef base::SharedMemoryHandle param_type; 591 static void GetSize(base::PickleSizer* sizer, const param_type& p); 592 static void Write(base::Pickle* m, const param_type& p); 593 static bool Read(const base::Pickle* m, 594 base::PickleIterator* iter, 595 param_type* r); 596 static void Log(const param_type& p, std::string* l); 597 }; 598 #endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) 599 600 template <> 601 struct IPC_EXPORT ParamTraits<base::FilePath> { 602 typedef base::FilePath param_type; 603 static void GetSize(base::PickleSizer* sizer, const param_type& p); 604 static void Write(base::Pickle* m, const param_type& p); 605 static bool Read(const base::Pickle* m, 606 base::PickleIterator* iter, 607 param_type* r); 608 static void Log(const param_type& p, std::string* l); 609 }; 610 611 template <> 612 struct IPC_EXPORT ParamTraits<base::ListValue> { 613 typedef base::ListValue param_type; 614 static void GetSize(base::PickleSizer* sizer, const param_type& p); 615 static void Write(base::Pickle* m, const param_type& p); 616 static bool Read(const base::Pickle* m, 617 base::PickleIterator* iter, 618 param_type* r); 619 static void Log(const param_type& p, std::string* l); 620 }; 621 622 template <> 623 struct IPC_EXPORT ParamTraits<base::NullableString16> { 624 typedef base::NullableString16 param_type; 625 static void GetSize(base::PickleSizer* sizer, const param_type& p); 626 static void Write(base::Pickle* m, const param_type& p); 627 static bool Read(const base::Pickle* m, 628 base::PickleIterator* iter, 629 param_type* r); 630 static void Log(const param_type& p, std::string* l); 631 }; 632 633 template <> 634 struct IPC_EXPORT ParamTraits<base::File::Info> { 635 typedef base::File::Info param_type; 636 static void GetSize(base::PickleSizer* sizer, const param_type& p); 637 static void Write(base::Pickle* m, const param_type& p); 638 static bool Read(const base::Pickle* m, 639 base::PickleIterator* iter, 640 param_type* r); 641 static void Log(const param_type& p, std::string* l); 642 }; 643 644 template <> 645 struct SimilarTypeTraits<base::File::Error> { 646 typedef int Type; 647 }; 648 649 #if defined(OS_WIN) 650 template <> 651 struct SimilarTypeTraits<HWND> { 652 typedef HANDLE Type; 653 }; 654 #endif // defined(OS_WIN) 655 656 template <> 657 struct IPC_EXPORT ParamTraits<base::Time> { 658 typedef base::Time param_type; 659 static void GetSize(base::PickleSizer* sizer, const param_type& p); 660 static void Write(base::Pickle* m, const param_type& p); 661 static bool Read(const base::Pickle* m, 662 base::PickleIterator* iter, 663 param_type* r); 664 static void Log(const param_type& p, std::string* l); 665 }; 666 667 template <> 668 struct IPC_EXPORT ParamTraits<base::TimeDelta> { 669 typedef base::TimeDelta param_type; 670 static void GetSize(base::PickleSizer* sizer, const param_type& p); 671 static void Write(base::Pickle* m, const param_type& p); 672 static bool Read(const base::Pickle* m, 673 base::PickleIterator* iter, 674 param_type* r); 675 static void Log(const param_type& p, std::string* l); 676 }; 677 678 template <> 679 struct IPC_EXPORT ParamTraits<base::TimeTicks> { 680 typedef base::TimeTicks param_type; 681 static void GetSize(base::PickleSizer* sizer, const param_type& p); 682 static void Write(base::Pickle* m, const param_type& p); 683 static bool Read(const base::Pickle* m, 684 base::PickleIterator* iter, 685 param_type* r); 686 static void Log(const param_type& p, std::string* l); 687 }; 688 689 template <> 690 struct IPC_EXPORT ParamTraits<base::UnguessableToken> { 691 typedef base::UnguessableToken param_type; 692 static void GetSize(base::PickleSizer* sizer, const param_type& p); 693 static void Write(base::Pickle* m, const param_type& p); 694 static bool Read(const base::Pickle* m, 695 base::PickleIterator* iter, 696 param_type* r); 697 static void Log(const param_type& p, std::string* l); 698 }; 699 700 template <> 701 struct ParamTraits<std::tuple<>> { 702 typedef std::tuple<> param_type; 703 static void GetSize(base::PickleSizer* sizer, const param_type& p) {} 704 static void Write(base::Pickle* m, const param_type& p) {} 705 static bool Read(const base::Pickle* m, 706 base::PickleIterator* iter, 707 param_type* r) { 708 return true; 709 } 710 static void Log(const param_type& p, std::string* l) { 711 } 712 }; 713 714 template <class A> 715 struct ParamTraits<std::tuple<A>> { 716 typedef std::tuple<A> param_type; 717 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 718 GetParamSize(sizer, std::get<0>(p)); 719 } 720 static void Write(base::Pickle* m, const param_type& p) { 721 WriteParam(m, std::get<0>(p)); 722 } 723 static bool Read(const base::Pickle* m, 724 base::PickleIterator* iter, 725 param_type* r) { 726 return ReadParam(m, iter, &std::get<0>(*r)); 727 } 728 static void Log(const param_type& p, std::string* l) { 729 LogParam(std::get<0>(p), l); 730 } 731 }; 732 733 template <class A, class B> 734 struct ParamTraits<std::tuple<A, B>> { 735 typedef std::tuple<A, B> param_type; 736 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 737 GetParamSize(sizer, std::get<0>(p)); 738 GetParamSize(sizer, std::get<1>(p)); 739 } 740 static void Write(base::Pickle* m, const param_type& p) { 741 WriteParam(m, std::get<0>(p)); 742 WriteParam(m, std::get<1>(p)); 743 } 744 static bool Read(const base::Pickle* m, 745 base::PickleIterator* iter, 746 param_type* r) { 747 return (ReadParam(m, iter, &std::get<0>(*r)) && 748 ReadParam(m, iter, &std::get<1>(*r))); 749 } 750 static void Log(const param_type& p, std::string* l) { 751 LogParam(std::get<0>(p), l); 752 l->append(", "); 753 LogParam(std::get<1>(p), l); 754 } 755 }; 756 757 template <class A, class B, class C> 758 struct ParamTraits<std::tuple<A, B, C>> { 759 typedef std::tuple<A, B, C> param_type; 760 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 761 GetParamSize(sizer, std::get<0>(p)); 762 GetParamSize(sizer, std::get<1>(p)); 763 GetParamSize(sizer, std::get<2>(p)); 764 } 765 static void Write(base::Pickle* m, const param_type& p) { 766 WriteParam(m, std::get<0>(p)); 767 WriteParam(m, std::get<1>(p)); 768 WriteParam(m, std::get<2>(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 } 777 static void Log(const param_type& p, std::string* l) { 778 LogParam(std::get<0>(p), l); 779 l->append(", "); 780 LogParam(std::get<1>(p), l); 781 l->append(", "); 782 LogParam(std::get<2>(p), l); 783 } 784 }; 785 786 template <class A, class B, class C, class D> 787 struct ParamTraits<std::tuple<A, B, C, D>> { 788 typedef std::tuple<A, B, C, D> param_type; 789 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 790 GetParamSize(sizer, std::get<0>(p)); 791 GetParamSize(sizer, std::get<1>(p)); 792 GetParamSize(sizer, std::get<2>(p)); 793 GetParamSize(sizer, std::get<3>(p)); 794 } 795 static void Write(base::Pickle* m, const param_type& p) { 796 WriteParam(m, std::get<0>(p)); 797 WriteParam(m, std::get<1>(p)); 798 WriteParam(m, std::get<2>(p)); 799 WriteParam(m, std::get<3>(p)); 800 } 801 static bool Read(const base::Pickle* m, 802 base::PickleIterator* iter, 803 param_type* r) { 804 return (ReadParam(m, iter, &std::get<0>(*r)) && 805 ReadParam(m, iter, &std::get<1>(*r)) && 806 ReadParam(m, iter, &std::get<2>(*r)) && 807 ReadParam(m, iter, &std::get<3>(*r))); 808 } 809 static void Log(const param_type& p, std::string* l) { 810 LogParam(std::get<0>(p), l); 811 l->append(", "); 812 LogParam(std::get<1>(p), l); 813 l->append(", "); 814 LogParam(std::get<2>(p), l); 815 l->append(", "); 816 LogParam(std::get<3>(p), l); 817 } 818 }; 819 820 template <class A, class B, class C, class D, class E> 821 struct ParamTraits<std::tuple<A, B, C, D, E>> { 822 typedef std::tuple<A, B, C, D, E> param_type; 823 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 824 GetParamSize(sizer, std::get<0>(p)); 825 GetParamSize(sizer, std::get<1>(p)); 826 GetParamSize(sizer, std::get<2>(p)); 827 GetParamSize(sizer, std::get<3>(p)); 828 GetParamSize(sizer, std::get<4>(p)); 829 } 830 static void Write(base::Pickle* m, const param_type& p) { 831 WriteParam(m, std::get<0>(p)); 832 WriteParam(m, std::get<1>(p)); 833 WriteParam(m, std::get<2>(p)); 834 WriteParam(m, std::get<3>(p)); 835 WriteParam(m, std::get<4>(p)); 836 } 837 static bool Read(const base::Pickle* m, 838 base::PickleIterator* iter, 839 param_type* r) { 840 return (ReadParam(m, iter, &std::get<0>(*r)) && 841 ReadParam(m, iter, &std::get<1>(*r)) && 842 ReadParam(m, iter, &std::get<2>(*r)) && 843 ReadParam(m, iter, &std::get<3>(*r)) && 844 ReadParam(m, iter, &std::get<4>(*r))); 845 } 846 static void Log(const param_type& p, std::string* l) { 847 LogParam(std::get<0>(p), l); 848 l->append(", "); 849 LogParam(std::get<1>(p), l); 850 l->append(", "); 851 LogParam(std::get<2>(p), l); 852 l->append(", "); 853 LogParam(std::get<3>(p), l); 854 l->append(", "); 855 LogParam(std::get<4>(p), l); 856 } 857 }; 858 859 template<class P> 860 struct ParamTraits<ScopedVector<P> > { 861 typedef ScopedVector<P> param_type; 862 static void Write(base::Pickle* m, const param_type& p) { 863 WriteParam(m, static_cast<int>(p.size())); 864 for (size_t i = 0; i < p.size(); i++) 865 WriteParam(m, *p[i]); 866 } 867 static bool Read(const base::Pickle* m, 868 base::PickleIterator* iter, 869 param_type* r) { 870 int size = 0; 871 if (!iter->ReadLength(&size)) 872 return false; 873 if (INT_MAX/sizeof(P) <= static_cast<size_t>(size)) 874 return false; 875 r->resize(size); 876 for (int i = 0; i < size; i++) { 877 (*r)[i] = new P(); 878 if (!ReadParam(m, iter, (*r)[i])) 879 return false; 880 } 881 return true; 882 } 883 static void Log(const param_type& p, std::string* l) { 884 for (size_t i = 0; i < p.size(); ++i) { 885 if (i != 0) 886 l->append(" "); 887 LogParam(*p[i], l); 888 } 889 } 890 }; 891 892 template <class P, size_t stack_capacity> 893 struct ParamTraits<base::StackVector<P, stack_capacity> > { 894 typedef base::StackVector<P, stack_capacity> param_type; 895 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 896 GetParamSize(sizer, static_cast<int>(p->size())); 897 for (size_t i = 0; i < p->size(); i++) 898 GetParamSize(sizer, p[i]); 899 } 900 static void Write(base::Pickle* m, const param_type& p) { 901 WriteParam(m, static_cast<int>(p->size())); 902 for (size_t i = 0; i < p->size(); i++) 903 WriteParam(m, p[i]); 904 } 905 static bool Read(const base::Pickle* m, 906 base::PickleIterator* iter, 907 param_type* r) { 908 int size; 909 // ReadLength() checks for < 0 itself. 910 if (!iter->ReadLength(&size)) 911 return false; 912 // Sanity check for the vector size. 913 if (INT_MAX / sizeof(P) <= static_cast<size_t>(size)) 914 return false; 915 P value; 916 for (int i = 0; i < size; i++) { 917 if (!ReadParam(m, iter, &value)) 918 return false; 919 (*r)->push_back(value); 920 } 921 return true; 922 } 923 static void Log(const param_type& p, std::string* l) { 924 for (size_t i = 0; i < p->size(); ++i) { 925 if (i != 0) 926 l->append(" "); 927 LogParam((p[i]), l); 928 } 929 } 930 }; 931 932 template <typename NormalMap, 933 int kArraySize, 934 typename EqualKey, 935 typename MapInit> 936 struct ParamTraits<base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> > { 937 typedef base::SmallMap<NormalMap, kArraySize, EqualKey, MapInit> param_type; 938 typedef typename param_type::key_type K; 939 typedef typename param_type::data_type V; 940 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 941 GetParamSize(sizer, static_cast<int>(p.size())); 942 typename param_type::const_iterator iter; 943 for (iter = p.begin(); iter != p.end(); ++iter) { 944 GetParamSize(sizer, iter->first); 945 GetParamSize(sizer, iter->second); 946 } 947 } 948 static void Write(base::Pickle* m, const param_type& p) { 949 WriteParam(m, static_cast<int>(p.size())); 950 typename param_type::const_iterator iter; 951 for (iter = p.begin(); iter != p.end(); ++iter) { 952 WriteParam(m, iter->first); 953 WriteParam(m, iter->second); 954 } 955 } 956 static bool Read(const base::Pickle* m, 957 base::PickleIterator* iter, 958 param_type* r) { 959 int size; 960 if (!iter->ReadLength(&size)) 961 return false; 962 for (int i = 0; i < size; ++i) { 963 K key; 964 if (!ReadParam(m, iter, &key)) 965 return false; 966 V& value = (*r)[key]; 967 if (!ReadParam(m, iter, &value)) 968 return false; 969 } 970 return true; 971 } 972 static void Log(const param_type& p, std::string* l) { 973 l->append("<base::SmallMap>"); 974 } 975 }; 976 977 template <class P> 978 struct ParamTraits<std::unique_ptr<P>> { 979 typedef std::unique_ptr<P> param_type; 980 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 981 bool valid = !!p; 982 GetParamSize(sizer, valid); 983 if (valid) 984 GetParamSize(sizer, *p); 985 } 986 static void Write(base::Pickle* m, const param_type& p) { 987 bool valid = !!p; 988 WriteParam(m, valid); 989 if (valid) 990 WriteParam(m, *p); 991 } 992 static bool Read(const base::Pickle* m, 993 base::PickleIterator* iter, 994 param_type* r) { 995 bool valid = false; 996 if (!ReadParam(m, iter, &valid)) 997 return false; 998 999 if (!valid) { 1000 r->reset(); 1001 return true; 1002 } 1003 1004 param_type temp(new P()); 1005 if (!ReadParam(m, iter, temp.get())) 1006 return false; 1007 1008 r->swap(temp); 1009 return true; 1010 } 1011 static void Log(const param_type& p, std::string* l) { 1012 if (p) 1013 LogParam(*p, l); 1014 else 1015 l->append("NULL"); 1016 } 1017 }; 1018 1019 template <class P> 1020 struct ParamTraits<base::Optional<P>> { 1021 typedef base::Optional<P> param_type; 1022 static void GetSize(base::PickleSizer* sizer, const param_type& p) { 1023 const bool is_set = static_cast<bool>(p); 1024 GetParamSize(sizer, is_set); 1025 if (is_set) 1026 GetParamSize(sizer, p.value()); 1027 } 1028 static void Write(base::Pickle* m, const param_type& p) { 1029 const bool is_set = static_cast<bool>(p); 1030 WriteParam(m, is_set); 1031 if (is_set) 1032 WriteParam(m, p.value()); 1033 } 1034 static bool Read(const base::Pickle* m, 1035 base::PickleIterator* iter, 1036 param_type* r) { 1037 bool is_set = false; 1038 if (!iter->ReadBool(&is_set)) 1039 return false; 1040 if (is_set) { 1041 P value; 1042 if (!ReadParam(m, iter, &value)) 1043 return false; 1044 *r = std::move(value); 1045 } 1046 return true; 1047 } 1048 static void Log(const param_type& p, std::string* l) { 1049 if (p) 1050 LogParam(p.value(), l); 1051 else 1052 l->append("(unset)"); 1053 } 1054 }; 1055 1056 // IPC types ParamTraits ------------------------------------------------------- 1057 1058 // A ChannelHandle is basically a platform-inspecific wrapper around the 1059 // fact that IPC endpoints are handled specially on POSIX. See above comments 1060 // on FileDescriptor for more background. 1061 template<> 1062 struct IPC_EXPORT ParamTraits<IPC::ChannelHandle> { 1063 typedef ChannelHandle param_type; 1064 static void GetSize(base::PickleSizer* sizer, const param_type& p); 1065 static void Write(base::Pickle* m, const param_type& p); 1066 static bool Read(const base::Pickle* m, 1067 base::PickleIterator* iter, 1068 param_type* r); 1069 static void Log(const param_type& p, std::string* l); 1070 }; 1071 1072 template <> 1073 struct IPC_EXPORT ParamTraits<LogData> { 1074 typedef LogData param_type; 1075 static void GetSize(base::PickleSizer* sizer, const param_type& p); 1076 static void Write(base::Pickle* m, const param_type& p); 1077 static bool Read(const base::Pickle* m, 1078 base::PickleIterator* iter, 1079 param_type* r); 1080 static void Log(const param_type& p, std::string* l); 1081 }; 1082 1083 template <> 1084 struct IPC_EXPORT ParamTraits<Message> { 1085 static void Write(base::Pickle* m, const Message& p); 1086 static bool Read(const base::Pickle* m, 1087 base::PickleIterator* iter, 1088 Message* r); 1089 static void Log(const Message& p, std::string* l); 1090 }; 1091 1092 // Windows ParamTraits --------------------------------------------------------- 1093 1094 #if defined(OS_WIN) 1095 template <> 1096 struct IPC_EXPORT ParamTraits<HANDLE> { 1097 typedef HANDLE param_type; 1098 static void GetSize(base::PickleSizer* sizer, const param_type& p); 1099 static void Write(base::Pickle* m, const param_type& p); 1100 static bool Read(const base::Pickle* m, 1101 base::PickleIterator* iter, 1102 param_type* r); 1103 static void Log(const param_type& p, std::string* l); 1104 }; 1105 1106 template <> 1107 struct IPC_EXPORT ParamTraits<LOGFONT> { 1108 typedef LOGFONT param_type; 1109 static void GetSize(base::PickleSizer* sizer, const param_type& p); 1110 static void Write(base::Pickle* m, const param_type& p); 1111 static bool Read(const base::Pickle* m, 1112 base::PickleIterator* iter, 1113 param_type* r); 1114 static void Log(const param_type& p, std::string* l); 1115 }; 1116 1117 template <> 1118 struct IPC_EXPORT ParamTraits<MSG> { 1119 typedef MSG param_type; 1120 static void GetSize(base::PickleSizer* sizer, const param_type& p); 1121 static void Write(base::Pickle* m, const param_type& p); 1122 static bool Read(const base::Pickle* m, 1123 base::PickleIterator* iter, 1124 param_type* r); 1125 static void Log(const param_type& p, std::string* l); 1126 }; 1127 #endif // defined(OS_WIN) 1128 1129 //----------------------------------------------------------------------------- 1130 // Generic message subclasses 1131 1132 // defined in ipc_logging.cc 1133 IPC_EXPORT void GenerateLogData(const Message& message, 1134 LogData* data, 1135 bool get_params); 1136 1137 #if defined(IPC_MESSAGE_LOG_ENABLED) 1138 inline void AddOutputParamsToLog(const Message* msg, std::string* l) { 1139 const std::string& output_params = msg->output_params(); 1140 if (!l->empty() && !output_params.empty()) 1141 l->append(", "); 1142 1143 l->append(output_params); 1144 } 1145 1146 template <class ReplyParamType> 1147 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, 1148 const Message* msg) { 1149 if (msg->received_time() != 0) { 1150 std::string output_params; 1151 LogParam(reply_params, &output_params); 1152 msg->set_output_params(output_params); 1153 } 1154 } 1155 1156 inline void ConnectMessageAndReply(const Message* msg, Message* reply) { 1157 if (msg->sent_time()) { 1158 // Don't log the sync message after dispatch, as we don't have the 1159 // output parameters at that point. Instead, save its data and log it 1160 // with the outgoing reply message when it's sent. 1161 LogData* data = new LogData; 1162 GenerateLogData(*msg, data, true); 1163 msg->set_dont_log(); 1164 reply->set_sync_log_data(data); 1165 } 1166 } 1167 #else 1168 inline void AddOutputParamsToLog(const Message* msg, std::string* l) {} 1169 1170 template <class ReplyParamType> 1171 inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, 1172 const Message* msg) {} 1173 1174 inline void ConnectMessageAndReply(const Message* msg, Message* reply) {} 1175 #endif 1176 1177 } // namespace IPC 1178 1179 #endif // IPC_IPC_MESSAGE_UTILS_H_ 1180