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"
20 #include "ipc/ipc_platform_file_attachment_posix.h"
23 #if defined(OS_MACOSX) && !defined(OS_IOS)
24 #include "base/memory/shared_memory_handle.h"
25 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
35 const int kMaxRecursionDepth
= 100;
37 template<typename CharType
>
38 void LogBytes(const std::vector
<CharType
>& data
, std::string
* out
) {
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
]);
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
) {
48 out
->push_back(data
[i
]);
51 base::StringPrintf("[%02X]", static_cast<unsigned char>(data
[i
])));
53 if (data
.size() > kMaxBytesToLog
) {
54 out
->append(base::StringPrintf(
56 static_cast<unsigned>(data
.size() - kMaxBytesToLog
)));
61 bool ReadValue(const Message
* m
,
62 base::PickleIterator
* iter
,
66 void WriteValue(Message
* m
, const base::Value
* value
, int recursion
) {
68 if (recursion
> kMaxRecursionDepth
) {
69 LOG(WARNING
) << "Max recursion depth hit in WriteValue.";
73 m
->WriteInt(value
->GetType());
75 switch (value
->GetType()) {
76 case base::Value::TYPE_NULL
:
78 case base::Value::TYPE_BOOLEAN
: {
80 result
= value
->GetAsBoolean(&val
);
85 case base::Value::TYPE_INTEGER
: {
87 result
= value
->GetAsInteger(&val
);
92 case base::Value::TYPE_DOUBLE
: {
94 result
= value
->GetAsDouble(&val
);
99 case base::Value::TYPE_STRING
: {
101 result
= value
->GetAsString(&val
);
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()));
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();
120 WriteParam(m
, it
.key());
121 WriteValue(m
, &it
.value(), recursion
+ 1);
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);
137 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated
139 bool ReadDictionaryValue(const Message
* m
,
140 base::PickleIterator
* iter
,
141 base::DictionaryValue
* value
,
144 if (!ReadParam(m
, iter
, &size
))
147 for (int i
= 0; i
< size
; ++i
) {
150 if (!ReadParam(m
, iter
, &key
) ||
151 !ReadValue(m
, iter
, &subval
, recursion
+ 1))
153 value
->SetWithoutPathExpansion(key
, subval
);
159 // Helper for ReadValue that reads a ReadListValue into a pre-allocated
161 bool ReadListValue(const Message
* m
,
162 base::PickleIterator
* iter
,
163 base::ListValue
* value
,
166 if (!ReadParam(m
, iter
, &size
))
169 for (int i
= 0; i
< size
; ++i
) {
171 if (!ReadValue(m
, iter
, &subval
, recursion
+ 1))
173 value
->Set(i
, subval
);
179 bool ReadValue(const Message
* m
,
180 base::PickleIterator
* iter
,
183 if (recursion
> kMaxRecursionDepth
) {
184 LOG(WARNING
) << "Max recursion depth hit in ReadValue.";
189 if (!ReadParam(m
, iter
, &type
))
193 case base::Value::TYPE_NULL
:
194 *value
= base::Value::CreateNullValue().release();
196 case base::Value::TYPE_BOOLEAN
: {
198 if (!ReadParam(m
, iter
, &val
))
200 *value
= new base::FundamentalValue(val
);
203 case base::Value::TYPE_INTEGER
: {
205 if (!ReadParam(m
, iter
, &val
))
207 *value
= new base::FundamentalValue(val
);
210 case base::Value::TYPE_DOUBLE
: {
212 if (!ReadParam(m
, iter
, &val
))
214 *value
= new base::FundamentalValue(val
);
217 case base::Value::TYPE_STRING
: {
219 if (!ReadParam(m
, iter
, &val
))
221 *value
= new base::StringValue(val
);
224 case base::Value::TYPE_BINARY
: {
227 if (!iter
->ReadData(&data
, &length
))
229 *value
= base::BinaryValue::CreateWithCopiedBuffer(data
, length
);
232 case base::Value::TYPE_DICTIONARY
: {
233 scoped_ptr
<base::DictionaryValue
> val(new base::DictionaryValue());
234 if (!ReadDictionaryValue(m
, iter
, val
.get(), recursion
))
236 *value
= val
.release();
239 case base::Value::TYPE_LIST
: {
240 scoped_ptr
<base::ListValue
> val(new base::ListValue());
241 if (!ReadListValue(m
, iter
, val
.get(), recursion
))
243 *value
= val
.release();
255 // -----------------------------------------------------------------------------
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
,
280 if (!iter
->ReadBytes(&data
, sizeof(param_type
)))
282 memcpy(r
, data
, sizeof(param_type
));
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
,
298 if (!iter
->ReadBytes(&data
, sizeof(param_type
)))
300 memcpy(r
, data
, sizeof(param_type
));
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
,
344 if (!iter
->ReadBytes(&data
, sizeof(*r
))) {
348 memcpy(r
, data
, sizeof(param_type
));
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
) {
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
) {
367 m
->WriteData(NULL
, 0);
369 m
->WriteData(&p
.front(), static_cast<int>(p
.size()));
373 bool ParamTraits
<std::vector
<char>>::Read(const Message
* m
,
374 base::PickleIterator
* iter
,
378 if (!iter
->ReadData(&data
, &data_size
) || data_size
< 0)
380 r
->resize(data_size
);
382 memcpy(&r
->front(), data
, data_size
);
386 void ParamTraits
<std::vector
<char> >::Log(const param_type
& p
, std::string
* l
) {
390 void ParamTraits
<std::vector
<unsigned char> >::Write(Message
* m
,
391 const param_type
& p
) {
393 m
->WriteData(NULL
, 0);
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
,
405 if (!iter
->ReadData(&data
, &data_size
) || data_size
< 0)
407 r
->resize(data_size
);
409 memcpy(&r
->front(), data
, data_size
);
413 void ParamTraits
<std::vector
<unsigned char> >::Log(const param_type
& p
,
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
,
431 // ReadLength() checks for < 0 itself.
432 if (!iter
->ReadLength(&size
))
435 for (int i
= 0; i
< size
; i
++) {
437 if (!ReadParam(m
, iter
, &value
))
444 void ParamTraits
<std::vector
<bool> >::Log(const param_type
& p
, std::string
* l
) {
445 for (size_t i
= 0; i
< p
.size(); ++i
) {
448 LogParam(static_cast<bool>(p
[i
]), l
);
452 void ParamTraits
<BrokerableAttachment::AttachmentId
>::Write(
454 const param_type
& p
) {
455 m
->WriteBytes(p
.nonce
, static_cast<int>(BrokerableAttachment::kNonceSize
));
458 bool ParamTraits
<BrokerableAttachment::AttachmentId
>::Read(
460 base::PickleIterator
* iter
,
463 if (!iter
->ReadBytes(&data
,
464 static_cast<int>(BrokerableAttachment::kNonceSize
))) {
467 memcpy(r
->nonce
, data
, BrokerableAttachment::kNonceSize
);
471 void ParamTraits
<BrokerableAttachment::AttachmentId
>::Log(const param_type
& p
,
473 l
->append(base::HexEncode(p
.nonce
, BrokerableAttachment::kNonceSize
));
476 void ParamTraits
<base::DictionaryValue
>::Write(Message
* m
,
477 const param_type
& p
) {
478 WriteValue(m
, &p
, 0);
481 bool ParamTraits
<base::DictionaryValue
>::Read(const Message
* m
,
482 base::PickleIterator
* iter
,
485 if (!ReadParam(m
, iter
, &type
) || type
!= base::Value::TYPE_DICTIONARY
)
488 return ReadDictionaryValue(m
, iter
, r
, 0);
491 void ParamTraits
<base::DictionaryValue
>::Log(const param_type
& p
,
494 base::JSONWriter::Write(p
, &json
);
498 #if defined(OS_POSIX)
499 void ParamTraits
<base::FileDescriptor
>::Write(Message
* m
, const param_type
& p
) {
500 const bool valid
= p
.fd
>= 0;
501 WriteParam(m
, valid
);
507 if (!m
->WriteAttachment(
508 new internal::PlatformFileAttachment(base::ScopedFD(p
.fd
))))
511 if (!m
->WriteAttachment(new internal::PlatformFileAttachment(p
.fd
)))
516 bool ParamTraits
<base::FileDescriptor
>::Read(const Message
* m
,
517 base::PickleIterator
* iter
,
519 *r
= base::FileDescriptor();
522 if (!ReadParam(m
, iter
, &valid
))
525 // TODO(morrita): Seems like this should return false.
529 scoped_refptr
<MessageAttachment
> attachment
;
530 if (!m
->ReadAttachment(iter
, &attachment
))
533 *r
= base::FileDescriptor(attachment
->TakePlatformFile(), true);
537 void ParamTraits
<base::FileDescriptor
>::Log(const param_type
& p
,
540 l
->append(base::StringPrintf("FD(%d auto-close)", p
.fd
));
542 l
->append(base::StringPrintf("FD(%d)", p
.fd
));
545 #endif // defined(OS_POSIX)
547 #if defined(OS_MACOSX) && !defined(OS_IOS)
548 void ParamTraits
<base::SharedMemoryHandle
>::Write(Message
* m
,
549 const param_type
& p
) {
550 m
->WriteInt(p
.GetType());
552 if (p
.GetType() == base::SharedMemoryHandle::POSIX
)
553 ParamTraits
<base::FileDescriptor
>::Write(m
, p
.GetFileDescriptor());
556 bool ParamTraits
<base::SharedMemoryHandle
>::Read(const Message
* m
,
557 base::PickleIterator
* iter
,
559 base::SharedMemoryHandle::TypeWireFormat type
;
560 if (!iter
->ReadInt(&type
))
563 base::SharedMemoryHandle::Type shm_type
= base::SharedMemoryHandle::POSIX
;
565 case base::SharedMemoryHandle::POSIX
:
566 case base::SharedMemoryHandle::MACH
: {
567 shm_type
= static_cast<base::SharedMemoryHandle::Type
>(type
);
574 if (shm_type
== base::SharedMemoryHandle::POSIX
) {
575 base::FileDescriptor file_descriptor
;
578 ParamTraits
<base::FileDescriptor
>::Read(m
, iter
, &file_descriptor
);
582 *r
= base::SharedMemoryHandle(file_descriptor
.fd
,
583 file_descriptor
.auto_close
);
590 void ParamTraits
<base::SharedMemoryHandle
>::Log(const param_type
& p
,
592 if (p
.GetType() == base::SharedMemoryHandle::POSIX
) {
593 l
->append(base::StringPrintf("Mechanism POSIX Fd"));
594 ParamTraits
<base::FileDescriptor
>::Log(p
.GetFileDescriptor(), l
);
597 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
599 void ParamTraits
<base::FilePath
>::Write(Message
* m
, const param_type
& p
) {
603 bool ParamTraits
<base::FilePath
>::Read(const Message
* m
,
604 base::PickleIterator
* iter
,
606 return r
->ReadFromPickle(iter
);
609 void ParamTraits
<base::FilePath
>::Log(const param_type
& p
, std::string
* l
) {
610 ParamTraits
<base::FilePath::StringType
>::Log(p
.value(), l
);
613 void ParamTraits
<base::ListValue
>::Write(Message
* m
, const param_type
& p
) {
614 WriteValue(m
, &p
, 0);
617 bool ParamTraits
<base::ListValue
>::Read(const Message
* m
,
618 base::PickleIterator
* iter
,
621 if (!ReadParam(m
, iter
, &type
) || type
!= base::Value::TYPE_LIST
)
624 return ReadListValue(m
, iter
, r
, 0);
627 void ParamTraits
<base::ListValue
>::Log(const param_type
& p
, std::string
* l
) {
629 base::JSONWriter::Write(p
, &json
);
633 void ParamTraits
<base::NullableString16
>::Write(Message
* m
,
634 const param_type
& p
) {
635 WriteParam(m
, p
.string());
636 WriteParam(m
, p
.is_null());
639 bool ParamTraits
<base::NullableString16
>::Read(const Message
* m
,
640 base::PickleIterator
* iter
,
642 base::string16 string
;
643 if (!ReadParam(m
, iter
, &string
))
646 if (!ReadParam(m
, iter
, &is_null
))
648 *r
= base::NullableString16(string
, is_null
);
652 void ParamTraits
<base::NullableString16
>::Log(const param_type
& p
,
655 LogParam(p
.string(), l
);
657 LogParam(p
.is_null(), l
);
661 void ParamTraits
<base::File::Info
>::Write(Message
* m
,
662 const param_type
& p
) {
663 WriteParam(m
, p
.size
);
664 WriteParam(m
, p
.is_directory
);
665 WriteParam(m
, p
.last_modified
.ToDoubleT());
666 WriteParam(m
, p
.last_accessed
.ToDoubleT());
667 WriteParam(m
, p
.creation_time
.ToDoubleT());
670 bool ParamTraits
<base::File::Info
>::Read(const Message
* m
,
671 base::PickleIterator
* iter
,
673 double last_modified
, last_accessed
, creation_time
;
674 if (!ReadParam(m
, iter
, &p
->size
) ||
675 !ReadParam(m
, iter
, &p
->is_directory
) ||
676 !ReadParam(m
, iter
, &last_modified
) ||
677 !ReadParam(m
, iter
, &last_accessed
) ||
678 !ReadParam(m
, iter
, &creation_time
))
680 p
->last_modified
= base::Time::FromDoubleT(last_modified
);
681 p
->last_accessed
= base::Time::FromDoubleT(last_accessed
);
682 p
->creation_time
= base::Time::FromDoubleT(creation_time
);
686 void ParamTraits
<base::File::Info
>::Log(const param_type
& p
,
691 LogParam(p
.is_directory
, l
);
693 LogParam(p
.last_modified
.ToDoubleT(), l
);
695 LogParam(p
.last_accessed
.ToDoubleT(), l
);
697 LogParam(p
.creation_time
.ToDoubleT(), l
);
701 void ParamTraits
<base::Time
>::Write(Message
* m
, const param_type
& p
) {
702 ParamTraits
<int64
>::Write(m
, p
.ToInternalValue());
705 bool ParamTraits
<base::Time
>::Read(const Message
* m
,
706 base::PickleIterator
* iter
,
709 if (!ParamTraits
<int64
>::Read(m
, iter
, &value
))
711 *r
= base::Time::FromInternalValue(value
);
715 void ParamTraits
<base::Time
>::Log(const param_type
& p
, std::string
* l
) {
716 ParamTraits
<int64
>::Log(p
.ToInternalValue(), l
);
719 void ParamTraits
<base::TimeDelta
>::Write(Message
* m
, const param_type
& p
) {
720 ParamTraits
<int64
>::Write(m
, p
.ToInternalValue());
723 bool ParamTraits
<base::TimeDelta
>::Read(const Message
* m
,
724 base::PickleIterator
* iter
,
727 bool ret
= ParamTraits
<int64
>::Read(m
, iter
, &value
);
729 *r
= base::TimeDelta::FromInternalValue(value
);
734 void ParamTraits
<base::TimeDelta
>::Log(const param_type
& p
, std::string
* l
) {
735 ParamTraits
<int64
>::Log(p
.ToInternalValue(), l
);
738 void ParamTraits
<base::TimeTicks
>::Write(Message
* m
, const param_type
& p
) {
739 ParamTraits
<int64
>::Write(m
, p
.ToInternalValue());
742 bool ParamTraits
<base::TimeTicks
>::Read(const Message
* m
,
743 base::PickleIterator
* iter
,
746 bool ret
= ParamTraits
<int64
>::Read(m
, iter
, &value
);
748 *r
= base::TimeTicks::FromInternalValue(value
);
753 void ParamTraits
<base::TimeTicks
>::Log(const param_type
& p
, std::string
* l
) {
754 ParamTraits
<int64
>::Log(p
.ToInternalValue(), l
);
757 void ParamTraits
<base::TraceTicks
>::Write(Message
* m
, const param_type
& p
) {
758 ParamTraits
<int64
>::Write(m
, p
.ToInternalValue());
761 bool ParamTraits
<base::TraceTicks
>::Read(const Message
* m
,
762 base::PickleIterator
* iter
,
765 bool ret
= ParamTraits
<int64
>::Read(m
, iter
, &value
);
767 *r
= base::TraceTicks::FromInternalValue(value
);
772 void ParamTraits
<base::TraceTicks
>::Log(const param_type
& p
, std::string
* l
) {
773 ParamTraits
<int64
>::Log(p
.ToInternalValue(), l
);
776 void ParamTraits
<IPC::ChannelHandle
>::Write(Message
* m
, const param_type
& p
) {
778 // On Windows marshalling pipe handle is not supported.
779 DCHECK(p
.pipe
.handle
== NULL
);
780 #endif // defined (OS_WIN)
781 WriteParam(m
, p
.name
);
782 #if defined(OS_POSIX)
783 WriteParam(m
, p
.socket
);
787 bool ParamTraits
<IPC::ChannelHandle
>::Read(const Message
* m
,
788 base::PickleIterator
* iter
,
790 return ReadParam(m
, iter
, &r
->name
)
791 #if defined(OS_POSIX)
792 && ReadParam(m
, iter
, &r
->socket
)
797 void ParamTraits
<IPC::ChannelHandle
>::Log(const param_type
& p
,
799 l
->append(base::StringPrintf("ChannelHandle(%s", p
.name
.c_str()));
800 #if defined(OS_POSIX)
802 ParamTraits
<base::FileDescriptor
>::Log(p
.socket
, l
);
807 void ParamTraits
<LogData
>::Write(Message
* m
, const param_type
& p
) {
808 WriteParam(m
, p
.channel
);
809 WriteParam(m
, p
.routing_id
);
810 WriteParam(m
, p
.type
);
811 WriteParam(m
, p
.flags
);
812 WriteParam(m
, p
.sent
);
813 WriteParam(m
, p
.receive
);
814 WriteParam(m
, p
.dispatch
);
815 WriteParam(m
, p
.message_name
);
816 WriteParam(m
, p
.params
);
819 bool ParamTraits
<LogData
>::Read(const Message
* m
,
820 base::PickleIterator
* iter
,
823 ReadParam(m
, iter
, &r
->channel
) &&
824 ReadParam(m
, iter
, &r
->routing_id
) &&
825 ReadParam(m
, iter
, &r
->type
) &&
826 ReadParam(m
, iter
, &r
->flags
) &&
827 ReadParam(m
, iter
, &r
->sent
) &&
828 ReadParam(m
, iter
, &r
->receive
) &&
829 ReadParam(m
, iter
, &r
->dispatch
) &&
830 ReadParam(m
, iter
, &r
->message_name
) &&
831 ReadParam(m
, iter
, &r
->params
);
834 void ParamTraits
<LogData
>::Log(const param_type
& p
, std::string
* l
) {
835 // Doesn't make sense to implement this!
838 void ParamTraits
<Message
>::Write(Message
* m
, const Message
& p
) {
839 #if defined(OS_POSIX)
840 // We don't serialize the file descriptors in the nested message, so there
841 // better not be any.
842 DCHECK(!p
.HasAttachments());
845 // Don't just write out the message. This is used to send messages between
846 // NaCl (Posix environment) and the browser (could be on Windows). The message
847 // header formats differ between these systems (so does handle sharing, but
848 // we already asserted we don't have any handles). So just write out the
849 // parts of the header we use.
851 // Be careful also to use only explicitly-sized types. The NaCl environment
852 // could be 64-bit and the host browser could be 32-bits. The nested message
853 // may or may not be safe to send between 32-bit and 64-bit systems, but we
854 // leave that up to the code sending the message to ensure.
855 m
->WriteUInt32(static_cast<uint32
>(p
.routing_id()));
856 m
->WriteUInt32(p
.type());
857 m
->WriteUInt32(p
.flags());
858 m
->WriteData(p
.payload(), static_cast<uint32
>(p
.payload_size()));
861 bool ParamTraits
<Message
>::Read(const Message
* m
,
862 base::PickleIterator
* iter
,
864 uint32 routing_id
, type
, flags
;
865 if (!iter
->ReadUInt32(&routing_id
) ||
866 !iter
->ReadUInt32(&type
) ||
867 !iter
->ReadUInt32(&flags
))
872 if (!iter
->ReadData(&payload
, &payload_size
))
875 r
->SetHeaderValues(static_cast<int32
>(routing_id
), type
, flags
);
876 return r
->WriteBytes(payload
, payload_size
);
879 void ParamTraits
<Message
>::Log(const Message
& p
, std::string
* l
) {
880 l
->append("<IPC::Message>");
884 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
885 // bit systems. That's why we use the Windows macros to convert to 32 bits.
886 void ParamTraits
<HANDLE
>::Write(Message
* m
, const param_type
& p
) {
887 m
->WriteInt(HandleToLong(p
));
890 bool ParamTraits
<HANDLE
>::Read(const Message
* m
,
891 base::PickleIterator
* iter
,
894 if (!iter
->ReadInt(&temp
))
896 *r
= LongToHandle(temp
);
900 void ParamTraits
<HANDLE
>::Log(const param_type
& p
, std::string
* l
) {
901 l
->append(base::StringPrintf("0x%X", p
));
904 void ParamTraits
<LOGFONT
>::Write(Message
* m
, const param_type
& p
) {
905 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(LOGFONT
));
908 bool ParamTraits
<LOGFONT
>::Read(const Message
* m
,
909 base::PickleIterator
* iter
,
913 if (iter
->ReadData(&data
, &data_size
) && data_size
== sizeof(LOGFONT
)) {
914 const LOGFONT
*font
= reinterpret_cast<LOGFONT
*>(const_cast<char*>(data
));
915 if (_tcsnlen(font
->lfFaceName
, LF_FACESIZE
) < LF_FACESIZE
) {
916 memcpy(r
, data
, sizeof(LOGFONT
));
925 void ParamTraits
<LOGFONT
>::Log(const param_type
& p
, std::string
* l
) {
926 l
->append(base::StringPrintf("<LOGFONT>"));
929 void ParamTraits
<MSG
>::Write(Message
* m
, const param_type
& p
) {
930 m
->WriteData(reinterpret_cast<const char*>(&p
), sizeof(MSG
));
933 bool ParamTraits
<MSG
>::Read(const Message
* m
,
934 base::PickleIterator
* iter
,
938 bool result
= iter
->ReadData(&data
, &data_size
);
939 if (result
&& data_size
== sizeof(MSG
)) {
940 memcpy(r
, data
, sizeof(MSG
));
949 void ParamTraits
<MSG
>::Log(const param_type
& p
, std::string
* l
) {