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 #include "ipc/ipc_message_utils.h" 6 7 #include <stddef.h> 8 #include <stdint.h> 9 10 #include "base/files/file_path.h" 11 #include "base/json/json_writer.h" 12 #include "base/strings/nullable_string16.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/time/time.h" 16 #include "base/unguessable_token.h" 17 #include "base/values.h" 18 #include "build/build_config.h" 19 #include "ipc/ipc_channel_handle.h" 20 #include "ipc/ipc_message_attachment.h" 21 #include "ipc/ipc_message_attachment_set.h" 22 #include "ipc/ipc_mojo_param_traits.h" 23 24 #if defined(OS_POSIX) 25 #include "base/file_descriptor_posix.h" 26 #include "ipc/ipc_platform_file_attachment_posix.h" 27 #endif 28 29 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) 30 #include "base/memory/shared_memory_handle.h" 31 #endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) 32 33 #if defined(OS_MACOSX) && !defined(OS_IOS) 34 #include "ipc/mach_port_mac.h" 35 #endif 36 37 #if defined(OS_WIN) 38 #include <tchar.h> 39 #include "ipc/handle_win.h" 40 #endif 41 42 namespace IPC { 43 44 namespace { 45 46 const int kMaxRecursionDepth = 200; 47 48 template<typename CharType> 49 void LogBytes(const std::vector<CharType>& data, std::string* out) { 50 #if defined(OS_WIN) 51 // Windows has a GUI for logging, which can handle arbitrary binary data. 52 for (size_t i = 0; i < data.size(); ++i) 53 out->push_back(data[i]); 54 #else 55 // On POSIX, we log to stdout, which we assume can display ASCII. 56 static const size_t kMaxBytesToLog = 100; 57 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) { 58 if (isprint(data[i])) 59 out->push_back(data[i]); 60 else 61 out->append( 62 base::StringPrintf("[%02X]", static_cast<unsigned char>(data[i]))); 63 } 64 if (data.size() > kMaxBytesToLog) { 65 out->append(base::StringPrintf( 66 " and %u more bytes", 67 static_cast<unsigned>(data.size() - kMaxBytesToLog))); 68 } 69 #endif 70 } 71 72 bool ReadValue(const base::Pickle* m, 73 base::PickleIterator* iter, 74 base::Value** value, 75 int recursion); 76 77 void GetValueSize(base::PickleSizer* sizer, 78 const base::Value* value, 79 int recursion) { 80 if (recursion > kMaxRecursionDepth) { 81 LOG(ERROR) << "Max recursion depth hit in GetValueSize."; 82 return; 83 } 84 85 sizer->AddInt(); 86 switch (value->GetType()) { 87 case base::Value::Type::NONE: 88 break; 89 case base::Value::Type::BOOLEAN: 90 sizer->AddBool(); 91 break; 92 case base::Value::Type::INTEGER: 93 sizer->AddInt(); 94 break; 95 case base::Value::Type::DOUBLE: 96 sizer->AddDouble(); 97 break; 98 case base::Value::Type::STRING: { 99 const base::Value* result; 100 value->GetAsString(&result); 101 if (value->GetAsString(&result)) { 102 DCHECK(result); 103 GetParamSize(sizer, result->GetString()); 104 } else { 105 std::string str; 106 bool as_string_result = value->GetAsString(&str); 107 DCHECK(as_string_result); 108 GetParamSize(sizer, str); 109 } 110 break; 111 } 112 case base::Value::Type::BINARY: { 113 sizer->AddData(static_cast<int>(value->GetSize())); 114 break; 115 } 116 case base::Value::Type::DICTIONARY: { 117 sizer->AddInt(); 118 const base::DictionaryValue* dict = 119 static_cast<const base::DictionaryValue*>(value); 120 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); 121 it.Advance()) { 122 GetParamSize(sizer, it.key()); 123 GetValueSize(sizer, &it.value(), recursion + 1); 124 } 125 break; 126 } 127 case base::Value::Type::LIST: { 128 sizer->AddInt(); 129 const base::ListValue* list = static_cast<const base::ListValue*>(value); 130 for (const auto& entry : *list) { 131 GetValueSize(sizer, entry.get(), recursion + 1); 132 } 133 break; 134 } 135 default: 136 NOTREACHED() << "Invalid base::Value type."; 137 } 138 } 139 140 void WriteValue(base::Pickle* m, const base::Value* value, int recursion) { 141 bool result; 142 if (recursion > kMaxRecursionDepth) { 143 LOG(ERROR) << "Max recursion depth hit in WriteValue."; 144 return; 145 } 146 147 m->WriteInt(static_cast<int>(value->GetType())); 148 149 switch (value->GetType()) { 150 case base::Value::Type::NONE: 151 break; 152 case base::Value::Type::BOOLEAN: { 153 bool val; 154 result = value->GetAsBoolean(&val); 155 DCHECK(result); 156 WriteParam(m, val); 157 break; 158 } 159 case base::Value::Type::INTEGER: { 160 int val; 161 result = value->GetAsInteger(&val); 162 DCHECK(result); 163 WriteParam(m, val); 164 break; 165 } 166 case base::Value::Type::DOUBLE: { 167 double val; 168 result = value->GetAsDouble(&val); 169 DCHECK(result); 170 WriteParam(m, val); 171 break; 172 } 173 case base::Value::Type::STRING: { 174 std::string val; 175 result = value->GetAsString(&val); 176 DCHECK(result); 177 WriteParam(m, val); 178 break; 179 } 180 case base::Value::Type::BINARY: { 181 m->WriteData(value->GetBuffer(), static_cast<int>(value->GetSize())); 182 break; 183 } 184 case base::Value::Type::DICTIONARY: { 185 const base::DictionaryValue* dict = 186 static_cast<const base::DictionaryValue*>(value); 187 188 WriteParam(m, static_cast<int>(dict->size())); 189 190 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); 191 it.Advance()) { 192 WriteParam(m, it.key()); 193 WriteValue(m, &it.value(), recursion + 1); 194 } 195 break; 196 } 197 case base::Value::Type::LIST: { 198 const base::ListValue* list = static_cast<const base::ListValue*>(value); 199 WriteParam(m, static_cast<int>(list->GetSize())); 200 for (const auto& entry : *list) { 201 WriteValue(m, entry.get(), recursion + 1); 202 } 203 break; 204 } 205 } 206 } 207 208 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated 209 // object. 210 bool ReadDictionaryValue(const base::Pickle* m, 211 base::PickleIterator* iter, 212 base::DictionaryValue* value, 213 int recursion) { 214 int size; 215 if (!ReadParam(m, iter, &size)) 216 return false; 217 218 for (int i = 0; i < size; ++i) { 219 std::string key; 220 base::Value* subval; 221 if (!ReadParam(m, iter, &key) || 222 !ReadValue(m, iter, &subval, recursion + 1)) 223 return false; 224 value->SetWithoutPathExpansion(key, subval); 225 } 226 227 return true; 228 } 229 230 // Helper for ReadValue that reads a ReadListValue into a pre-allocated 231 // object. 232 bool ReadListValue(const base::Pickle* m, 233 base::PickleIterator* iter, 234 base::ListValue* value, 235 int recursion) { 236 int size; 237 if (!ReadParam(m, iter, &size)) 238 return false; 239 240 for (int i = 0; i < size; ++i) { 241 base::Value* subval; 242 if (!ReadValue(m, iter, &subval, recursion + 1)) 243 return false; 244 value->Set(i, subval); 245 } 246 247 return true; 248 } 249 250 bool ReadValue(const base::Pickle* m, 251 base::PickleIterator* iter, 252 base::Value** value, 253 int recursion) { 254 if (recursion > kMaxRecursionDepth) { 255 LOG(ERROR) << "Max recursion depth hit in ReadValue."; 256 return false; 257 } 258 259 int type; 260 if (!ReadParam(m, iter, &type)) 261 return false; 262 263 switch (static_cast<base::Value::Type>(type)) { 264 case base::Value::Type::NONE: 265 *value = base::Value::CreateNullValue().release(); 266 break; 267 case base::Value::Type::BOOLEAN: { 268 bool val; 269 if (!ReadParam(m, iter, &val)) 270 return false; 271 *value = new base::Value(val); 272 break; 273 } 274 case base::Value::Type::INTEGER: { 275 int val; 276 if (!ReadParam(m, iter, &val)) 277 return false; 278 *value = new base::Value(val); 279 break; 280 } 281 case base::Value::Type::DOUBLE: { 282 double val; 283 if (!ReadParam(m, iter, &val)) 284 return false; 285 *value = new base::Value(val); 286 break; 287 } 288 case base::Value::Type::STRING: { 289 std::string val; 290 if (!ReadParam(m, iter, &val)) 291 return false; 292 *value = new base::Value(val); 293 break; 294 } 295 case base::Value::Type::BINARY: { 296 const char* data; 297 int length; 298 if (!iter->ReadData(&data, &length)) 299 return false; 300 std::unique_ptr<base::BinaryValue> val = 301 base::BinaryValue::CreateWithCopiedBuffer(data, length); 302 *value = val.release(); 303 break; 304 } 305 case base::Value::Type::DICTIONARY: { 306 std::unique_ptr<base::DictionaryValue> val(new base::DictionaryValue()); 307 if (!ReadDictionaryValue(m, iter, val.get(), recursion)) 308 return false; 309 *value = val.release(); 310 break; 311 } 312 case base::Value::Type::LIST: { 313 std::unique_ptr<base::ListValue> val(new base::ListValue()); 314 if (!ReadListValue(m, iter, val.get(), recursion)) 315 return false; 316 *value = val.release(); 317 break; 318 } 319 default: 320 return false; 321 } 322 323 return true; 324 } 325 326 } // namespace 327 328 // ----------------------------------------------------------------------------- 329 330 LogData::LogData() 331 : routing_id(0), 332 type(0), 333 sent(0), 334 receive(0), 335 dispatch(0) { 336 } 337 338 LogData::LogData(const LogData& other) = default; 339 340 LogData::~LogData() { 341 } 342 343 void ParamTraits<bool>::Log(const param_type& p, std::string* l) { 344 l->append(p ? "true" : "false"); 345 } 346 347 void ParamTraits<signed char>::GetSize(base::PickleSizer* sizer, 348 const param_type& p) { 349 sizer->AddBytes(sizeof(param_type)); 350 } 351 352 void ParamTraits<signed char>::Write(base::Pickle* m, const param_type& p) { 353 m->WriteBytes(&p, sizeof(param_type)); 354 } 355 356 bool ParamTraits<signed char>::Read(const base::Pickle* m, 357 base::PickleIterator* iter, 358 param_type* r) { 359 const char* data; 360 if (!iter->ReadBytes(&data, sizeof(param_type))) 361 return false; 362 memcpy(r, data, sizeof(param_type)); 363 return true; 364 } 365 366 void ParamTraits<signed char>::Log(const param_type& p, std::string* l) { 367 l->append(base::IntToString(p)); 368 } 369 370 void ParamTraits<unsigned char>::GetSize(base::PickleSizer* sizer, 371 const param_type& p) { 372 sizer->AddBytes(sizeof(param_type)); 373 } 374 375 void ParamTraits<unsigned char>::Write(base::Pickle* m, const param_type& p) { 376 m->WriteBytes(&p, sizeof(param_type)); 377 } 378 379 bool ParamTraits<unsigned char>::Read(const base::Pickle* m, 380 base::PickleIterator* iter, 381 param_type* r) { 382 const char* data; 383 if (!iter->ReadBytes(&data, sizeof(param_type))) 384 return false; 385 memcpy(r, data, sizeof(param_type)); 386 return true; 387 } 388 389 void ParamTraits<unsigned char>::Log(const param_type& p, std::string* l) { 390 l->append(base::UintToString(p)); 391 } 392 393 void ParamTraits<unsigned short>::GetSize(base::PickleSizer* sizer, 394 const param_type& p) { 395 sizer->AddBytes(sizeof(param_type)); 396 } 397 398 void ParamTraits<unsigned short>::Write(base::Pickle* m, const param_type& p) { 399 m->WriteBytes(&p, sizeof(param_type)); 400 } 401 402 bool ParamTraits<unsigned short>::Read(const base::Pickle* m, 403 base::PickleIterator* iter, 404 param_type* r) { 405 const char* data; 406 if (!iter->ReadBytes(&data, sizeof(param_type))) 407 return false; 408 memcpy(r, data, sizeof(param_type)); 409 return true; 410 } 411 412 void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) { 413 l->append(base::UintToString(p)); 414 } 415 416 void ParamTraits<int>::Log(const param_type& p, std::string* l) { 417 l->append(base::IntToString(p)); 418 } 419 420 void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) { 421 l->append(base::UintToString(p)); 422 } 423 424 #if defined(OS_WIN) || defined(OS_LINUX) || \ 425 (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS)) 426 void ParamTraits<long>::Log(const param_type& p, std::string* l) { 427 l->append(base::Int64ToString(static_cast<int64_t>(p))); 428 } 429 430 void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) { 431 l->append(base::Uint64ToString(static_cast<uint64_t>(p))); 432 } 433 #endif 434 435 void ParamTraits<long long>::Log(const param_type& p, std::string* l) { 436 l->append(base::Int64ToString(static_cast<int64_t>(p))); 437 } 438 439 void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) { 440 l->append(base::Uint64ToString(p)); 441 } 442 443 void ParamTraits<float>::Log(const param_type& p, std::string* l) { 444 l->append(base::StringPrintf("%e", p)); 445 } 446 447 void ParamTraits<double>::GetSize(base::PickleSizer* sizer, 448 const param_type& p) { 449 sizer->AddBytes(sizeof(param_type)); 450 } 451 452 void ParamTraits<double>::Write(base::Pickle* m, const param_type& p) { 453 m->WriteBytes(reinterpret_cast<const char*>(&p), sizeof(param_type)); 454 } 455 456 bool ParamTraits<double>::Read(const base::Pickle* m, 457 base::PickleIterator* iter, 458 param_type* r) { 459 const char *data; 460 if (!iter->ReadBytes(&data, sizeof(*r))) { 461 NOTREACHED(); 462 return false; 463 } 464 memcpy(r, data, sizeof(param_type)); 465 return true; 466 } 467 468 void ParamTraits<double>::Log(const param_type& p, std::string* l) { 469 l->append(base::StringPrintf("%e", p)); 470 } 471 472 473 void ParamTraits<std::string>::Log(const param_type& p, std::string* l) { 474 l->append(p); 475 } 476 477 void ParamTraits<base::string16>::Log(const param_type& p, std::string* l) { 478 l->append(base::UTF16ToUTF8(p)); 479 } 480 481 void ParamTraits<std::vector<char>>::GetSize(base::PickleSizer* sizer, 482 const param_type& p) { 483 sizer->AddData(static_cast<int>(p.size())); 484 } 485 486 void ParamTraits<std::vector<char>>::Write(base::Pickle* m, 487 const param_type& p) { 488 if (p.empty()) { 489 m->WriteData(NULL, 0); 490 } else { 491 m->WriteData(&p.front(), static_cast<int>(p.size())); 492 } 493 } 494 495 bool ParamTraits<std::vector<char>>::Read(const base::Pickle* m, 496 base::PickleIterator* iter, 497 param_type* r) { 498 const char *data; 499 int data_size = 0; 500 if (!iter->ReadData(&data, &data_size) || data_size < 0) 501 return false; 502 r->resize(data_size); 503 if (data_size) 504 memcpy(&r->front(), data, data_size); 505 return true; 506 } 507 508 void ParamTraits<std::vector<char> >::Log(const param_type& p, std::string* l) { 509 LogBytes(p, l); 510 } 511 512 void ParamTraits<std::vector<unsigned char>>::GetSize(base::PickleSizer* sizer, 513 const param_type& p) { 514 sizer->AddData(static_cast<int>(p.size())); 515 } 516 517 void ParamTraits<std::vector<unsigned char>>::Write(base::Pickle* m, 518 const param_type& p) { 519 if (p.empty()) { 520 m->WriteData(NULL, 0); 521 } else { 522 m->WriteData(reinterpret_cast<const char*>(&p.front()), 523 static_cast<int>(p.size())); 524 } 525 } 526 527 bool ParamTraits<std::vector<unsigned char>>::Read(const base::Pickle* m, 528 base::PickleIterator* iter, 529 param_type* r) { 530 const char *data; 531 int data_size = 0; 532 if (!iter->ReadData(&data, &data_size) || data_size < 0) 533 return false; 534 r->resize(data_size); 535 if (data_size) 536 memcpy(&r->front(), data, data_size); 537 return true; 538 } 539 540 void ParamTraits<std::vector<unsigned char> >::Log(const param_type& p, 541 std::string* l) { 542 LogBytes(p, l); 543 } 544 545 void ParamTraits<std::vector<bool>>::GetSize(base::PickleSizer* sizer, 546 const param_type& p) { 547 GetParamSize(sizer, static_cast<int>(p.size())); 548 for (size_t i = 0; i < p.size(); ++i) 549 GetParamSize(sizer, static_cast<bool>(p[i])); 550 } 551 552 void ParamTraits<std::vector<bool>>::Write(base::Pickle* m, 553 const param_type& p) { 554 WriteParam(m, static_cast<int>(p.size())); 555 // Cast to bool below is required because libc++'s 556 // vector<bool>::const_reference is different from bool, and we want to avoid 557 // writing an extra specialization of ParamTraits for it. 558 for (size_t i = 0; i < p.size(); i++) 559 WriteParam(m, static_cast<bool>(p[i])); 560 } 561 562 bool ParamTraits<std::vector<bool>>::Read(const base::Pickle* m, 563 base::PickleIterator* iter, 564 param_type* r) { 565 int size; 566 // ReadLength() checks for < 0 itself. 567 if (!iter->ReadLength(&size)) 568 return false; 569 r->resize(size); 570 for (int i = 0; i < size; i++) { 571 bool value; 572 if (!ReadParam(m, iter, &value)) 573 return false; 574 (*r)[i] = value; 575 } 576 return true; 577 } 578 579 void ParamTraits<std::vector<bool> >::Log(const param_type& p, std::string* l) { 580 for (size_t i = 0; i < p.size(); ++i) { 581 if (i != 0) 582 l->push_back(' '); 583 LogParam(static_cast<bool>(p[i]), l); 584 } 585 } 586 587 void ParamTraits<base::DictionaryValue>::GetSize(base::PickleSizer* sizer, 588 const param_type& p) { 589 GetValueSize(sizer, &p, 0); 590 } 591 592 void ParamTraits<base::DictionaryValue>::Write(base::Pickle* m, 593 const param_type& p) { 594 WriteValue(m, &p, 0); 595 } 596 597 bool ParamTraits<base::DictionaryValue>::Read(const base::Pickle* m, 598 base::PickleIterator* iter, 599 param_type* r) { 600 int type; 601 if (!ReadParam(m, iter, &type) || 602 type != static_cast<int>(base::Value::Type::DICTIONARY)) 603 return false; 604 605 return ReadDictionaryValue(m, iter, r, 0); 606 } 607 608 void ParamTraits<base::DictionaryValue>::Log(const param_type& p, 609 std::string* l) { 610 std::string json; 611 base::JSONWriter::Write(p, &json); 612 l->append(json); 613 } 614 615 #if defined(OS_POSIX) 616 void ParamTraits<base::FileDescriptor>::GetSize(base::PickleSizer* sizer, 617 const param_type& p) { 618 GetParamSize(sizer, p.fd >= 0); 619 if (p.fd >= 0) 620 sizer->AddAttachment(); 621 } 622 623 void ParamTraits<base::FileDescriptor>::Write(base::Pickle* m, 624 const param_type& p) { 625 const bool valid = p.fd >= 0; 626 WriteParam(m, valid); 627 628 if (!valid) 629 return; 630 631 if (p.auto_close) { 632 if (!m->WriteAttachment( 633 new internal::PlatformFileAttachment(base::ScopedFD(p.fd)))) 634 NOTREACHED(); 635 } else { 636 if (!m->WriteAttachment(new internal::PlatformFileAttachment(p.fd))) 637 NOTREACHED(); 638 } 639 } 640 641 bool ParamTraits<base::FileDescriptor>::Read(const base::Pickle* m, 642 base::PickleIterator* iter, 643 param_type* r) { 644 *r = base::FileDescriptor(); 645 646 bool valid; 647 if (!ReadParam(m, iter, &valid)) 648 return false; 649 650 // TODO(morrita): Seems like this should return false. 651 if (!valid) 652 return true; 653 654 scoped_refptr<base::Pickle::Attachment> attachment; 655 if (!m->ReadAttachment(iter, &attachment)) 656 return false; 657 658 if (static_cast<MessageAttachment*>(attachment.get())->GetType() != 659 MessageAttachment::Type::PLATFORM_FILE) { 660 return false; 661 } 662 663 *r = base::FileDescriptor( 664 static_cast<internal::PlatformFileAttachment*>(attachment.get()) 665 ->TakePlatformFile(), 666 true); 667 return true; 668 } 669 670 void ParamTraits<base::FileDescriptor>::Log(const param_type& p, 671 std::string* l) { 672 if (p.auto_close) { 673 l->append(base::StringPrintf("FD(%d auto-close)", p.fd)); 674 } else { 675 l->append(base::StringPrintf("FD(%d)", p.fd)); 676 } 677 } 678 #endif // defined(OS_POSIX) 679 680 #if defined(OS_MACOSX) && !defined(OS_IOS) 681 void ParamTraits<base::SharedMemoryHandle>::GetSize(base::PickleSizer* sizer, 682 const param_type& p) { 683 GetParamSize(sizer, p.GetMemoryObject()); 684 uint32_t dummy = 0; 685 GetParamSize(sizer, dummy); 686 } 687 688 void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m, 689 const param_type& p) { 690 MachPortMac mach_port_mac(p.GetMemoryObject()); 691 ParamTraits<MachPortMac>::Write(m, mach_port_mac); 692 size_t size = 0; 693 bool result = p.GetSize(&size); 694 DCHECK(result); 695 ParamTraits<uint32_t>::Write(m, static_cast<uint32_t>(size)); 696 697 // If the caller intended to pass ownership to the IPC stack, release a 698 // reference. 699 if (p.OwnershipPassesToIPC()) 700 p.Close(); 701 } 702 703 bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m, 704 base::PickleIterator* iter, 705 param_type* r) { 706 MachPortMac mach_port_mac; 707 if (!ParamTraits<MachPortMac>::Read(m, iter, &mach_port_mac)) 708 return false; 709 710 uint32_t size; 711 if (!ParamTraits<uint32_t>::Read(m, iter, &size)) 712 return false; 713 714 *r = base::SharedMemoryHandle(mach_port_mac.get_mach_port(), 715 static_cast<size_t>(size), 716 base::GetCurrentProcId()); 717 return true; 718 } 719 720 void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p, 721 std::string* l) { 722 l->append("Mach port: "); 723 LogParam(p.GetMemoryObject(), l); 724 } 725 726 #elif defined(OS_WIN) 727 void ParamTraits<base::SharedMemoryHandle>::GetSize(base::PickleSizer* s, 728 const param_type& p) { 729 GetParamSize(s, p.NeedsBrokering()); 730 if (p.NeedsBrokering()) { 731 GetParamSize(s, p.GetHandle()); 732 } else { 733 GetParamSize(s, HandleToLong(p.GetHandle())); 734 } 735 } 736 737 void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m, 738 const param_type& p) { 739 m->WriteBool(p.NeedsBrokering()); 740 741 if (p.NeedsBrokering()) { 742 HandleWin handle_win(p.GetHandle(), HandleWin::DUPLICATE); 743 ParamTraits<HandleWin>::Write(m, handle_win); 744 745 // If the caller intended to pass ownership to the IPC stack, release a 746 // reference. 747 if (p.OwnershipPassesToIPC() && p.BelongsToCurrentProcess()) 748 p.Close(); 749 } else { 750 m->WriteInt(HandleToLong(p.GetHandle())); 751 } 752 } 753 754 bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m, 755 base::PickleIterator* iter, 756 param_type* r) { 757 bool needs_brokering; 758 if (!iter->ReadBool(&needs_brokering)) 759 return false; 760 761 if (needs_brokering) { 762 HandleWin handle_win; 763 if (!ParamTraits<HandleWin>::Read(m, iter, &handle_win)) 764 return false; 765 *r = base::SharedMemoryHandle(handle_win.get_handle(), 766 base::GetCurrentProcId()); 767 return true; 768 } 769 770 int handle_int; 771 if (!iter->ReadInt(&handle_int)) 772 return false; 773 HANDLE handle = LongToHandle(handle_int); 774 *r = base::SharedMemoryHandle(handle, base::GetCurrentProcId()); 775 return true; 776 } 777 778 void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p, 779 std::string* l) { 780 LogParam(p.GetHandle(), l); 781 l->append(" needs brokering: "); 782 LogParam(p.NeedsBrokering(), l); 783 } 784 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 785 786 void ParamTraits<base::FilePath>::GetSize(base::PickleSizer* sizer, 787 const param_type& p) { 788 p.GetSizeForPickle(sizer); 789 } 790 791 void ParamTraits<base::FilePath>::Write(base::Pickle* m, const param_type& p) { 792 p.WriteToPickle(m); 793 } 794 795 bool ParamTraits<base::FilePath>::Read(const base::Pickle* m, 796 base::PickleIterator* iter, 797 param_type* r) { 798 return r->ReadFromPickle(iter); 799 } 800 801 void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) { 802 ParamTraits<base::FilePath::StringType>::Log(p.value(), l); 803 } 804 805 void ParamTraits<base::ListValue>::GetSize(base::PickleSizer* sizer, 806 const param_type& p) { 807 GetValueSize(sizer, &p, 0); 808 } 809 810 void ParamTraits<base::ListValue>::Write(base::Pickle* m, const param_type& p) { 811 WriteValue(m, &p, 0); 812 } 813 814 bool ParamTraits<base::ListValue>::Read(const base::Pickle* m, 815 base::PickleIterator* iter, 816 param_type* r) { 817 int type; 818 if (!ReadParam(m, iter, &type) || 819 type != static_cast<int>(base::Value::Type::LIST)) 820 return false; 821 822 return ReadListValue(m, iter, r, 0); 823 } 824 825 void ParamTraits<base::ListValue>::Log(const param_type& p, std::string* l) { 826 std::string json; 827 base::JSONWriter::Write(p, &json); 828 l->append(json); 829 } 830 831 void ParamTraits<base::NullableString16>::GetSize(base::PickleSizer* sizer, 832 const param_type& p) { 833 GetParamSize(sizer, p.string()); 834 GetParamSize(sizer, p.is_null()); 835 } 836 837 void ParamTraits<base::NullableString16>::Write(base::Pickle* m, 838 const param_type& p) { 839 WriteParam(m, p.string()); 840 WriteParam(m, p.is_null()); 841 } 842 843 bool ParamTraits<base::NullableString16>::Read(const base::Pickle* m, 844 base::PickleIterator* iter, 845 param_type* r) { 846 base::string16 string; 847 if (!ReadParam(m, iter, &string)) 848 return false; 849 bool is_null; 850 if (!ReadParam(m, iter, &is_null)) 851 return false; 852 *r = base::NullableString16(string, is_null); 853 return true; 854 } 855 856 void ParamTraits<base::NullableString16>::Log(const param_type& p, 857 std::string* l) { 858 l->append("("); 859 LogParam(p.string(), l); 860 l->append(", "); 861 LogParam(p.is_null(), l); 862 l->append(")"); 863 } 864 865 void ParamTraits<base::File::Info>::GetSize(base::PickleSizer* sizer, 866 const param_type& p) { 867 GetParamSize(sizer, p.size); 868 GetParamSize(sizer, p.is_directory); 869 GetParamSize(sizer, p.last_modified.ToDoubleT()); 870 GetParamSize(sizer, p.last_accessed.ToDoubleT()); 871 GetParamSize(sizer, p.creation_time.ToDoubleT()); 872 } 873 874 void ParamTraits<base::File::Info>::Write(base::Pickle* m, 875 const param_type& p) { 876 WriteParam(m, p.size); 877 WriteParam(m, p.is_directory); 878 WriteParam(m, p.last_modified.ToDoubleT()); 879 WriteParam(m, p.last_accessed.ToDoubleT()); 880 WriteParam(m, p.creation_time.ToDoubleT()); 881 } 882 883 bool ParamTraits<base::File::Info>::Read(const base::Pickle* m, 884 base::PickleIterator* iter, 885 param_type* p) { 886 double last_modified, last_accessed, creation_time; 887 if (!ReadParam(m, iter, &p->size) || 888 !ReadParam(m, iter, &p->is_directory) || 889 !ReadParam(m, iter, &last_modified) || 890 !ReadParam(m, iter, &last_accessed) || 891 !ReadParam(m, iter, &creation_time)) 892 return false; 893 p->last_modified = base::Time::FromDoubleT(last_modified); 894 p->last_accessed = base::Time::FromDoubleT(last_accessed); 895 p->creation_time = base::Time::FromDoubleT(creation_time); 896 return true; 897 } 898 899 void ParamTraits<base::File::Info>::Log(const param_type& p, 900 std::string* l) { 901 l->append("("); 902 LogParam(p.size, l); 903 l->append(","); 904 LogParam(p.is_directory, l); 905 l->append(","); 906 LogParam(p.last_modified.ToDoubleT(), l); 907 l->append(","); 908 LogParam(p.last_accessed.ToDoubleT(), l); 909 l->append(","); 910 LogParam(p.creation_time.ToDoubleT(), l); 911 l->append(")"); 912 } 913 914 void ParamTraits<base::Time>::GetSize(base::PickleSizer* sizer, 915 const param_type& p) { 916 sizer->AddInt64(); 917 } 918 919 void ParamTraits<base::Time>::Write(base::Pickle* m, const param_type& p) { 920 ParamTraits<int64_t>::Write(m, p.ToInternalValue()); 921 } 922 923 bool ParamTraits<base::Time>::Read(const base::Pickle* m, 924 base::PickleIterator* iter, 925 param_type* r) { 926 int64_t value; 927 if (!ParamTraits<int64_t>::Read(m, iter, &value)) 928 return false; 929 *r = base::Time::FromInternalValue(value); 930 return true; 931 } 932 933 void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) { 934 ParamTraits<int64_t>::Log(p.ToInternalValue(), l); 935 } 936 937 void ParamTraits<base::TimeDelta>::GetSize(base::PickleSizer* sizer, 938 const param_type& p) { 939 sizer->AddInt64(); 940 } 941 942 void ParamTraits<base::TimeDelta>::Write(base::Pickle* m, const param_type& p) { 943 ParamTraits<int64_t>::Write(m, p.ToInternalValue()); 944 } 945 946 bool ParamTraits<base::TimeDelta>::Read(const base::Pickle* m, 947 base::PickleIterator* iter, 948 param_type* r) { 949 int64_t value; 950 bool ret = ParamTraits<int64_t>::Read(m, iter, &value); 951 if (ret) 952 *r = base::TimeDelta::FromInternalValue(value); 953 954 return ret; 955 } 956 957 void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) { 958 ParamTraits<int64_t>::Log(p.ToInternalValue(), l); 959 } 960 961 void ParamTraits<base::TimeTicks>::GetSize(base::PickleSizer* sizer, 962 const param_type& p) { 963 sizer->AddInt64(); 964 } 965 966 void ParamTraits<base::TimeTicks>::Write(base::Pickle* m, const param_type& p) { 967 ParamTraits<int64_t>::Write(m, p.ToInternalValue()); 968 } 969 970 bool ParamTraits<base::TimeTicks>::Read(const base::Pickle* m, 971 base::PickleIterator* iter, 972 param_type* r) { 973 int64_t value; 974 bool ret = ParamTraits<int64_t>::Read(m, iter, &value); 975 if (ret) 976 *r = base::TimeTicks::FromInternalValue(value); 977 978 return ret; 979 } 980 981 void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) { 982 ParamTraits<int64_t>::Log(p.ToInternalValue(), l); 983 } 984 985 // If base::UnguessableToken is no longer 128 bits, the IPC serialization logic 986 // below should be updated. 987 static_assert(sizeof(base::UnguessableToken) == 2 * sizeof(uint64_t), 988 "base::UnguessableToken should be of size 2 * sizeof(uint64_t)."); 989 990 void ParamTraits<base::UnguessableToken>::GetSize(base::PickleSizer* sizer, 991 const param_type& p) { 992 sizer->AddBytes(2 * sizeof(uint64_t)); 993 } 994 995 void ParamTraits<base::UnguessableToken>::Write(base::Pickle* m, 996 const param_type& p) { 997 DCHECK(!p.is_empty()); 998 999 ParamTraits<uint64_t>::Write(m, p.GetHighForSerialization()); 1000 ParamTraits<uint64_t>::Write(m, p.GetLowForSerialization()); 1001 } 1002 1003 bool ParamTraits<base::UnguessableToken>::Read(const base::Pickle* m, 1004 base::PickleIterator* iter, 1005 param_type* r) { 1006 uint64_t high, low; 1007 if (!ParamTraits<uint64_t>::Read(m, iter, &high) || 1008 !ParamTraits<uint64_t>::Read(m, iter, &low)) 1009 return false; 1010 1011 // Receiving a zeroed UnguessableToken is a security issue. 1012 if (high == 0 && low == 0) 1013 return false; 1014 1015 *r = base::UnguessableToken::Deserialize(high, low); 1016 return true; 1017 } 1018 1019 void ParamTraits<base::UnguessableToken>::Log(const param_type& p, 1020 std::string* l) { 1021 l->append(p.ToString()); 1022 } 1023 1024 void ParamTraits<IPC::ChannelHandle>::GetSize(base::PickleSizer* sizer, 1025 const param_type& p) { 1026 #if defined(OS_NACL_SFI) 1027 GetParamSize(sizer, p.socket); 1028 #else 1029 GetParamSize(sizer, p.mojo_handle); 1030 #endif 1031 } 1032 1033 void ParamTraits<IPC::ChannelHandle>::Write(base::Pickle* m, 1034 const param_type& p) { 1035 #if defined(OS_NACL_SFI) 1036 WriteParam(m, p.socket); 1037 #else 1038 WriteParam(m, p.mojo_handle); 1039 #endif 1040 } 1041 1042 bool ParamTraits<IPC::ChannelHandle>::Read(const base::Pickle* m, 1043 base::PickleIterator* iter, 1044 param_type* r) { 1045 #if defined(OS_NACL_SFI) 1046 return ReadParam(m, iter, &r->socket); 1047 #else 1048 return ReadParam(m, iter, &r->mojo_handle); 1049 #endif 1050 } 1051 1052 void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p, 1053 std::string* l) { 1054 l->append("ChannelHandle("); 1055 #if defined(OS_NACL_SFI) 1056 ParamTraits<base::FileDescriptor>::Log(p.socket, l); 1057 #else 1058 LogParam(p.mojo_handle, l); 1059 #endif 1060 l->append(")"); 1061 } 1062 1063 void ParamTraits<LogData>::GetSize(base::PickleSizer* sizer, 1064 const param_type& p) { 1065 GetParamSize(sizer, p.channel); 1066 GetParamSize(sizer, p.routing_id); 1067 GetParamSize(sizer, p.type); 1068 GetParamSize(sizer, p.flags); 1069 GetParamSize(sizer, p.sent); 1070 GetParamSize(sizer, p.receive); 1071 GetParamSize(sizer, p.dispatch); 1072 GetParamSize(sizer, p.message_name); 1073 GetParamSize(sizer, p.params); 1074 } 1075 1076 void ParamTraits<LogData>::Write(base::Pickle* m, const param_type& p) { 1077 WriteParam(m, p.channel); 1078 WriteParam(m, p.routing_id); 1079 WriteParam(m, p.type); 1080 WriteParam(m, p.flags); 1081 WriteParam(m, p.sent); 1082 WriteParam(m, p.receive); 1083 WriteParam(m, p.dispatch); 1084 WriteParam(m, p.message_name); 1085 WriteParam(m, p.params); 1086 } 1087 1088 bool ParamTraits<LogData>::Read(const base::Pickle* m, 1089 base::PickleIterator* iter, 1090 param_type* r) { 1091 return 1092 ReadParam(m, iter, &r->channel) && 1093 ReadParam(m, iter, &r->routing_id) && 1094 ReadParam(m, iter, &r->type) && 1095 ReadParam(m, iter, &r->flags) && 1096 ReadParam(m, iter, &r->sent) && 1097 ReadParam(m, iter, &r->receive) && 1098 ReadParam(m, iter, &r->dispatch) && 1099 ReadParam(m, iter, &r->message_name) && 1100 ReadParam(m, iter, &r->params); 1101 } 1102 1103 void ParamTraits<LogData>::Log(const param_type& p, std::string* l) { 1104 // Doesn't make sense to implement this! 1105 } 1106 1107 void ParamTraits<Message>::Write(base::Pickle* m, const Message& p) { 1108 #if defined(OS_POSIX) 1109 // We don't serialize the file descriptors in the nested message, so there 1110 // better not be any. 1111 DCHECK(!p.HasAttachments()); 1112 #endif 1113 1114 // Don't just write out the message. This is used to send messages between 1115 // NaCl (Posix environment) and the browser (could be on Windows). The message 1116 // header formats differ between these systems (so does handle sharing, but 1117 // we already asserted we don't have any handles). So just write out the 1118 // parts of the header we use. 1119 // 1120 // Be careful also to use only explicitly-sized types. The NaCl environment 1121 // could be 64-bit and the host browser could be 32-bits. The nested message 1122 // may or may not be safe to send between 32-bit and 64-bit systems, but we 1123 // leave that up to the code sending the message to ensure. 1124 m->WriteUInt32(static_cast<uint32_t>(p.routing_id())); 1125 m->WriteUInt32(p.type()); 1126 m->WriteUInt32(p.flags()); 1127 m->WriteData(p.payload(), static_cast<uint32_t>(p.payload_size())); 1128 } 1129 1130 bool ParamTraits<Message>::Read(const base::Pickle* m, 1131 base::PickleIterator* iter, 1132 Message* r) { 1133 uint32_t routing_id, type, flags; 1134 if (!iter->ReadUInt32(&routing_id) || 1135 !iter->ReadUInt32(&type) || 1136 !iter->ReadUInt32(&flags)) 1137 return false; 1138 1139 int payload_size; 1140 const char* payload; 1141 if (!iter->ReadData(&payload, &payload_size)) 1142 return false; 1143 1144 r->SetHeaderValues(static_cast<int32_t>(routing_id), type, flags); 1145 return r->WriteBytes(payload, payload_size); 1146 } 1147 1148 void ParamTraits<Message>::Log(const Message& p, std::string* l) { 1149 l->append("<IPC::Message>"); 1150 } 1151 1152 #if defined(OS_WIN) 1153 void ParamTraits<HANDLE>::GetSize(base::PickleSizer* sizer, 1154 const param_type& p) { 1155 sizer->AddInt(); 1156 } 1157 1158 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64 1159 // bit systems. That's why we use the Windows macros to convert to 32 bits. 1160 void ParamTraits<HANDLE>::Write(base::Pickle* m, const param_type& p) { 1161 m->WriteInt(HandleToLong(p)); 1162 } 1163 1164 bool ParamTraits<HANDLE>::Read(const base::Pickle* m, 1165 base::PickleIterator* iter, 1166 param_type* r) { 1167 int32_t temp; 1168 if (!iter->ReadInt(&temp)) 1169 return false; 1170 *r = LongToHandle(temp); 1171 return true; 1172 } 1173 1174 void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) { 1175 l->append(base::StringPrintf("0x%p", p)); 1176 } 1177 1178 void ParamTraits<LOGFONT>::GetSize(base::PickleSizer* sizer, 1179 const param_type& p) { 1180 sizer->AddData(sizeof(LOGFONT)); 1181 } 1182 1183 void ParamTraits<LOGFONT>::Write(base::Pickle* m, const param_type& p) { 1184 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT)); 1185 } 1186 1187 bool ParamTraits<LOGFONT>::Read(const base::Pickle* m, 1188 base::PickleIterator* iter, 1189 param_type* r) { 1190 const char *data; 1191 int data_size = 0; 1192 if (iter->ReadData(&data, &data_size) && data_size == sizeof(LOGFONT)) { 1193 const LOGFONT *font = reinterpret_cast<LOGFONT*>(const_cast<char*>(data)); 1194 if (_tcsnlen(font->lfFaceName, LF_FACESIZE) < LF_FACESIZE) { 1195 memcpy(r, data, sizeof(LOGFONT)); 1196 return true; 1197 } 1198 } 1199 1200 NOTREACHED(); 1201 return false; 1202 } 1203 1204 void ParamTraits<LOGFONT>::Log(const param_type& p, std::string* l) { 1205 l->append(base::StringPrintf("<LOGFONT>")); 1206 } 1207 1208 void ParamTraits<MSG>::GetSize(base::PickleSizer* sizer, const param_type& p) { 1209 sizer->AddData(sizeof(MSG)); 1210 } 1211 1212 void ParamTraits<MSG>::Write(base::Pickle* m, const param_type& p) { 1213 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG)); 1214 } 1215 1216 bool ParamTraits<MSG>::Read(const base::Pickle* m, 1217 base::PickleIterator* iter, 1218 param_type* r) { 1219 const char *data; 1220 int data_size = 0; 1221 bool result = iter->ReadData(&data, &data_size); 1222 if (result && data_size == sizeof(MSG)) { 1223 memcpy(r, data, sizeof(MSG)); 1224 } else { 1225 result = false; 1226 NOTREACHED(); 1227 } 1228 1229 return result; 1230 } 1231 1232 void ParamTraits<MSG>::Log(const param_type& p, std::string* l) { 1233 l->append("<MSG>"); 1234 } 1235 1236 #endif // OS_WIN 1237 1238 } // namespace IPC 1239