Update base::StartsWith calls to new form.
[chromium-blink-merge.git] / ipc / ipc_message_utils.cc
blobb6b979278a9e387a9af83c9ca2da97de130426b6
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<base::DictionaryValue>::Write(Message* m,
453 const param_type& p) {
454 WriteValue(m, &p, 0);
457 bool ParamTraits<base::DictionaryValue>::Read(const Message* m,
458 base::PickleIterator* iter,
459 param_type* r) {
460 int type;
461 if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_DICTIONARY)
462 return false;
464 return ReadDictionaryValue(m, iter, r, 0);
467 void ParamTraits<base::DictionaryValue>::Log(const param_type& p,
468 std::string* l) {
469 std::string json;
470 base::JSONWriter::Write(p, &json);
471 l->append(json);
474 #if defined(OS_POSIX)
475 void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
476 const bool valid = p.fd >= 0;
477 WriteParam(m, valid);
479 if (!valid)
480 return;
482 if (p.auto_close) {
483 if (!m->WriteAttachment(
484 new internal::PlatformFileAttachment(base::ScopedFD(p.fd))))
485 NOTREACHED();
486 } else {
487 if (!m->WriteAttachment(new internal::PlatformFileAttachment(p.fd)))
488 NOTREACHED();
492 bool ParamTraits<base::FileDescriptor>::Read(const Message* m,
493 base::PickleIterator* iter,
494 param_type* r) {
495 *r = base::FileDescriptor();
497 bool valid;
498 if (!ReadParam(m, iter, &valid))
499 return false;
501 // TODO(morrita): Seems like this should return false.
502 if (!valid)
503 return true;
505 scoped_refptr<MessageAttachment> attachment;
506 if (!m->ReadAttachment(iter, &attachment))
507 return false;
509 *r = base::FileDescriptor(attachment->TakePlatformFile(), true);
510 return true;
513 void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
514 std::string* l) {
515 if (p.auto_close) {
516 l->append(base::StringPrintf("FD(%d auto-close)", p.fd));
517 } else {
518 l->append(base::StringPrintf("FD(%d)", p.fd));
521 #endif // defined(OS_POSIX)
523 #if defined(OS_MACOSX) && !defined(OS_IOS)
524 void ParamTraits<base::SharedMemoryHandle>::Write(Message* m,
525 const param_type& p) {
526 m->WriteInt(p.GetType());
528 if (p.GetType() == base::SharedMemoryHandle::POSIX)
529 ParamTraits<base::FileDescriptor>::Write(m, p.GetFileDescriptor());
532 bool ParamTraits<base::SharedMemoryHandle>::Read(const Message* m,
533 base::PickleIterator* iter,
534 param_type* r) {
535 base::SharedMemoryHandle::TypeWireFormat type;
536 if (!iter->ReadInt(&type))
537 return false;
539 base::SharedMemoryHandle::Type shm_type = base::SharedMemoryHandle::POSIX;
540 switch (type) {
541 case base::SharedMemoryHandle::POSIX:
542 case base::SharedMemoryHandle::MACH: {
543 shm_type = static_cast<base::SharedMemoryHandle::Type>(type);
544 break;
546 default:
547 return false;
550 if (shm_type == base::SharedMemoryHandle::POSIX) {
551 base::FileDescriptor file_descriptor;
553 bool success =
554 ParamTraits<base::FileDescriptor>::Read(m, iter, &file_descriptor);
555 if (!success)
556 return false;
558 *r = base::SharedMemoryHandle(file_descriptor.fd,
559 file_descriptor.auto_close);
560 return true;
563 return true;
566 void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p,
567 std::string* l) {
568 if (p.GetType() == base::SharedMemoryHandle::POSIX) {
569 l->append(base::StringPrintf("Mechanism POSIX Fd"));
570 ParamTraits<base::FileDescriptor>::Log(p.GetFileDescriptor(), l);
573 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
575 void ParamTraits<base::FilePath>::Write(Message* m, const param_type& p) {
576 p.WriteToPickle(m);
579 bool ParamTraits<base::FilePath>::Read(const Message* m,
580 base::PickleIterator* iter,
581 param_type* r) {
582 return r->ReadFromPickle(iter);
585 void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) {
586 ParamTraits<base::FilePath::StringType>::Log(p.value(), l);
589 void ParamTraits<base::ListValue>::Write(Message* m, const param_type& p) {
590 WriteValue(m, &p, 0);
593 bool ParamTraits<base::ListValue>::Read(const Message* m,
594 base::PickleIterator* iter,
595 param_type* r) {
596 int type;
597 if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_LIST)
598 return false;
600 return ReadListValue(m, iter, r, 0);
603 void ParamTraits<base::ListValue>::Log(const param_type& p, std::string* l) {
604 std::string json;
605 base::JSONWriter::Write(p, &json);
606 l->append(json);
609 void ParamTraits<base::NullableString16>::Write(Message* m,
610 const param_type& p) {
611 WriteParam(m, p.string());
612 WriteParam(m, p.is_null());
615 bool ParamTraits<base::NullableString16>::Read(const Message* m,
616 base::PickleIterator* iter,
617 param_type* r) {
618 base::string16 string;
619 if (!ReadParam(m, iter, &string))
620 return false;
621 bool is_null;
622 if (!ReadParam(m, iter, &is_null))
623 return false;
624 *r = base::NullableString16(string, is_null);
625 return true;
628 void ParamTraits<base::NullableString16>::Log(const param_type& p,
629 std::string* l) {
630 l->append("(");
631 LogParam(p.string(), l);
632 l->append(", ");
633 LogParam(p.is_null(), l);
634 l->append(")");
637 void ParamTraits<base::File::Info>::Write(Message* m,
638 const param_type& p) {
639 WriteParam(m, p.size);
640 WriteParam(m, p.is_directory);
641 WriteParam(m, p.last_modified.ToDoubleT());
642 WriteParam(m, p.last_accessed.ToDoubleT());
643 WriteParam(m, p.creation_time.ToDoubleT());
646 bool ParamTraits<base::File::Info>::Read(const Message* m,
647 base::PickleIterator* iter,
648 param_type* p) {
649 double last_modified, last_accessed, creation_time;
650 if (!ReadParam(m, iter, &p->size) ||
651 !ReadParam(m, iter, &p->is_directory) ||
652 !ReadParam(m, iter, &last_modified) ||
653 !ReadParam(m, iter, &last_accessed) ||
654 !ReadParam(m, iter, &creation_time))
655 return false;
656 p->last_modified = base::Time::FromDoubleT(last_modified);
657 p->last_accessed = base::Time::FromDoubleT(last_accessed);
658 p->creation_time = base::Time::FromDoubleT(creation_time);
659 return true;
662 void ParamTraits<base::File::Info>::Log(const param_type& p,
663 std::string* l) {
664 l->append("(");
665 LogParam(p.size, l);
666 l->append(",");
667 LogParam(p.is_directory, l);
668 l->append(",");
669 LogParam(p.last_modified.ToDoubleT(), l);
670 l->append(",");
671 LogParam(p.last_accessed.ToDoubleT(), l);
672 l->append(",");
673 LogParam(p.creation_time.ToDoubleT(), l);
674 l->append(")");
677 void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
678 ParamTraits<int64>::Write(m, p.ToInternalValue());
681 bool ParamTraits<base::Time>::Read(const Message* m,
682 base::PickleIterator* iter,
683 param_type* r) {
684 int64 value;
685 if (!ParamTraits<int64>::Read(m, iter, &value))
686 return false;
687 *r = base::Time::FromInternalValue(value);
688 return true;
691 void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
692 ParamTraits<int64>::Log(p.ToInternalValue(), l);
695 void ParamTraits<base::TimeDelta>::Write(Message* m, const param_type& p) {
696 ParamTraits<int64>::Write(m, p.ToInternalValue());
699 bool ParamTraits<base::TimeDelta>::Read(const Message* m,
700 base::PickleIterator* iter,
701 param_type* r) {
702 int64 value;
703 bool ret = ParamTraits<int64>::Read(m, iter, &value);
704 if (ret)
705 *r = base::TimeDelta::FromInternalValue(value);
707 return ret;
710 void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) {
711 ParamTraits<int64>::Log(p.ToInternalValue(), l);
714 void ParamTraits<base::TimeTicks>::Write(Message* m, const param_type& p) {
715 ParamTraits<int64>::Write(m, p.ToInternalValue());
718 bool ParamTraits<base::TimeTicks>::Read(const Message* m,
719 base::PickleIterator* iter,
720 param_type* r) {
721 int64 value;
722 bool ret = ParamTraits<int64>::Read(m, iter, &value);
723 if (ret)
724 *r = base::TimeTicks::FromInternalValue(value);
726 return ret;
729 void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) {
730 ParamTraits<int64>::Log(p.ToInternalValue(), l);
733 void ParamTraits<base::TraceTicks>::Write(Message* m, const param_type& p) {
734 ParamTraits<int64>::Write(m, p.ToInternalValue());
737 bool ParamTraits<base::TraceTicks>::Read(const Message* m,
738 base::PickleIterator* iter,
739 param_type* r) {
740 int64 value;
741 bool ret = ParamTraits<int64>::Read(m, iter, &value);
742 if (ret)
743 *r = base::TraceTicks::FromInternalValue(value);
745 return ret;
748 void ParamTraits<base::TraceTicks>::Log(const param_type& p, std::string* l) {
749 ParamTraits<int64>::Log(p.ToInternalValue(), l);
752 void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
753 #if defined(OS_WIN)
754 // On Windows marshalling pipe handle is not supported.
755 DCHECK(p.pipe.handle == NULL);
756 #endif // defined (OS_WIN)
757 WriteParam(m, p.name);
758 #if defined(OS_POSIX)
759 WriteParam(m, p.socket);
760 #endif
763 bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m,
764 base::PickleIterator* iter,
765 param_type* r) {
766 return ReadParam(m, iter, &r->name)
767 #if defined(OS_POSIX)
768 && ReadParam(m, iter, &r->socket)
769 #endif
773 void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
774 std::string* l) {
775 l->append(base::StringPrintf("ChannelHandle(%s", p.name.c_str()));
776 #if defined(OS_POSIX)
777 l->append(", ");
778 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
779 #endif
780 l->append(")");
783 void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
784 WriteParam(m, p.channel);
785 WriteParam(m, p.routing_id);
786 WriteParam(m, p.type);
787 WriteParam(m, p.flags);
788 WriteParam(m, p.sent);
789 WriteParam(m, p.receive);
790 WriteParam(m, p.dispatch);
791 WriteParam(m, p.message_name);
792 WriteParam(m, p.params);
795 bool ParamTraits<LogData>::Read(const Message* m,
796 base::PickleIterator* iter,
797 param_type* r) {
798 return
799 ReadParam(m, iter, &r->channel) &&
800 ReadParam(m, iter, &r->routing_id) &&
801 ReadParam(m, iter, &r->type) &&
802 ReadParam(m, iter, &r->flags) &&
803 ReadParam(m, iter, &r->sent) &&
804 ReadParam(m, iter, &r->receive) &&
805 ReadParam(m, iter, &r->dispatch) &&
806 ReadParam(m, iter, &r->message_name) &&
807 ReadParam(m, iter, &r->params);
810 void ParamTraits<LogData>::Log(const param_type& p, std::string* l) {
811 // Doesn't make sense to implement this!
814 void ParamTraits<Message>::Write(Message* m, const Message& p) {
815 #if defined(OS_POSIX)
816 // We don't serialize the file descriptors in the nested message, so there
817 // better not be any.
818 DCHECK(!p.HasAttachments());
819 #endif
821 // Don't just write out the message. This is used to send messages between
822 // NaCl (Posix environment) and the browser (could be on Windows). The message
823 // header formats differ between these systems (so does handle sharing, but
824 // we already asserted we don't have any handles). So just write out the
825 // parts of the header we use.
827 // Be careful also to use only explicitly-sized types. The NaCl environment
828 // could be 64-bit and the host browser could be 32-bits. The nested message
829 // may or may not be safe to send between 32-bit and 64-bit systems, but we
830 // leave that up to the code sending the message to ensure.
831 m->WriteUInt32(static_cast<uint32>(p.routing_id()));
832 m->WriteUInt32(p.type());
833 m->WriteUInt32(p.flags());
834 m->WriteData(p.payload(), static_cast<uint32>(p.payload_size()));
837 bool ParamTraits<Message>::Read(const Message* m,
838 base::PickleIterator* iter,
839 Message* r) {
840 uint32 routing_id, type, flags;
841 if (!iter->ReadUInt32(&routing_id) ||
842 !iter->ReadUInt32(&type) ||
843 !iter->ReadUInt32(&flags))
844 return false;
846 int payload_size;
847 const char* payload;
848 if (!iter->ReadData(&payload, &payload_size))
849 return false;
851 r->SetHeaderValues(static_cast<int32>(routing_id), type, flags);
852 return r->WriteBytes(payload, payload_size);
855 void ParamTraits<Message>::Log(const Message& p, std::string* l) {
856 l->append("<IPC::Message>");
859 #if defined(OS_WIN)
860 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
861 // bit systems. That's why we use the Windows macros to convert to 32 bits.
862 void ParamTraits<HANDLE>::Write(Message* m, const param_type& p) {
863 m->WriteInt(HandleToLong(p));
866 bool ParamTraits<HANDLE>::Read(const Message* m,
867 base::PickleIterator* iter,
868 param_type* r) {
869 int32 temp;
870 if (!iter->ReadInt(&temp))
871 return false;
872 *r = LongToHandle(temp);
873 return true;
876 void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) {
877 l->append(base::StringPrintf("0x%X", p));
880 void ParamTraits<LOGFONT>::Write(Message* m, const param_type& p) {
881 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
884 bool ParamTraits<LOGFONT>::Read(const Message* m,
885 base::PickleIterator* iter,
886 param_type* r) {
887 const char *data;
888 int data_size = 0;
889 if (iter->ReadData(&data, &data_size) && data_size == sizeof(LOGFONT)) {
890 const LOGFONT *font = reinterpret_cast<LOGFONT*>(const_cast<char*>(data));
891 if (_tcsnlen(font->lfFaceName, LF_FACESIZE) < LF_FACESIZE) {
892 memcpy(r, data, sizeof(LOGFONT));
893 return true;
897 NOTREACHED();
898 return false;
901 void ParamTraits<LOGFONT>::Log(const param_type& p, std::string* l) {
902 l->append(base::StringPrintf("<LOGFONT>"));
905 void ParamTraits<MSG>::Write(Message* m, const param_type& p) {
906 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
909 bool ParamTraits<MSG>::Read(const Message* m,
910 base::PickleIterator* iter,
911 param_type* r) {
912 const char *data;
913 int data_size = 0;
914 bool result = iter->ReadData(&data, &data_size);
915 if (result && data_size == sizeof(MSG)) {
916 memcpy(r, data, sizeof(MSG));
917 } else {
918 result = false;
919 NOTREACHED();
922 return result;
925 void ParamTraits<MSG>::Log(const param_type& p, std::string* l) {
926 l->append("<MSG>");
929 #endif // OS_WIN
931 } // namespace IPC