ipc_message_utils.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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 23namespace IPC { 24 25namespace { 26 27const int kMaxRecursionDepth = 100; 28 29template<typename CharType> 30void 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 53bool ReadValue(const Message* m, PickleIterator* iter, base::Value** value, 54 int recursion); 55 56void 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. 129bool 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. 149bool 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 165bool 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 241LogData::LogData() 242 : routing_id(0), 243 type(0), 244 sent(0), 245 receive(0), 246 dispatch(0) { 247} 248 249LogData::~LogData() { 250} 251 252void ParamTraits<bool>::Log(const param_type& p, std::string* l) { 253 l->append(p ? "true" : "false"); 254} 255 256void ParamTraits<unsigned char>::Write(Message* m, const param_type& p) { 257 m->WriteBytes(&p, sizeof(param_type)); 258} 259 260bool 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 269void ParamTraits<unsigned char>::Log(const param_type& p, std::string* l) { 270 l->append(base::UintToString(p)); 271} 272 273void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) { 274 m->WriteBytes(&p, sizeof(param_type)); 275} 276 277bool 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 286void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) { 287 l->append(base::UintToString(p)); 288} 289 290void ParamTraits<int>::Log(const param_type& p, std::string* l) { 291 l->append(base::IntToString(p)); 292} 293 294void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) { 295 l->append(base::UintToString(p)); 296} 297 298void ParamTraits<long>::Log(const param_type& p, std::string* l) { 299 l->append(base::Int64ToString(static_cast<int64>(p))); 300} 301 302void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) { 303 l->append(base::Uint64ToString(static_cast<uint64>(p))); 304} 305 306void ParamTraits<long long>::Log(const param_type& p, std::string* l) { 307 l->append(base::Int64ToString(static_cast<int64>(p))); 308} 309 310void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) { 311 l->append(base::Uint64ToString(p)); 312} 313 314void ParamTraits<float>::Log(const param_type& p, std::string* l) { 315 l->append(base::StringPrintf("%e", p)); 316} 317 318void ParamTraits<double>::Write(Message* m, const param_type& p) { 319 m->WriteBytes(reinterpret_cast<const char*>(&p), sizeof(param_type)); 320} 321 322bool 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 333void ParamTraits<double>::Log(const param_type& p, std::string* l) { 334 l->append(base::StringPrintf("%e", p)); 335} 336 337 338void ParamTraits<std::string>::Log(const param_type& p, std::string* l) { 339 l->append(p); 340} 341 342void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) { 343 l->append(WideToUTF8(p)); 344} 345 346#if !defined(WCHAR_T_IS_UTF16) 347void ParamTraits<string16>::Log(const param_type& p, std::string* l) { 348 l->append(UTF16ToUTF8(p)); 349} 350#endif 351 352void 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 360bool 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 373void ParamTraits<std::vector<char> >::Log(const param_type& p, std::string* l) { 374 LogBytes(p, l); 375} 376 377void 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 387bool 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 400void ParamTraits<std::vector<unsigned char> >::Log(const param_type& p, 401 std::string* l) { 402 LogBytes(p, l); 403} 404 405void 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 414bool 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 431void 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 439void ParamTraits<base::DictionaryValue>::Write(Message* m, 440 const param_type& p) { 441 WriteValue(m, &p, 0); 442} 443 444bool 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 453void 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) 461void 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 471bool 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 487void 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 497void ParamTraits<base::FilePath>::Write(Message* m, const param_type& p) { 498 p.WriteToPickle(m); 499} 500 501bool ParamTraits<base::FilePath>::Read(const Message* m, 502 PickleIterator* iter, 503 param_type* r) { 504 return r->ReadFromPickle(iter); 505} 506 507void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) { 508 ParamTraits<base::FilePath::StringType>::Log(p.value(), l); 509} 510 511void ParamTraits<base::ListValue>::Write(Message* m, const param_type& p) { 512 WriteValue(m, &p, 0); 513} 514 515bool 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 524void 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 530void ParamTraits<base::NullableString16>::Write(Message* m, 531 const param_type& p) { 532 WriteParam(m, p.string()); 533 WriteParam(m, p.is_null()); 534} 535 536bool ParamTraits<base::NullableString16>::Read(const Message* m, 537 PickleIterator* iter, 538 param_type* r) { 539 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 549void 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 558void ParamTraits<base::PlatformFileInfo>::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 567bool ParamTraits<base::PlatformFileInfo>::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 587void ParamTraits<base::PlatformFileInfo>::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 602void ParamTraits<base::Time>::Write(Message* m, const param_type& p) { 603 ParamTraits<int64>::Write(m, p.ToInternalValue()); 604} 605 606bool 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 615void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) { 616 ParamTraits<int64>::Log(p.ToInternalValue(), l); 617} 618 619void ParamTraits<base::TimeDelta>::Write(Message* m, const param_type& p) { 620 ParamTraits<int64>::Write(m, p.ToInternalValue()); 621} 622 623bool 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 634void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) { 635 ParamTraits<int64>::Log(p.ToInternalValue(), l); 636} 637 638void ParamTraits<base::TimeTicks>::Write(Message* m, const param_type& p) { 639 ParamTraits<int64>::Write(m, p.ToInternalValue()); 640} 641 642bool 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 653void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) { 654 ParamTraits<int64>::Log(p.ToInternalValue(), l); 655} 656 657void 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 668bool 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 678void 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 688void 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 700bool 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 715void ParamTraits<LogData>::Log(const param_type& p, std::string* l) { 716 // Doesn't make sense to implement this! 717} 718 719void 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 742bool 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 759void 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. 766void ParamTraits<HANDLE>::Write(Message* m, const param_type& p) { 767 m->WriteInt(HandleToLong(p)); 768} 769 770bool 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 779void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) { 780 l->append(base::StringPrintf("0x%X", p)); 781} 782 783void ParamTraits<LOGFONT>::Write(Message* m, const param_type& p) { 784 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT)); 785} 786 787bool 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 803void ParamTraits<LOGFONT>::Log(const param_type& p, std::string* l) { 804 l->append(base::StringPrintf("<LOGFONT>")); 805} 806 807void ParamTraits<MSG>::Write(Message* m, const param_type& p) { 808 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG)); 809} 810 811bool 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 826void 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