Reorder permission message rules, so that related rules appear together.
[chromium-blink-merge.git] / ipc / ipc_message_utils.cc
blobdbb2572e6683c707ead39035b42ecbb223dc3a64
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.
5 #include "ipc/ipc_message_utils.h"
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 #include "ipc/ipc_message_attachment.h"
17 #include "ipc/ipc_message_attachment_set.h"
19 #if defined(OS_POSIX)
20 #include "ipc/ipc_platform_file_attachment_posix.h"
21 #endif
23 #if defined(OS_MACOSX) && !defined(OS_IOS)
24 #include "base/memory/shared_memory_handle.h"
25 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
27 #if defined(OS_WIN)
28 #include <tchar.h>
29 #endif
31 namespace IPC {
33 namespace {
35 const int kMaxRecursionDepth = 100;
37 template<typename CharType>
38 void LogBytes(const std::vector<CharType>& data, std::string* out) {
39 #if defined(OS_WIN)
40 // Windows has a GUI for logging, which can handle arbitrary binary data.
41 for (size_t i = 0; i < data.size(); ++i)
42 out->push_back(data[i]);
43 #else
44 // On POSIX, we log to stdout, which we assume can display ASCII.
45 static const size_t kMaxBytesToLog = 100;
46 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
47 if (isprint(data[i]))
48 out->push_back(data[i]);
49 else
50 out->append(
51 base::StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
53 if (data.size() > kMaxBytesToLog) {
54 out->append(base::StringPrintf(
55 " and %u more bytes",
56 static_cast<unsigned>(data.size() - kMaxBytesToLog)));
58 #endif
61 bool ReadValue(const Message* m,
62 base::PickleIterator* iter,
63 base::Value** value,
64 int recursion);
66 void WriteValue(Message* m, const base::Value* value, int recursion) {
67 bool result;
68 if (recursion > kMaxRecursionDepth) {
69 LOG(WARNING) << "Max recursion depth hit in WriteValue.";
70 return;
73 m->WriteInt(value->GetType());
75 switch (value->GetType()) {
76 case base::Value::TYPE_NULL:
77 break;
78 case base::Value::TYPE_BOOLEAN: {
79 bool val;
80 result = value->GetAsBoolean(&val);
81 DCHECK(result);
82 WriteParam(m, val);
83 break;
85 case base::Value::TYPE_INTEGER: {
86 int val;
87 result = value->GetAsInteger(&val);
88 DCHECK(result);
89 WriteParam(m, val);
90 break;
92 case base::Value::TYPE_DOUBLE: {
93 double val;
94 result = value->GetAsDouble(&val);
95 DCHECK(result);
96 WriteParam(m, val);
97 break;
99 case base::Value::TYPE_STRING: {
100 std::string val;
101 result = value->GetAsString(&val);
102 DCHECK(result);
103 WriteParam(m, val);
104 break;
106 case base::Value::TYPE_BINARY: {
107 const base::BinaryValue* binary =
108 static_cast<const base::BinaryValue*>(value);
109 m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
110 break;
112 case base::Value::TYPE_DICTIONARY: {
113 const base::DictionaryValue* dict =
114 static_cast<const base::DictionaryValue*>(value);
116 WriteParam(m, static_cast<int>(dict->size()));
118 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
119 it.Advance()) {
120 WriteParam(m, it.key());
121 WriteValue(m, &it.value(), recursion + 1);
123 break;
125 case base::Value::TYPE_LIST: {
126 const base::ListValue* list = static_cast<const base::ListValue*>(value);
127 WriteParam(m, static_cast<int>(list->GetSize()));
128 for (base::ListValue::const_iterator it = list->begin();
129 it != list->end(); ++it) {
130 WriteValue(m, *it, recursion + 1);
132 break;
137 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated
138 // object.
139 bool ReadDictionaryValue(const Message* m,
140 base::PickleIterator* iter,
141 base::DictionaryValue* value,
142 int recursion) {
143 int size;
144 if (!ReadParam(m, iter, &size))
145 return false;
147 for (int i = 0; i < size; ++i) {
148 std::string key;
149 base::Value* subval;
150 if (!ReadParam(m, iter, &key) ||
151 !ReadValue(m, iter, &subval, recursion + 1))
152 return false;
153 value->SetWithoutPathExpansion(key, subval);
156 return true;
159 // Helper for ReadValue that reads a ReadListValue into a pre-allocated
160 // object.
161 bool ReadListValue(const Message* m,
162 base::PickleIterator* iter,
163 base::ListValue* value,
164 int recursion) {
165 int size;
166 if (!ReadParam(m, iter, &size))
167 return false;
169 for (int i = 0; i < size; ++i) {
170 base::Value* subval;
171 if (!ReadValue(m, iter, &subval, recursion + 1))
172 return false;
173 value->Set(i, subval);
176 return true;
179 bool ReadValue(const Message* m,
180 base::PickleIterator* iter,
181 base::Value** value,
182 int recursion) {
183 if (recursion > kMaxRecursionDepth) {
184 LOG(WARNING) << "Max recursion depth hit in ReadValue.";
185 return false;
188 int type;
189 if (!ReadParam(m, iter, &type))
190 return false;
192 switch (type) {
193 case base::Value::TYPE_NULL:
194 *value = base::Value::CreateNullValue().release();
195 break;
196 case base::Value::TYPE_BOOLEAN: {
197 bool val;
198 if (!ReadParam(m, iter, &val))
199 return false;
200 *value = new base::FundamentalValue(val);
201 break;
203 case base::Value::TYPE_INTEGER: {
204 int val;
205 if (!ReadParam(m, iter, &val))
206 return false;
207 *value = new base::FundamentalValue(val);
208 break;
210 case base::Value::TYPE_DOUBLE: {
211 double val;
212 if (!ReadParam(m, iter, &val))
213 return false;
214 *value = new base::FundamentalValue(val);
215 break;
217 case base::Value::TYPE_STRING: {
218 std::string val;
219 if (!ReadParam(m, iter, &val))
220 return false;
221 *value = new base::StringValue(val);
222 break;
224 case base::Value::TYPE_BINARY: {
225 const char* data;
226 int length;
227 if (!iter->ReadData(&data, &length))
228 return false;
229 *value = base::BinaryValue::CreateWithCopiedBuffer(data, length);
230 break;
232 case base::Value::TYPE_DICTIONARY: {
233 scoped_ptr<base::DictionaryValue> val(new base::DictionaryValue());
234 if (!ReadDictionaryValue(m, iter, val.get(), recursion))
235 return false;
236 *value = val.release();
237 break;
239 case base::Value::TYPE_LIST: {
240 scoped_ptr<base::ListValue> val(new base::ListValue());
241 if (!ReadListValue(m, iter, val.get(), recursion))
242 return false;
243 *value = val.release();
244 break;
246 default:
247 return false;
250 return true;
253 } // namespace
255 // -----------------------------------------------------------------------------
257 LogData::LogData()
258 : routing_id(0),
259 type(0),
260 sent(0),
261 receive(0),
262 dispatch(0) {
265 LogData::~LogData() {
268 void ParamTraits<bool>::Log(const param_type& p, std::string* l) {
269 l->append(p ? "true" : "false");
272 void ParamTraits<unsigned char>::Write(Message* m, const param_type& p) {
273 m->WriteBytes(&p, sizeof(param_type));
276 bool ParamTraits<unsigned char>::Read(const Message* m,
277 base::PickleIterator* iter,
278 param_type* r) {
279 const char* data;
280 if (!iter->ReadBytes(&data, sizeof(param_type)))
281 return false;
282 memcpy(r, data, sizeof(param_type));
283 return true;
286 void ParamTraits<unsigned char>::Log(const param_type& p, std::string* l) {
287 l->append(base::UintToString(p));
290 void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) {
291 m->WriteBytes(&p, sizeof(param_type));
294 bool ParamTraits<unsigned short>::Read(const Message* m,
295 base::PickleIterator* iter,
296 param_type* r) {
297 const char* data;
298 if (!iter->ReadBytes(&data, sizeof(param_type)))
299 return false;
300 memcpy(r, data, sizeof(param_type));
301 return true;
304 void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
305 l->append(base::UintToString(p));
308 void ParamTraits<int>::Log(const param_type& p, std::string* l) {
309 l->append(base::IntToString(p));
312 void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
313 l->append(base::UintToString(p));
316 void ParamTraits<long>::Log(const param_type& p, std::string* l) {
317 l->append(base::Int64ToString(static_cast<int64>(p)));
320 void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
321 l->append(base::Uint64ToString(static_cast<uint64>(p)));
324 void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
325 l->append(base::Int64ToString(static_cast<int64>(p)));
328 void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
329 l->append(base::Uint64ToString(p));
332 void ParamTraits<float>::Log(const param_type& p, std::string* l) {
333 l->append(base::StringPrintf("%e", p));
336 void ParamTraits<double>::Write(Message* m, const param_type& p) {
337 m->WriteBytes(reinterpret_cast<const char*>(&p), sizeof(param_type));
340 bool ParamTraits<double>::Read(const Message* m,
341 base::PickleIterator* iter,
342 param_type* r) {
343 const char *data;
344 if (!iter->ReadBytes(&data, sizeof(*r))) {
345 NOTREACHED();
346 return false;
348 memcpy(r, data, sizeof(param_type));
349 return true;
352 void ParamTraits<double>::Log(const param_type& p, std::string* l) {
353 l->append(base::StringPrintf("%e", p));
357 void ParamTraits<std::string>::Log(const param_type& p, std::string* l) {
358 l->append(p);
361 void ParamTraits<base::string16>::Log(const param_type& p, std::string* l) {
362 l->append(base::UTF16ToUTF8(p));
365 void ParamTraits<std::vector<char> >::Write(Message* m, const param_type& p) {
366 if (p.empty()) {
367 m->WriteData(NULL, 0);
368 } else {
369 m->WriteData(&p.front(), static_cast<int>(p.size()));
373 bool ParamTraits<std::vector<char>>::Read(const Message* m,
374 base::PickleIterator* iter,
375 param_type* r) {
376 const char *data;
377 int data_size = 0;
378 if (!iter->ReadData(&data, &data_size) || data_size < 0)
379 return false;
380 r->resize(data_size);
381 if (data_size)
382 memcpy(&r->front(), data, data_size);
383 return true;
386 void ParamTraits<std::vector<char> >::Log(const param_type& p, std::string* l) {
387 LogBytes(p, l);
390 void ParamTraits<std::vector<unsigned char> >::Write(Message* m,
391 const param_type& p) {
392 if (p.empty()) {
393 m->WriteData(NULL, 0);
394 } else {
395 m->WriteData(reinterpret_cast<const char*>(&p.front()),
396 static_cast<int>(p.size()));
400 bool ParamTraits<std::vector<unsigned char>>::Read(const Message* m,
401 base::PickleIterator* iter,
402 param_type* r) {
403 const char *data;
404 int data_size = 0;
405 if (!iter->ReadData(&data, &data_size) || data_size < 0)
406 return false;
407 r->resize(data_size);
408 if (data_size)
409 memcpy(&r->front(), data, data_size);
410 return true;
413 void ParamTraits<std::vector<unsigned char> >::Log(const param_type& p,
414 std::string* l) {
415 LogBytes(p, l);
418 void ParamTraits<std::vector<bool> >::Write(Message* m, const param_type& p) {
419 WriteParam(m, static_cast<int>(p.size()));
420 // Cast to bool below is required because libc++'s
421 // vector<bool>::const_reference is different from bool, and we want to avoid
422 // writing an extra specialization of ParamTraits for it.
423 for (size_t i = 0; i < p.size(); i++)
424 WriteParam(m, static_cast<bool>(p[i]));
427 bool ParamTraits<std::vector<bool>>::Read(const Message* m,
428 base::PickleIterator* iter,
429 param_type* r) {
430 int size;
431 // ReadLength() checks for < 0 itself.
432 if (!iter->ReadLength(&size))
433 return false;
434 r->resize(size);
435 for (int i = 0; i < size; i++) {
436 bool value;
437 if (!ReadParam(m, iter, &value))
438 return false;
439 (*r)[i] = value;
441 return true;
444 void ParamTraits<std::vector<bool> >::Log(const param_type& p, std::string* l) {
445 for (size_t i = 0; i < p.size(); ++i) {
446 if (i != 0)
447 l->push_back(' ');
448 LogParam(static_cast<bool>(p[i]), l);
452 void ParamTraits<BrokerableAttachment::AttachmentId>::Write(
453 Message* m,
454 const param_type& p) {
455 m->WriteBytes(p.nonce, BrokerableAttachment::kNonceSize);
458 bool ParamTraits<BrokerableAttachment::AttachmentId>::Read(
459 const Message* m,
460 base::PickleIterator* iter,
461 param_type* r) {
462 const char* data;
463 if (!iter->ReadBytes(&data, BrokerableAttachment::kNonceSize))
464 return false;
465 memcpy(r->nonce, data, BrokerableAttachment::kNonceSize);
466 return true;
469 void ParamTraits<BrokerableAttachment::AttachmentId>::Log(const param_type& p,
470 std::string* l) {
471 l->append(base::HexEncode(p.nonce, BrokerableAttachment::kNonceSize));
474 void ParamTraits<base::DictionaryValue>::Write(Message* m,
475 const param_type& p) {
476 WriteValue(m, &p, 0);
479 bool ParamTraits<base::DictionaryValue>::Read(const Message* m,
480 base::PickleIterator* iter,
481 param_type* r) {
482 int type;
483 if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_DICTIONARY)
484 return false;
486 return ReadDictionaryValue(m, iter, r, 0);
489 void ParamTraits<base::DictionaryValue>::Log(const param_type& p,
490 std::string* l) {
491 std::string json;
492 base::JSONWriter::Write(p, &json);
493 l->append(json);
496 #if defined(OS_POSIX)
497 void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
498 const bool valid = p.fd >= 0;
499 WriteParam(m, valid);
501 if (!valid)
502 return;
504 if (p.auto_close) {
505 if (!m->WriteAttachment(
506 new internal::PlatformFileAttachment(base::ScopedFD(p.fd))))
507 NOTREACHED();
508 } else {
509 if (!m->WriteAttachment(new internal::PlatformFileAttachment(p.fd)))
510 NOTREACHED();
514 bool ParamTraits<base::FileDescriptor>::Read(const Message* m,
515 base::PickleIterator* iter,
516 param_type* r) {
517 *r = base::FileDescriptor();
519 bool valid;
520 if (!ReadParam(m, iter, &valid))
521 return false;
523 // TODO(morrita): Seems like this should return false.
524 if (!valid)
525 return true;
527 scoped_refptr<MessageAttachment> attachment;
528 if (!m->ReadAttachment(iter, &attachment))
529 return false;
531 *r = base::FileDescriptor(attachment->TakePlatformFile(), true);
532 return true;
535 void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
536 std::string* l) {
537 if (p.auto_close) {
538 l->append(base::StringPrintf("FD(%d auto-close)", p.fd));
539 } else {
540 l->append(base::StringPrintf("FD(%d)", p.fd));
543 #endif // defined(OS_POSIX)
545 #if defined(OS_MACOSX) && !defined(OS_IOS)
546 void ParamTraits<base::SharedMemoryHandle>::Write(Message* m,
547 const param_type& p) {
548 m->WriteInt(p.GetType());
550 if (p.GetType() == base::SharedMemoryHandle::POSIX)
551 ParamTraits<base::FileDescriptor>::Write(m, p.GetFileDescriptor());
554 bool ParamTraits<base::SharedMemoryHandle>::Read(const Message* m,
555 base::PickleIterator* iter,
556 param_type* r) {
557 base::SharedMemoryHandle::TypeWireFormat type;
558 if (!iter->ReadInt(&type))
559 return false;
561 base::SharedMemoryHandle::Type shm_type = base::SharedMemoryHandle::POSIX;
562 switch (type) {
563 case base::SharedMemoryHandle::POSIX:
564 case base::SharedMemoryHandle::MACH: {
565 shm_type = static_cast<base::SharedMemoryHandle::Type>(type);
566 break;
568 default:
569 return false;
572 if (shm_type == base::SharedMemoryHandle::POSIX) {
573 base::FileDescriptor file_descriptor;
575 bool success =
576 ParamTraits<base::FileDescriptor>::Read(m, iter, &file_descriptor);
577 if (!success)
578 return false;
580 *r = base::SharedMemoryHandle(file_descriptor.fd,
581 file_descriptor.auto_close);
582 return true;
585 return true;
588 void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p,
589 std::string* l) {
590 if (p.GetType() == base::SharedMemoryHandle::POSIX) {
591 l->append(base::StringPrintf("Mechanism POSIX Fd"));
592 ParamTraits<base::FileDescriptor>::Log(p.GetFileDescriptor(), l);
595 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
597 void ParamTraits<base::FilePath>::Write(Message* m, const param_type& p) {
598 p.WriteToPickle(m);
601 bool ParamTraits<base::FilePath>::Read(const Message* m,
602 base::PickleIterator* iter,
603 param_type* r) {
604 return r->ReadFromPickle(iter);
607 void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) {
608 ParamTraits<base::FilePath::StringType>::Log(p.value(), l);
611 void ParamTraits<base::ListValue>::Write(Message* m, const param_type& p) {
612 WriteValue(m, &p, 0);
615 bool ParamTraits<base::ListValue>::Read(const Message* m,
616 base::PickleIterator* iter,
617 param_type* r) {
618 int type;
619 if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_LIST)
620 return false;
622 return ReadListValue(m, iter, r, 0);
625 void ParamTraits<base::ListValue>::Log(const param_type& p, std::string* l) {
626 std::string json;
627 base::JSONWriter::Write(p, &json);
628 l->append(json);
631 void ParamTraits<base::NullableString16>::Write(Message* m,
632 const param_type& p) {
633 WriteParam(m, p.string());
634 WriteParam(m, p.is_null());
637 bool ParamTraits<base::NullableString16>::Read(const Message* m,
638 base::PickleIterator* iter,
639 param_type* r) {
640 base::string16 string;
641 if (!ReadParam(m, iter, &string))
642 return false;
643 bool is_null;
644 if (!ReadParam(m, iter, &is_null))
645 return false;
646 *r = base::NullableString16(string, is_null);
647 return true;
650 void ParamTraits<base::NullableString16>::Log(const param_type& p,
651 std::string* l) {
652 l->append("(");
653 LogParam(p.string(), l);
654 l->append(", ");
655 LogParam(p.is_null(), l);
656 l->append(")");
659 void ParamTraits<base::File::Info>::Write(Message* m,
660 const param_type& p) {
661 WriteParam(m, p.size);
662 WriteParam(m, p.is_directory);
663 WriteParam(m, p.last_modified.ToDoubleT());
664 WriteParam(m, p.last_accessed.ToDoubleT());
665 WriteParam(m, p.creation_time.ToDoubleT());
668 bool ParamTraits<base::File::Info>::Read(const Message* m,
669 base::PickleIterator* iter,
670 param_type* p) {
671 double last_modified, last_accessed, creation_time;
672 if (!ReadParam(m, iter, &p->size) ||
673 !ReadParam(m, iter, &p->is_directory) ||
674 !ReadParam(m, iter, &last_modified) ||
675 !ReadParam(m, iter, &last_accessed) ||
676 !ReadParam(m, iter, &creation_time))
677 return false;
678 p->last_modified = base::Time::FromDoubleT(last_modified);
679 p->last_accessed = base::Time::FromDoubleT(last_accessed);
680 p->creation_time = base::Time::FromDoubleT(creation_time);
681 return true;
684 void ParamTraits<base::File::Info>::Log(const param_type& p,
685 std::string* l) {
686 l->append("(");
687 LogParam(p.size, l);
688 l->append(",");
689 LogParam(p.is_directory, l);
690 l->append(",");
691 LogParam(p.last_modified.ToDoubleT(), l);
692 l->append(",");
693 LogParam(p.last_accessed.ToDoubleT(), l);
694 l->append(",");
695 LogParam(p.creation_time.ToDoubleT(), l);
696 l->append(")");
699 void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
700 ParamTraits<int64>::Write(m, p.ToInternalValue());
703 bool ParamTraits<base::Time>::Read(const Message* m,
704 base::PickleIterator* iter,
705 param_type* r) {
706 int64 value;
707 if (!ParamTraits<int64>::Read(m, iter, &value))
708 return false;
709 *r = base::Time::FromInternalValue(value);
710 return true;
713 void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
714 ParamTraits<int64>::Log(p.ToInternalValue(), l);
717 void ParamTraits<base::TimeDelta>::Write(Message* m, const param_type& p) {
718 ParamTraits<int64>::Write(m, p.ToInternalValue());
721 bool ParamTraits<base::TimeDelta>::Read(const Message* m,
722 base::PickleIterator* iter,
723 param_type* r) {
724 int64 value;
725 bool ret = ParamTraits<int64>::Read(m, iter, &value);
726 if (ret)
727 *r = base::TimeDelta::FromInternalValue(value);
729 return ret;
732 void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) {
733 ParamTraits<int64>::Log(p.ToInternalValue(), l);
736 void ParamTraits<base::TimeTicks>::Write(Message* m, const param_type& p) {
737 ParamTraits<int64>::Write(m, p.ToInternalValue());
740 bool ParamTraits<base::TimeTicks>::Read(const Message* m,
741 base::PickleIterator* iter,
742 param_type* r) {
743 int64 value;
744 bool ret = ParamTraits<int64>::Read(m, iter, &value);
745 if (ret)
746 *r = base::TimeTicks::FromInternalValue(value);
748 return ret;
751 void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) {
752 ParamTraits<int64>::Log(p.ToInternalValue(), l);
755 void ParamTraits<base::TraceTicks>::Write(Message* m, const param_type& p) {
756 ParamTraits<int64>::Write(m, p.ToInternalValue());
759 bool ParamTraits<base::TraceTicks>::Read(const Message* m,
760 base::PickleIterator* iter,
761 param_type* r) {
762 int64 value;
763 bool ret = ParamTraits<int64>::Read(m, iter, &value);
764 if (ret)
765 *r = base::TraceTicks::FromInternalValue(value);
767 return ret;
770 void ParamTraits<base::TraceTicks>::Log(const param_type& p, std::string* l) {
771 ParamTraits<int64>::Log(p.ToInternalValue(), l);
774 void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
775 #if defined(OS_WIN)
776 // On Windows marshalling pipe handle is not supported.
777 DCHECK(p.pipe.handle == NULL);
778 #endif // defined (OS_WIN)
779 WriteParam(m, p.name);
780 #if defined(OS_POSIX)
781 WriteParam(m, p.socket);
782 #endif
785 bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m,
786 base::PickleIterator* iter,
787 param_type* r) {
788 return ReadParam(m, iter, &r->name)
789 #if defined(OS_POSIX)
790 && ReadParam(m, iter, &r->socket)
791 #endif
795 void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
796 std::string* l) {
797 l->append(base::StringPrintf("ChannelHandle(%s", p.name.c_str()));
798 #if defined(OS_POSIX)
799 l->append(", ");
800 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
801 #endif
802 l->append(")");
805 void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
806 WriteParam(m, p.channel);
807 WriteParam(m, p.routing_id);
808 WriteParam(m, p.type);
809 WriteParam(m, p.flags);
810 WriteParam(m, p.sent);
811 WriteParam(m, p.receive);
812 WriteParam(m, p.dispatch);
813 WriteParam(m, p.message_name);
814 WriteParam(m, p.params);
817 bool ParamTraits<LogData>::Read(const Message* m,
818 base::PickleIterator* iter,
819 param_type* r) {
820 return
821 ReadParam(m, iter, &r->channel) &&
822 ReadParam(m, iter, &r->routing_id) &&
823 ReadParam(m, iter, &r->type) &&
824 ReadParam(m, iter, &r->flags) &&
825 ReadParam(m, iter, &r->sent) &&
826 ReadParam(m, iter, &r->receive) &&
827 ReadParam(m, iter, &r->dispatch) &&
828 ReadParam(m, iter, &r->message_name) &&
829 ReadParam(m, iter, &r->params);
832 void ParamTraits<LogData>::Log(const param_type& p, std::string* l) {
833 // Doesn't make sense to implement this!
836 void ParamTraits<Message>::Write(Message* m, const Message& p) {
837 #if defined(OS_POSIX)
838 // We don't serialize the file descriptors in the nested message, so there
839 // better not be any.
840 DCHECK(!p.HasAttachments());
841 #endif
843 // Don't just write out the message. This is used to send messages between
844 // NaCl (Posix environment) and the browser (could be on Windows). The message
845 // header formats differ between these systems (so does handle sharing, but
846 // we already asserted we don't have any handles). So just write out the
847 // parts of the header we use.
849 // Be careful also to use only explicitly-sized types. The NaCl environment
850 // could be 64-bit and the host browser could be 32-bits. The nested message
851 // may or may not be safe to send between 32-bit and 64-bit systems, but we
852 // leave that up to the code sending the message to ensure.
853 m->WriteUInt32(static_cast<uint32>(p.routing_id()));
854 m->WriteUInt32(p.type());
855 m->WriteUInt32(p.flags());
856 m->WriteData(p.payload(), static_cast<uint32>(p.payload_size()));
859 bool ParamTraits<Message>::Read(const Message* m,
860 base::PickleIterator* iter,
861 Message* r) {
862 uint32 routing_id, type, flags;
863 if (!iter->ReadUInt32(&routing_id) ||
864 !iter->ReadUInt32(&type) ||
865 !iter->ReadUInt32(&flags))
866 return false;
868 int payload_size;
869 const char* payload;
870 if (!iter->ReadData(&payload, &payload_size))
871 return false;
873 r->SetHeaderValues(static_cast<int32>(routing_id), type, flags);
874 return r->WriteBytes(payload, payload_size);
877 void ParamTraits<Message>::Log(const Message& p, std::string* l) {
878 l->append("<IPC::Message>");
881 #if defined(OS_WIN)
882 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
883 // bit systems. That's why we use the Windows macros to convert to 32 bits.
884 void ParamTraits<HANDLE>::Write(Message* m, const param_type& p) {
885 m->WriteInt(HandleToLong(p));
888 bool ParamTraits<HANDLE>::Read(const Message* m,
889 base::PickleIterator* iter,
890 param_type* r) {
891 int32 temp;
892 if (!iter->ReadInt(&temp))
893 return false;
894 *r = LongToHandle(temp);
895 return true;
898 void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) {
899 l->append(base::StringPrintf("0x%X", p));
902 void ParamTraits<LOGFONT>::Write(Message* m, const param_type& p) {
903 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
906 bool ParamTraits<LOGFONT>::Read(const Message* m,
907 base::PickleIterator* iter,
908 param_type* r) {
909 const char *data;
910 int data_size = 0;
911 if (iter->ReadData(&data, &data_size) && data_size == sizeof(LOGFONT)) {
912 const LOGFONT *font = reinterpret_cast<LOGFONT*>(const_cast<char*>(data));
913 if (_tcsnlen(font->lfFaceName, LF_FACESIZE) < LF_FACESIZE) {
914 memcpy(r, data, sizeof(LOGFONT));
915 return true;
919 NOTREACHED();
920 return false;
923 void ParamTraits<LOGFONT>::Log(const param_type& p, std::string* l) {
924 l->append(base::StringPrintf("<LOGFONT>"));
927 void ParamTraits<MSG>::Write(Message* m, const param_type& p) {
928 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
931 bool ParamTraits<MSG>::Read(const Message* m,
932 base::PickleIterator* iter,
933 param_type* r) {
934 const char *data;
935 int data_size = 0;
936 bool result = iter->ReadData(&data, &data_size);
937 if (result && data_size == sizeof(MSG)) {
938 memcpy(r, data, sizeof(MSG));
939 } else {
940 result = false;
941 NOTREACHED();
944 return result;
947 void ParamTraits<MSG>::Log(const param_type& p, std::string* l) {
948 l->append("<MSG>");
951 #endif // OS_WIN
953 } // namespace IPC