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 35namespace base { 36class DictionaryValue; 37class FilePath; 38class ListValue; 39class NullableString16; 40class Time; 41class TimeDelta; 42class TimeTicks; 43struct FileDescriptor; 44 45#if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) 46class SharedMemoryHandle; 47#endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) 48} 49 50namespace IPC { 51 52struct ChannelHandle; 53 54// ----------------------------------------------------------------------------- 55// How we send IPC message logs across channels. 56struct 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. 78struct NoParams { 79}; 80 81// Specializations are checked by 'IPC checker' part of find-bad-constructs 82// Clang plugin (see WriteParam() below for the details). 83template <typename... Ts> 84struct CheckedTuple { 85 typedef std::tuple<Ts...> Tuple; 86}; 87 88template <class P> 89static 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>) 101template <class P> 102static 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 107template <class P> 108static 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 115template <class P> 116static 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 123template <> 124struct 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 138template <> 139struct 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 149template <> 150struct 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 160template <> 161struct 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 171template <> 172struct 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 186template <> 187struct 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)) 214template <> 215struct 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 231template <> 232struct 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 249template <> 250struct 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 266template <> 267struct 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. 284template <> 285struct 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 299template <> 300struct 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 312template <> 313struct 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 327template <> 328struct 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 344template <> 345struct 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 355template <> 356struct 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 366template <> 367struct 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 377template <class P> 378struct 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 416template <class P> 417struct 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 450template <class K, class V, class C, class A> 451struct 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 490template <class A, class B> 491struct 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 ------------------------------------------------------------- 516template <> 517struct 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 528template <> 529struct 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. 555template<> 556struct 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) 568template <> 569struct 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 580template <> 581struct 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 591template <> 592struct 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 602template <> 603struct 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 613template <> 614struct 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 624template <> 625struct SimilarTypeTraits<base::File::Error> { 626 typedef int Type; 627}; 628 629#if defined(OS_WIN) 630template <> 631struct SimilarTypeTraits<HWND> { 632 typedef HANDLE Type; 633}; 634#endif // defined(OS_WIN) 635 636template <> 637struct 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 647template <> 648struct 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 658template <> 659struct 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 669template <> 670struct 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 683template <class A> 684struct 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 702template <class A, class B> 703struct 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 726template <class A, class B, class C> 727struct 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 755template <class A, class B, class C, class D> 756struct 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 789template <class A, class B, class C, class D, class E> 790struct 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 828template<class P> 829struct 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 861template <class P, size_t stack_capacity> 862struct 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 901template <typename NormalMap, 902 int kArraySize, 903 typename EqualKey, 904 typename MapInit> 905struct 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 946template <class P> 947struct 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 988template <class P> 989struct 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. 1030template<> 1031struct 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 1041template <> 1042struct 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 1052template <> 1053struct 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) 1064template <> 1065struct 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 1075template <> 1076struct 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 1086template <> 1087struct 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 1102IPC_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) 1108inline 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 1116template <class ReplyParamType> 1117inline 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 1126inline 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 1138inline void AddOutputParamsToLog(const Message* msg, std::string* l) {} 1139 1140template <class ReplyParamType> 1141inline void LogReplyParamsToMessage(const ReplyParamType& reply_params, 1142 const Message* msg) {} 1143 1144inline void ConnectMessageAndReply(const Message* msg, Message* reply) {} 1145#endif 1146 1147} // namespace IPC 1148 1149#endif // IPC_IPC_MESSAGE_UTILS_H_ 1150