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 "base/files/file_path.h" 8 #include "base/json/json_writer.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/strings/nullable_string16.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "base/time/time.h" 14 #include "base/values.h" 15 #include "ipc/ipc_channel_handle.h" 16 17 #if defined(OS_POSIX) 18 #include "ipc/file_descriptor_set_posix.h" 19 #elif defined(OS_WIN) 20 #include <tchar.h> 21 #endif 22 23 namespace IPC { 24 25 namespace { 26 27 const int kMaxRecursionDepth = 100; 28 29 template<typename CharType> 30 void LogBytes(const std::vector<CharType>& data, std::string* out) { 31 #if defined(OS_WIN) 32 // Windows has a GUI for logging, which can handle arbitrary binary data. 33 for (size_t i = 0; i < data.size(); ++i) 34 out->push_back(data[i]); 35 #else 36 // On POSIX, we log to stdout, which we assume can display ASCII. 37 static const size_t kMaxBytesToLog = 100; 38 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) { 39 if (isprint(data[i])) 40 out->push_back(data[i]); 41 else 42 out->append( 43 base::StringPrintf("[%02X]", static_cast<unsigned char>(data[i]))); 44 } 45 if (data.size() > kMaxBytesToLog) { 46 out->append(base::StringPrintf( 47 " and %u more bytes", 48 static_cast<unsigned>(data.size() - kMaxBytesToLog))); 49 } 50 #endif 51 } 52 53 bool ReadValue(const Message* m, PickleIterator* iter, base::Value** value, 54 int recursion); 55 56 void WriteValue(Message* m, const base::Value* value, int recursion) { 57 bool result; 58 if (recursion > kMaxRecursionDepth) { 59 LOG(WARNING) << "Max recursion depth hit in WriteValue."; 60 return; 61 } 62 63 m->WriteInt(value->GetType()); 64 65 switch (value->GetType()) { 66 case base::Value::TYPE_NULL: 67 break; 68 case base::Value::TYPE_BOOLEAN: { 69 bool val; 70 result = value->GetAsBoolean(&val); 71 DCHECK(result); 72 WriteParam(m, val); 73 break; 74 } 75 case base::Value::TYPE_INTEGER: { 76 int val; 77 result = value->GetAsInteger(&val); 78 DCHECK(result); 79 WriteParam(m, val); 80 break; 81 } 82 case base::Value::TYPE_DOUBLE: { 83 double val; 84 result = value->GetAsDouble(&val); 85 DCHECK(result); 86 WriteParam(m, val); 87 break; 88 } 89 case base::Value::TYPE_STRING: { 90 std::string val; 91 result = value->GetAsString(&val); 92 DCHECK(result); 93 WriteParam(m, val); 94 break; 95 } 96 case base::Value::TYPE_BINARY: { 97 const base::BinaryValue* binary = 98 static_cast<const base::BinaryValue*>(value); 99 m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize())); 100 break; 101 } 102 case base::Value::TYPE_DICTIONARY: { 103 const base::DictionaryValue* dict = 104 static_cast<const base::DictionaryValue*>(value); 105 106 WriteParam(m, static_cast<int>(dict->size())); 107 108 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); 109 it.Advance()) { 110 WriteParam(m, it.key()); 111 WriteValue(m, &it.value(), recursion + 1); 112 } 113 break; 114 } 115 case base::Value::TYPE_LIST: { 116 const base::ListValue* list = static_cast<const base::ListValue*>(value); 117 WriteParam(m, static_cast<int>(list->GetSize())); 118 for (base::ListValue::const_iterator it = list->begin(); 119 it != list->end(); ++it) { 120 WriteValue(m, *it, recursion + 1); 121 } 122 break; 123 } 124 } 125 } 126 127 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated 128 // object. 129 bool ReadDictionaryValue(const Message* m, PickleIterator* iter, 130 base::DictionaryValue* value, int recursion) { 131 int size; 132 if (!ReadParam(m, iter, &size)) 133 return false; 134 135 for (int i = 0; i < size; ++i) { 136 std::string key; 137 base::Value* subval; 138 if (!ReadParam(m, iter, &key) || 139 !ReadValue(m, iter, &subval, recursion + 1)) 140 return false; 141 value->SetWithoutPathExpansion(key, subval); 142 } 143 144 return true; 145 } 146 147 // Helper for ReadValue that reads a ReadListValue into a pre-allocated 148 // object. 149 bool ReadListValue(const Message* m, PickleIterator* iter, 150 base::ListValue* value, int recursion) { 151 int size; 152 if (!ReadParam(m, iter, &size)) 153 return false; 154 155 for (int i = 0; i < size; ++i) { 156 base::Value* subval; 157 if (!ReadValue(m, iter, &subval, recursion + 1)) 158 return false; 159 value->Set(i, subval); 160 } 161 162 return true; 163 } 164 165 bool ReadValue(const Message* m, PickleIterator* iter, base::Value** value, 166 int recursion) { 167 if (recursion > kMaxRecursionDepth) { 168 LOG(WARNING) << "Max recursion depth hit in ReadValue."; 169 return false; 170 } 171 172 int type; 173 if (!ReadParam(m, iter, &type)) 174 return false; 175 176 switch (type) { 177 case base::Value::TYPE_NULL: 178 *value = base::Value::CreateNullValue(); 179 break; 180 case base::Value::TYPE_BOOLEAN: { 181 bool val; 182 if (!ReadParam(m, iter, &val)) 183 return false; 184 *value = new base::FundamentalValue(val); 185 break; 186 } 187 case base::Value::TYPE_INTEGER: { 188 int val; 189 if (!ReadParam(m, iter, &val)) 190 return false; 191 *value = new base::FundamentalValue(val); 192 break; 193 } 194 case base::Value::TYPE_DOUBLE: { 195 double val; 196 if (!ReadParam(m, iter, &val)) 197 return false; 198 *value = new base::FundamentalValue(val); 199 break; 200 } 201 case base::Value::TYPE_STRING: { 202 std::string val; 203 if (!ReadParam(m, iter, &val)) 204 return false; 205 *value = new base::StringValue(val); 206 break; 207 } 208 case base::Value::TYPE_BINARY: { 209 const char* data; 210 int length; 211 if (!m->ReadData(iter, &data, &length)) 212 return false; 213 *value = base::BinaryValue::CreateWithCopiedBuffer(data, length); 214 break; 215 } 216 case base::Value::TYPE_DICTIONARY: { 217 scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue()); 218 if (!ReadDictionaryValue(m, iter, val.get(), recursion)) 219 return false; 220 *value = val.release(); 221 break; 222 } 223 case base::Value::TYPE_LIST: { 224 scoped_ptr<base::ListValue> val(new base::ListValue()); 225 if (!ReadListValue(m, iter, val.get(), recursion)) 226 return false; 227 *value = val.release(); 228 break; 229 } 230 default: 231 return false; 232 } 233 234 return true; 235 } 236 237 } // namespace 238 239 // ----------------------------------------------------------------------------- 240 241 LogData::LogData() 242 : routing_id(0), 243 type(0), 244 sent(0), 245 receive(0), 246 dispatch(0) { 247 } 248 249 LogData::~LogData() { 250 } 251 252 void ParamTraits<bool>::Log(const param_type& p, std::string* l) { 253 l->append(p ? "true" : "false"); 254 } 255 256 void ParamTraits<unsigned char>::Write(Message* m, const param_type& p) { 257 m->WriteBytes(&p, sizeof(param_type)); 258 } 259 260 bool ParamTraits<unsigned char>::Read(const Message* m, PickleIterator* iter, 261 param_type* r) { 262 const char* data; 263 if (!m->ReadBytes(iter, &data, sizeof(param_type))) 264 return false; 265 memcpy(r, data, sizeof(param_type)); 266 return true; 267 } 268 269 void ParamTraits<unsigned char>::Log(const param_type& p, std::string* l) { 270 l->append(base::UintToString(p)); 271 } 272 273 void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) { 274 m->WriteBytes(&p, sizeof(param_type)); 275 } 276 277 bool ParamTraits<unsigned short>::Read(const Message* m, PickleIterator* iter, 278 param_type* r) { 279 const char* data; 280 if (!m->ReadBytes(iter, &data, sizeof(param_type))) 281 return false; 282 memcpy(r, data, sizeof(param_type)); 283 return true; 284 } 285 286 void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) { 287 l->append(base::UintToString(p)); 288 } 289 290 void ParamTraits<int>::Log(const param_type& p, std::string* l) { 291 l->append(base::IntToString(p)); 292 } 293 294 void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) { 295 l->append(base::UintToString(p)); 296 } 297 298 void ParamTraits<long>::Log(const param_type& p, std::string* l) { 299 l->append(base::Int64ToString(static_cast<int64>(p))); 300 } 301 302 void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) { 303 l->append(base::Uint64ToString(static_cast<uint64>(p))); 304 } 305 306 void ParamTraits<long long>::Log(const param_type& p, std::string* l) { 307 l->append(base::Int64ToString(static_cast<int64>(p))); 308 } 309 310 void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) { 311 l->append(base::Uint64ToString(p)); 312 } 313 314 void ParamTraits<float>::Log(const param_type& p, std::string* l) { 315 l->append(base::StringPrintf("%e", p)); 316 } 317 318 void ParamTraits<double>::Write(Message* m, const param_type& p) { 319 m->WriteBytes(reinterpret_cast<const char*>(&p), sizeof(param_type)); 320 } 321 322 bool ParamTraits<double>::Read(const Message* m, PickleIterator* iter, 323 param_type* r) { 324 const char *data; 325 if (!m->ReadBytes(iter, &data, sizeof(*r))) { 326 NOTREACHED(); 327 return false; 328 } 329 memcpy(r, data, sizeof(param_type)); 330 return true; 331 } 332 333 void ParamTraits<double>::Log(const param_type& p, std::string* l) { 334 l->append(base::StringPrintf("%e", p)); 335 } 336 337 338 void ParamTraits<std::string>::Log(const param_type& p, std::string* l) { 339 l->append(p); 340 } 341 342 void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) { 343 l->append(base::WideToUTF8(p)); 344 } 345 346 #if !defined(WCHAR_T_IS_UTF16) 347 void ParamTraits<base::string16>::Log(const param_type& p, std::string* l) { 348 l->append(base::UTF16ToUTF8(p)); 349 } 350 #endif 351 352 void ParamTraits<std::vector<char> >::Write(Message* m, const param_type& p) { 353 if (p.empty()) { 354 m->WriteData(NULL, 0); 355 } else { 356 m->WriteData(&p.front(), static_cast<int>(p.size())); 357 } 358 } 359 360 bool ParamTraits<std::vector<char> >::Read(const Message* m, 361 PickleIterator* iter, 362 param_type* r) { 363 const char *data; 364 int data_size = 0; 365 if (!m->ReadData(iter, &data, &data_size) || data_size < 0) 366 return false; 367 r->resize(data_size); 368 if (data_size) 369 memcpy(&r->front(), data, data_size); 370 return true; 371 } 372 373 void ParamTraits<std::vector<char> >::Log(const param_type& p, std::string* l) { 374 LogBytes(p, l); 375 } 376 377 void ParamTraits<std::vector<unsigned char> >::Write(Message* m, 378 const param_type& p) { 379 if (p.empty()) { 380 m->WriteData(NULL, 0); 381 } else { 382 m->WriteData(reinterpret_cast<const char*>(&p.front()), 383 static_cast<int>(p.size())); 384 } 385 } 386 387 bool ParamTraits<std::vector<unsigned char> >::Read(const Message* m, 388 PickleIterator* iter, 389 param_type* r) { 390 const char *data; 391 int data_size = 0; 392 if (!m->ReadData(iter, &data, &data_size) || data_size < 0) 393 return false; 394 r->resize(data_size); 395 if (data_size) 396 memcpy(&r->front(), data, data_size); 397 return true; 398 } 399 400 void ParamTraits<std::vector<unsigned char> >::Log(const param_type& p, 401 std::string* l) { 402 LogBytes(p, l); 403 } 404 405 void ParamTraits<std::vector<bool> >::Write(Message* m, const param_type& p) { 406 WriteParam(m, static_cast<int>(p.size())); 407 // Cast to bool below is required because libc++'s 408 // vector<bool>::const_reference is different from bool, and we want to avoid 409 // writing an extra specialization of ParamTraits for it. 410 for (size_t i = 0; i < p.size(); i++) 411 WriteParam(m, static_cast<bool>(p[i])); 412 } 413 414 bool ParamTraits<std::vector<bool> >::Read(const Message* m, 415 PickleIterator* iter, 416 param_type* r) { 417 int size; 418 // ReadLength() checks for < 0 itself. 419 if (!m->ReadLength(iter, &size)) 420 return false; 421 r->resize(size); 422 for (int i = 0; i < size; i++) { 423 bool value; 424 if (!ReadParam(m, iter, &value)) 425 return false; 426 (*r)[i] = value; 427 } 428 return true; 429 } 430 431 void ParamTraits<std::vector<bool> >::Log(const param_type& p, std::string* l) { 432 for (size_t i = 0; i < p.size(); ++i) { 433 if (i != 0) 434 l->push_back(' '); 435 LogParam(static_cast<bool>(p[i]), l); 436 } 437 } 438 439 void ParamTraits<base::DictionaryValue>::Write(Message* m, 440 const param_type& p) { 441 WriteValue(m, &p, 0); 442 } 443 444 bool ParamTraits<base::DictionaryValue>::Read( 445 const Message* m, PickleIterator* iter, param_type* r) { 446 int type; 447 if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_DICTIONARY) 448 return false; 449 450 return ReadDictionaryValue(m, iter, r, 0); 451 } 452 453 void ParamTraits<base::DictionaryValue>::Log(const param_type& p, 454 std::string* l) { 455 std::string json; 456 base::JSONWriter::Write(&p, &json); 457 l->append(json); 458 } 459 460 #if defined(OS_POSIX) 461 void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) { 462 const bool valid = p.fd >= 0; 463 WriteParam(m, valid); 464 465 if (valid) { 466 if (!m->WriteFileDescriptor(p)) 467 NOTREACHED(); 468 } 469 } 470 471 bool ParamTraits<base::FileDescriptor>::Read(const Message* m, 472 PickleIterator* iter, 473 param_type* r) { 474 bool valid; 475 if (!ReadParam(m, iter, &valid)) 476 return false; 477 478 if (!valid) { 479 r->fd = -1; 480 r->auto_close = false; 481 return true; 482 } 483 484 return m->ReadFileDescriptor(iter, r); 485 } 486 487 void ParamTraits<base::FileDescriptor>::Log(const param_type& p, 488 std::string* l) { 489 if (p.auto_close) { 490 l->append(base::StringPrintf("FD(%d auto-close)", p.fd)); 491 } else { 492 l->append(base::StringPrintf("FD(%d)", p.fd)); 493 } 494 } 495 #endif // defined(OS_POSIX) 496 497 void ParamTraits<base::FilePath>::Write(Message* m, const param_type& p) { 498 p.WriteToPickle(m); 499 } 500 501 bool ParamTraits<base::FilePath>::Read(const Message* m, 502 PickleIterator* iter, 503 param_type* r) { 504 return r->ReadFromPickle(iter); 505 } 506 507 void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) { 508 ParamTraits<base::FilePath::StringType>::Log(p.value(), l); 509 } 510 511 void ParamTraits<base::ListValue>::Write(Message* m, const param_type& p) { 512 WriteValue(m, &p, 0); 513 } 514 515 bool ParamTraits<base::ListValue>::Read( 516 const Message* m, PickleIterator* iter, param_type* r) { 517 int type; 518 if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_LIST) 519 return false; 520 521 return ReadListValue(m, iter, r, 0); 522 } 523 524 void ParamTraits<base::ListValue>::Log(const param_type& p, std::string* l) { 525 std::string json; 526 base::JSONWriter::Write(&p, &json); 527 l->append(json); 528 } 529 530 void ParamTraits<base::NullableString16>::Write(Message* m, 531 const param_type& p) { 532 WriteParam(m, p.string()); 533 WriteParam(m, p.is_null()); 534 } 535 536 bool ParamTraits<base::NullableString16>::Read(const Message* m, 537 PickleIterator* iter, 538 param_type* r) { 539 base::string16 string; 540 if (!ReadParam(m, iter, &string)) 541 return false; 542 bool is_null; 543 if (!ReadParam(m, iter, &is_null)) 544 return false; 545 *r = base::NullableString16(string, is_null); 546 return true; 547 } 548 549 void ParamTraits<base::NullableString16>::Log(const param_type& p, 550 std::string* l) { 551 l->append("("); 552 LogParam(p.string(), l); 553 l->append(", "); 554 LogParam(p.is_null(), l); 555 l->append(")"); 556 } 557 558 void ParamTraits<base::File::Info>::Write(Message* m, 559 const param_type& p) { 560 WriteParam(m, p.size); 561 WriteParam(m, p.is_directory); 562 WriteParam(m, p.last_modified.ToDoubleT()); 563 WriteParam(m, p.last_accessed.ToDoubleT()); 564 WriteParam(m, p.creation_time.ToDoubleT()); 565 } 566 567 bool ParamTraits<base::File::Info>::Read(const Message* m, 568 PickleIterator* iter, 569 param_type* p) { 570 double last_modified; 571 double last_accessed; 572 double creation_time; 573 bool result = 574 ReadParam(m, iter, &p->size) && 575 ReadParam(m, iter, &p->is_directory) && 576 ReadParam(m, iter, &last_modified) && 577 ReadParam(m, iter, &last_accessed) && 578 ReadParam(m, iter, &creation_time); 579 if (result) { 580 p->last_modified = base::Time::FromDoubleT(last_modified); 581 p->last_accessed = base::Time::FromDoubleT(last_accessed); 582 p->creation_time = base::Time::FromDoubleT(creation_time); 583 } 584 return result; 585 } 586 587 void ParamTraits<base::File::Info>::Log(const param_type& p, 588 std::string* l) { 589 l->append("("); 590 LogParam(p.size, l); 591 l->append(","); 592 LogParam(p.is_directory, l); 593 l->append(","); 594 LogParam(p.last_modified.ToDoubleT(), l); 595 l->append(","); 596 LogParam(p.last_accessed.ToDoubleT(), l); 597 l->append(","); 598 LogParam(p.creation_time.ToDoubleT(), l); 599 l->append(")"); 600 } 601 602 void ParamTraits<base::Time>::Write(Message* m, const param_type& p) { 603 ParamTraits<int64>::Write(m, p.ToInternalValue()); 604 } 605 606 bool ParamTraits<base::Time>::Read(const Message* m, PickleIterator* iter, 607 param_type* r) { 608 int64 value; 609 if (!ParamTraits<int64>::Read(m, iter, &value)) 610 return false; 611 *r = base::Time::FromInternalValue(value); 612 return true; 613 } 614 615 void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) { 616 ParamTraits<int64>::Log(p.ToInternalValue(), l); 617 } 618 619 void ParamTraits<base::TimeDelta>::Write(Message* m, const param_type& p) { 620 ParamTraits<int64>::Write(m, p.ToInternalValue()); 621 } 622 623 bool ParamTraits<base::TimeDelta>::Read(const Message* m, 624 PickleIterator* iter, 625 param_type* r) { 626 int64 value; 627 bool ret = ParamTraits<int64>::Read(m, iter, &value); 628 if (ret) 629 *r = base::TimeDelta::FromInternalValue(value); 630 631 return ret; 632 } 633 634 void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) { 635 ParamTraits<int64>::Log(p.ToInternalValue(), l); 636 } 637 638 void ParamTraits<base::TimeTicks>::Write(Message* m, const param_type& p) { 639 ParamTraits<int64>::Write(m, p.ToInternalValue()); 640 } 641 642 bool ParamTraits<base::TimeTicks>::Read(const Message* m, 643 PickleIterator* iter, 644 param_type* r) { 645 int64 value; 646 bool ret = ParamTraits<int64>::Read(m, iter, &value); 647 if (ret) 648 *r = base::TimeTicks::FromInternalValue(value); 649 650 return ret; 651 } 652 653 void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) { 654 ParamTraits<int64>::Log(p.ToInternalValue(), l); 655 } 656 657 void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) { 658 #if defined(OS_WIN) 659 // On Windows marshalling pipe handle is not supported. 660 DCHECK(p.pipe.handle == NULL); 661 #endif // defined (OS_WIN) 662 WriteParam(m, p.name); 663 #if defined(OS_POSIX) 664 WriteParam(m, p.socket); 665 #endif 666 } 667 668 bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m, 669 PickleIterator* iter, 670 param_type* r) { 671 return ReadParam(m, iter, &r->name) 672 #if defined(OS_POSIX) 673 && ReadParam(m, iter, &r->socket) 674 #endif 675 ; 676 } 677 678 void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p, 679 std::string* l) { 680 l->append(base::StringPrintf("ChannelHandle(%s", p.name.c_str())); 681 #if defined(OS_POSIX) 682 l->append(", "); 683 ParamTraits<base::FileDescriptor>::Log(p.socket, l); 684 #endif 685 l->append(")"); 686 } 687 688 void ParamTraits<LogData>::Write(Message* m, const param_type& p) { 689 WriteParam(m, p.channel); 690 WriteParam(m, p.routing_id); 691 WriteParam(m, p.type); 692 WriteParam(m, p.flags); 693 WriteParam(m, p.sent); 694 WriteParam(m, p.receive); 695 WriteParam(m, p.dispatch); 696 WriteParam(m, p.message_name); 697 WriteParam(m, p.params); 698 } 699 700 bool ParamTraits<LogData>::Read(const Message* m, 701 PickleIterator* iter, 702 param_type* r) { 703 return 704 ReadParam(m, iter, &r->channel) && 705 ReadParam(m, iter, &r->routing_id) && 706 ReadParam(m, iter, &r->type) && 707 ReadParam(m, iter, &r->flags) && 708 ReadParam(m, iter, &r->sent) && 709 ReadParam(m, iter, &r->receive) && 710 ReadParam(m, iter, &r->dispatch) && 711 ReadParam(m, iter, &r->message_name) && 712 ReadParam(m, iter, &r->params); 713 } 714 715 void ParamTraits<LogData>::Log(const param_type& p, std::string* l) { 716 // Doesn't make sense to implement this! 717 } 718 719 void ParamTraits<Message>::Write(Message* m, const Message& p) { 720 #if defined(OS_POSIX) 721 // We don't serialize the file descriptors in the nested message, so there 722 // better not be any. 723 DCHECK(!p.HasFileDescriptors()); 724 #endif 725 726 // Don't just write out the message. This is used to send messages between 727 // NaCl (Posix environment) and the browser (could be on Windows). The message 728 // header formats differ between these systems (so does handle sharing, but 729 // we already asserted we don't have any handles). So just write out the 730 // parts of the header we use. 731 // 732 // Be careful also to use only explicitly-sized types. The NaCl environment 733 // could be 64-bit and the host browser could be 32-bits. The nested message 734 // may or may not be safe to send between 32-bit and 64-bit systems, but we 735 // leave that up to the code sending the message to ensure. 736 m->WriteUInt32(static_cast<uint32>(p.routing_id())); 737 m->WriteUInt32(p.type()); 738 m->WriteUInt32(p.flags()); 739 m->WriteData(p.payload(), static_cast<uint32>(p.payload_size())); 740 } 741 742 bool ParamTraits<Message>::Read(const Message* m, PickleIterator* iter, 743 Message* r) { 744 uint32 routing_id, type, flags; 745 if (!m->ReadUInt32(iter, &routing_id) || 746 !m->ReadUInt32(iter, &type) || 747 !m->ReadUInt32(iter, &flags)) 748 return false; 749 750 int payload_size; 751 const char* payload; 752 if (!m->ReadData(iter, &payload, &payload_size)) 753 return false; 754 755 r->SetHeaderValues(static_cast<int32>(routing_id), type, flags); 756 return r->WriteBytes(payload, payload_size); 757 } 758 759 void ParamTraits<Message>::Log(const Message& p, std::string* l) { 760 l->append("<IPC::Message>"); 761 } 762 763 #if defined(OS_WIN) 764 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64 765 // bit systems. That's why we use the Windows macros to convert to 32 bits. 766 void ParamTraits<HANDLE>::Write(Message* m, const param_type& p) { 767 m->WriteInt(HandleToLong(p)); 768 } 769 770 bool ParamTraits<HANDLE>::Read(const Message* m, PickleIterator* iter, 771 param_type* r) { 772 int32 temp; 773 if (!m->ReadInt(iter, &temp)) 774 return false; 775 *r = LongToHandle(temp); 776 return true; 777 } 778 779 void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) { 780 l->append(base::StringPrintf("0x%X", p)); 781 } 782 783 void ParamTraits<LOGFONT>::Write(Message* m, const param_type& p) { 784 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT)); 785 } 786 787 bool ParamTraits<LOGFONT>::Read(const Message* m, PickleIterator* iter, 788 param_type* r) { 789 const char *data; 790 int data_size = 0; 791 if (m->ReadData(iter, &data, &data_size) && data_size == sizeof(LOGFONT)) { 792 const LOGFONT *font = reinterpret_cast<LOGFONT*>(const_cast<char*>(data)); 793 if (_tcsnlen(font->lfFaceName, LF_FACESIZE) < LF_FACESIZE) { 794 memcpy(r, data, sizeof(LOGFONT)); 795 return true; 796 } 797 } 798 799 NOTREACHED(); 800 return false; 801 } 802 803 void ParamTraits<LOGFONT>::Log(const param_type& p, std::string* l) { 804 l->append(base::StringPrintf("<LOGFONT>")); 805 } 806 807 void ParamTraits<MSG>::Write(Message* m, const param_type& p) { 808 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG)); 809 } 810 811 bool ParamTraits<MSG>::Read(const Message* m, PickleIterator* iter, 812 param_type* r) { 813 const char *data; 814 int data_size = 0; 815 bool result = m->ReadData(iter, &data, &data_size); 816 if (result && data_size == sizeof(MSG)) { 817 memcpy(r, data, sizeof(MSG)); 818 } else { 819 result = false; 820 NOTREACHED(); 821 } 822 823 return result; 824 } 825 826 void ParamTraits<MSG>::Log(const param_type& p, std::string* l) { 827 l->append("<MSG>"); 828 } 829 830 #endif // OS_WIN 831 832 } // namespace IPC 833