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