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