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 <stddef.h>
8 #include <stdint.h>
9
10 #include "base/files/file_path.h"
11 #include "base/json/json_writer.h"
12 #include "base/strings/nullable_string16.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/time/time.h"
16 #include "base/values.h"
17 #include "build/build_config.h"
18 #include "ipc/ipc_channel_handle.h"
19 #include "ipc/ipc_message_attachment.h"
20 #include "ipc/ipc_message_attachment_set.h"
21 #include "ipc/ipc_mojo_param_traits.h"
22
23 #if defined(OS_POSIX)
24 #include "ipc/ipc_platform_file_attachment_posix.h"
25 #endif
26
27 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
28 #include "base/memory/shared_memory_handle.h"
29 #endif // (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN)
30
31 #if defined(OS_MACOSX) && !defined(OS_IOS)
32 #include "ipc/mach_port_mac.h"
33 #endif
34
35 #if defined(OS_WIN)
36 #include <tchar.h>
37 #include "ipc/handle_win.h"
38 #endif
39
40 namespace IPC {
41
42 namespace {
43
44 const int kMaxRecursionDepth = 100;
45
46 template<typename CharType>
LogBytes(const std::vector<CharType> & data,std::string * out)47 void LogBytes(const std::vector<CharType>& data, std::string* out) {
48 #if defined(OS_WIN)
49 // Windows has a GUI for logging, which can handle arbitrary binary data.
50 for (size_t i = 0; i < data.size(); ++i)
51 out->push_back(data[i]);
52 #else
53 // On POSIX, we log to stdout, which we assume can display ASCII.
54 static const size_t kMaxBytesToLog = 100;
55 for (size_t i = 0; i < std::min(data.size(), kMaxBytesToLog); ++i) {
56 if (isprint(data[i]))
57 out->push_back(data[i]);
58 else
59 out->append(
60 base::StringPrintf("[%02X]", static_cast<unsigned char>(data[i])));
61 }
62 if (data.size() > kMaxBytesToLog) {
63 out->append(base::StringPrintf(
64 " and %u more bytes",
65 static_cast<unsigned>(data.size() - kMaxBytesToLog)));
66 }
67 #endif
68 }
69
70 bool ReadValue(const base::Pickle* m,
71 base::PickleIterator* iter,
72 base::Value** value,
73 int recursion);
74
GetValueSize(base::PickleSizer * sizer,const base::Value * value,int recursion)75 void GetValueSize(base::PickleSizer* sizer,
76 const base::Value* value,
77 int recursion) {
78 if (recursion > kMaxRecursionDepth) {
79 LOG(WARNING) << "Max recursion depth hit in GetValueSize.";
80 return;
81 }
82
83 sizer->AddInt();
84 switch (value->GetType()) {
85 case base::Value::TYPE_NULL:
86 break;
87 case base::Value::TYPE_BOOLEAN:
88 sizer->AddBool();
89 break;
90 case base::Value::TYPE_INTEGER:
91 sizer->AddInt();
92 break;
93 case base::Value::TYPE_DOUBLE:
94 sizer->AddDouble();
95 break;
96 case base::Value::TYPE_STRING: {
97 const base::StringValue* result;
98 value->GetAsString(&result);
99 if (value->GetAsString(&result)) {
100 DCHECK(result);
101 GetParamSize(sizer, result->GetString());
102 } else {
103 std::string str;
104 bool as_string_result = value->GetAsString(&str);
105 DCHECK(as_string_result);
106 GetParamSize(sizer, str);
107 }
108 break;
109 }
110 case base::Value::TYPE_BINARY: {
111 const base::BinaryValue* binary =
112 static_cast<const base::BinaryValue*>(value);
113 sizer->AddData(static_cast<int>(binary->GetSize()));
114 break;
115 }
116 case base::Value::TYPE_DICTIONARY: {
117 sizer->AddInt();
118 const base::DictionaryValue* dict =
119 static_cast<const base::DictionaryValue*>(value);
120 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
121 it.Advance()) {
122 GetParamSize(sizer, it.key());
123 GetValueSize(sizer, &it.value(), recursion + 1);
124 }
125 break;
126 }
127 case base::Value::TYPE_LIST: {
128 sizer->AddInt();
129 const base::ListValue* list = static_cast<const base::ListValue*>(value);
130 for (const auto& entry : *list) {
131 GetValueSize(sizer, entry.get(), recursion + 1);
132 }
133 break;
134 }
135 default:
136 NOTREACHED() << "Invalid base::Value type.";
137 }
138 }
139
WriteValue(base::Pickle * m,const base::Value * value,int recursion)140 void WriteValue(base::Pickle* m, const base::Value* value, int recursion) {
141 bool result;
142 if (recursion > kMaxRecursionDepth) {
143 LOG(WARNING) << "Max recursion depth hit in WriteValue.";
144 return;
145 }
146
147 m->WriteInt(value->GetType());
148
149 switch (value->GetType()) {
150 case base::Value::TYPE_NULL:
151 break;
152 case base::Value::TYPE_BOOLEAN: {
153 bool val;
154 result = value->GetAsBoolean(&val);
155 DCHECK(result);
156 WriteParam(m, val);
157 break;
158 }
159 case base::Value::TYPE_INTEGER: {
160 int val;
161 result = value->GetAsInteger(&val);
162 DCHECK(result);
163 WriteParam(m, val);
164 break;
165 }
166 case base::Value::TYPE_DOUBLE: {
167 double val;
168 result = value->GetAsDouble(&val);
169 DCHECK(result);
170 WriteParam(m, val);
171 break;
172 }
173 case base::Value::TYPE_STRING: {
174 std::string val;
175 result = value->GetAsString(&val);
176 DCHECK(result);
177 WriteParam(m, val);
178 break;
179 }
180 case base::Value::TYPE_BINARY: {
181 const base::BinaryValue* binary =
182 static_cast<const base::BinaryValue*>(value);
183 m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
184 break;
185 }
186 case base::Value::TYPE_DICTIONARY: {
187 const base::DictionaryValue* dict =
188 static_cast<const base::DictionaryValue*>(value);
189
190 WriteParam(m, static_cast<int>(dict->size()));
191
192 for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
193 it.Advance()) {
194 WriteParam(m, it.key());
195 WriteValue(m, &it.value(), recursion + 1);
196 }
197 break;
198 }
199 case base::Value::TYPE_LIST: {
200 const base::ListValue* list = static_cast<const base::ListValue*>(value);
201 WriteParam(m, static_cast<int>(list->GetSize()));
202 for (const auto& entry : *list) {
203 WriteValue(m, entry.get(), recursion + 1);
204 }
205 break;
206 }
207 }
208 }
209
210 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated
211 // object.
ReadDictionaryValue(const base::Pickle * m,base::PickleIterator * iter,base::DictionaryValue * value,int recursion)212 bool ReadDictionaryValue(const base::Pickle* m,
213 base::PickleIterator* iter,
214 base::DictionaryValue* value,
215 int recursion) {
216 int size;
217 if (!ReadParam(m, iter, &size))
218 return false;
219
220 for (int i = 0; i < size; ++i) {
221 std::string key;
222 base::Value* subval;
223 if (!ReadParam(m, iter, &key) ||
224 !ReadValue(m, iter, &subval, recursion + 1))
225 return false;
226 value->SetWithoutPathExpansion(key, subval);
227 }
228
229 return true;
230 }
231
232 // Helper for ReadValue that reads a ReadListValue into a pre-allocated
233 // object.
ReadListValue(const base::Pickle * m,base::PickleIterator * iter,base::ListValue * value,int recursion)234 bool ReadListValue(const base::Pickle* m,
235 base::PickleIterator* iter,
236 base::ListValue* value,
237 int recursion) {
238 int size;
239 if (!ReadParam(m, iter, &size))
240 return false;
241
242 for (int i = 0; i < size; ++i) {
243 base::Value* subval;
244 if (!ReadValue(m, iter, &subval, recursion + 1))
245 return false;
246 value->Set(i, subval);
247 }
248
249 return true;
250 }
251
ReadValue(const base::Pickle * m,base::PickleIterator * iter,base::Value ** value,int recursion)252 bool ReadValue(const base::Pickle* m,
253 base::PickleIterator* iter,
254 base::Value** value,
255 int recursion) {
256 if (recursion > kMaxRecursionDepth) {
257 LOG(WARNING) << "Max recursion depth hit in ReadValue.";
258 return false;
259 }
260
261 int type;
262 if (!ReadParam(m, iter, &type))
263 return false;
264
265 switch (type) {
266 case base::Value::TYPE_NULL:
267 *value = base::Value::CreateNullValue().release();
268 break;
269 case base::Value::TYPE_BOOLEAN: {
270 bool val;
271 if (!ReadParam(m, iter, &val))
272 return false;
273 *value = new base::FundamentalValue(val);
274 break;
275 }
276 case base::Value::TYPE_INTEGER: {
277 int val;
278 if (!ReadParam(m, iter, &val))
279 return false;
280 *value = new base::FundamentalValue(val);
281 break;
282 }
283 case base::Value::TYPE_DOUBLE: {
284 double val;
285 if (!ReadParam(m, iter, &val))
286 return false;
287 *value = new base::FundamentalValue(val);
288 break;
289 }
290 case base::Value::TYPE_STRING: {
291 std::string val;
292 if (!ReadParam(m, iter, &val))
293 return false;
294 *value = new base::StringValue(val);
295 break;
296 }
297 case base::Value::TYPE_BINARY: {
298 const char* data;
299 int length;
300 if (!iter->ReadData(&data, &length))
301 return false;
302 std::unique_ptr<base::BinaryValue> val =
303 base::BinaryValue::CreateWithCopiedBuffer(data, length);
304 *value = val.release();
305 break;
306 }
307 case base::Value::TYPE_DICTIONARY: {
308 std::unique_ptr<base::DictionaryValue> val(new base::DictionaryValue());
309 if (!ReadDictionaryValue(m, iter, val.get(), recursion))
310 return false;
311 *value = val.release();
312 break;
313 }
314 case base::Value::TYPE_LIST: {
315 std::unique_ptr<base::ListValue> val(new base::ListValue());
316 if (!ReadListValue(m, iter, val.get(), recursion))
317 return false;
318 *value = val.release();
319 break;
320 }
321 default:
322 return false;
323 }
324
325 return true;
326 }
327
328 } // namespace
329
330 // -----------------------------------------------------------------------------
331
LogData()332 LogData::LogData()
333 : routing_id(0),
334 type(0),
335 sent(0),
336 receive(0),
337 dispatch(0) {
338 }
339
340 LogData::LogData(const LogData& other) = default;
341
~LogData()342 LogData::~LogData() {
343 }
344
Log(const param_type & p,std::string * l)345 void ParamTraits<bool>::Log(const param_type& p, std::string* l) {
346 l->append(p ? "true" : "false");
347 }
348
GetSize(base::PickleSizer * sizer,const param_type & p)349 void ParamTraits<signed char>::GetSize(base::PickleSizer* sizer,
350 const param_type& p) {
351 sizer->AddBytes(sizeof(param_type));
352 }
353
Write(base::Pickle * m,const param_type & p)354 void ParamTraits<signed char>::Write(base::Pickle* m, const param_type& p) {
355 m->WriteBytes(&p, sizeof(param_type));
356 }
357
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)358 bool ParamTraits<signed char>::Read(const base::Pickle* m,
359 base::PickleIterator* iter,
360 param_type* r) {
361 const char* data;
362 if (!iter->ReadBytes(&data, sizeof(param_type)))
363 return false;
364 memcpy(r, data, sizeof(param_type));
365 return true;
366 }
367
Log(const param_type & p,std::string * l)368 void ParamTraits<signed char>::Log(const param_type& p, std::string* l) {
369 l->append(base::IntToString(p));
370 }
371
GetSize(base::PickleSizer * sizer,const param_type & p)372 void ParamTraits<unsigned char>::GetSize(base::PickleSizer* sizer,
373 const param_type& p) {
374 sizer->AddBytes(sizeof(param_type));
375 }
376
Write(base::Pickle * m,const param_type & p)377 void ParamTraits<unsigned char>::Write(base::Pickle* m, const param_type& p) {
378 m->WriteBytes(&p, sizeof(param_type));
379 }
380
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)381 bool ParamTraits<unsigned char>::Read(const base::Pickle* m,
382 base::PickleIterator* iter,
383 param_type* r) {
384 const char* data;
385 if (!iter->ReadBytes(&data, sizeof(param_type)))
386 return false;
387 memcpy(r, data, sizeof(param_type));
388 return true;
389 }
390
Log(const param_type & p,std::string * l)391 void ParamTraits<unsigned char>::Log(const param_type& p, std::string* l) {
392 l->append(base::UintToString(p));
393 }
394
GetSize(base::PickleSizer * sizer,const param_type & p)395 void ParamTraits<unsigned short>::GetSize(base::PickleSizer* sizer,
396 const param_type& p) {
397 sizer->AddBytes(sizeof(param_type));
398 }
399
Write(base::Pickle * m,const param_type & p)400 void ParamTraits<unsigned short>::Write(base::Pickle* m, const param_type& p) {
401 m->WriteBytes(&p, sizeof(param_type));
402 }
403
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)404 bool ParamTraits<unsigned short>::Read(const base::Pickle* m,
405 base::PickleIterator* iter,
406 param_type* r) {
407 const char* data;
408 if (!iter->ReadBytes(&data, sizeof(param_type)))
409 return false;
410 memcpy(r, data, sizeof(param_type));
411 return true;
412 }
413
Log(const param_type & p,std::string * l)414 void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
415 l->append(base::UintToString(p));
416 }
417
Log(const param_type & p,std::string * l)418 void ParamTraits<int>::Log(const param_type& p, std::string* l) {
419 l->append(base::IntToString(p));
420 }
421
Log(const param_type & p,std::string * l)422 void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
423 l->append(base::UintToString(p));
424 }
425
426 #if defined(OS_WIN) || defined(OS_LINUX) || \
427 (defined(OS_ANDROID) && defined(ARCH_CPU_64_BITS))
Log(const param_type & p,std::string * l)428 void ParamTraits<long>::Log(const param_type& p, std::string* l) {
429 l->append(base::Int64ToString(static_cast<int64_t>(p)));
430 }
431
Log(const param_type & p,std::string * l)432 void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
433 l->append(base::Uint64ToString(static_cast<uint64_t>(p)));
434 }
435 #endif
436
Log(const param_type & p,std::string * l)437 void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
438 l->append(base::Int64ToString(static_cast<int64_t>(p)));
439 }
440
Log(const param_type & p,std::string * l)441 void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
442 l->append(base::Uint64ToString(p));
443 }
444
Log(const param_type & p,std::string * l)445 void ParamTraits<float>::Log(const param_type& p, std::string* l) {
446 l->append(base::StringPrintf("%e", p));
447 }
448
GetSize(base::PickleSizer * sizer,const param_type & p)449 void ParamTraits<double>::GetSize(base::PickleSizer* sizer,
450 const param_type& p) {
451 sizer->AddBytes(sizeof(param_type));
452 }
453
Write(base::Pickle * m,const param_type & p)454 void ParamTraits<double>::Write(base::Pickle* m, const param_type& p) {
455 m->WriteBytes(reinterpret_cast<const char*>(&p), sizeof(param_type));
456 }
457
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)458 bool ParamTraits<double>::Read(const base::Pickle* m,
459 base::PickleIterator* iter,
460 param_type* r) {
461 const char *data;
462 if (!iter->ReadBytes(&data, sizeof(*r))) {
463 NOTREACHED();
464 return false;
465 }
466 memcpy(r, data, sizeof(param_type));
467 return true;
468 }
469
Log(const param_type & p,std::string * l)470 void ParamTraits<double>::Log(const param_type& p, std::string* l) {
471 l->append(base::StringPrintf("%e", p));
472 }
473
474
Log(const param_type & p,std::string * l)475 void ParamTraits<std::string>::Log(const param_type& p, std::string* l) {
476 l->append(p);
477 }
478
Log(const param_type & p,std::string * l)479 void ParamTraits<base::string16>::Log(const param_type& p, std::string* l) {
480 l->append(base::UTF16ToUTF8(p));
481 }
482
GetSize(base::PickleSizer * sizer,const param_type & p)483 void ParamTraits<std::vector<char>>::GetSize(base::PickleSizer* sizer,
484 const param_type& p) {
485 sizer->AddData(static_cast<int>(p.size()));
486 }
487
Write(base::Pickle * m,const param_type & p)488 void ParamTraits<std::vector<char>>::Write(base::Pickle* m,
489 const param_type& p) {
490 if (p.empty()) {
491 m->WriteData(NULL, 0);
492 } else {
493 m->WriteData(&p.front(), static_cast<int>(p.size()));
494 }
495 }
496
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)497 bool ParamTraits<std::vector<char>>::Read(const base::Pickle* m,
498 base::PickleIterator* iter,
499 param_type* r) {
500 const char *data;
501 int data_size = 0;
502 if (!iter->ReadData(&data, &data_size) || data_size < 0)
503 return false;
504 r->resize(data_size);
505 if (data_size)
506 memcpy(&r->front(), data, data_size);
507 return true;
508 }
509
Log(const param_type & p,std::string * l)510 void ParamTraits<std::vector<char> >::Log(const param_type& p, std::string* l) {
511 LogBytes(p, l);
512 }
513
GetSize(base::PickleSizer * sizer,const param_type & p)514 void ParamTraits<std::vector<unsigned char>>::GetSize(base::PickleSizer* sizer,
515 const param_type& p) {
516 sizer->AddData(static_cast<int>(p.size()));
517 }
518
Write(base::Pickle * m,const param_type & p)519 void ParamTraits<std::vector<unsigned char>>::Write(base::Pickle* m,
520 const param_type& p) {
521 if (p.empty()) {
522 m->WriteData(NULL, 0);
523 } else {
524 m->WriteData(reinterpret_cast<const char*>(&p.front()),
525 static_cast<int>(p.size()));
526 }
527 }
528
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)529 bool ParamTraits<std::vector<unsigned char>>::Read(const base::Pickle* m,
530 base::PickleIterator* iter,
531 param_type* r) {
532 const char *data;
533 int data_size = 0;
534 if (!iter->ReadData(&data, &data_size) || data_size < 0)
535 return false;
536 r->resize(data_size);
537 if (data_size)
538 memcpy(&r->front(), data, data_size);
539 return true;
540 }
541
Log(const param_type & p,std::string * l)542 void ParamTraits<std::vector<unsigned char> >::Log(const param_type& p,
543 std::string* l) {
544 LogBytes(p, l);
545 }
546
GetSize(base::PickleSizer * sizer,const param_type & p)547 void ParamTraits<std::vector<bool>>::GetSize(base::PickleSizer* sizer,
548 const param_type& p) {
549 GetParamSize(sizer, static_cast<int>(p.size()));
550 for (size_t i = 0; i < p.size(); ++i)
551 GetParamSize(sizer, static_cast<bool>(p[i]));
552 }
553
Write(base::Pickle * m,const param_type & p)554 void ParamTraits<std::vector<bool>>::Write(base::Pickle* m,
555 const param_type& p) {
556 WriteParam(m, static_cast<int>(p.size()));
557 // Cast to bool below is required because libc++'s
558 // vector<bool>::const_reference is different from bool, and we want to avoid
559 // writing an extra specialization of ParamTraits for it.
560 for (size_t i = 0; i < p.size(); i++)
561 WriteParam(m, static_cast<bool>(p[i]));
562 }
563
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)564 bool ParamTraits<std::vector<bool>>::Read(const base::Pickle* m,
565 base::PickleIterator* iter,
566 param_type* r) {
567 int size;
568 // ReadLength() checks for < 0 itself.
569 if (!iter->ReadLength(&size))
570 return false;
571 r->resize(size);
572 for (int i = 0; i < size; i++) {
573 bool value;
574 if (!ReadParam(m, iter, &value))
575 return false;
576 (*r)[i] = value;
577 }
578 return true;
579 }
580
Log(const param_type & p,std::string * l)581 void ParamTraits<std::vector<bool> >::Log(const param_type& p, std::string* l) {
582 for (size_t i = 0; i < p.size(); ++i) {
583 if (i != 0)
584 l->push_back(' ');
585 LogParam(static_cast<bool>(p[i]), l);
586 }
587 }
588
Write(base::Pickle * m,const param_type & p)589 void ParamTraits<BrokerableAttachment::AttachmentId>::Write(
590 base::Pickle* m,
591 const param_type& p) {
592 m->WriteBytes(p.nonce, BrokerableAttachment::kNonceSize);
593 }
594
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)595 bool ParamTraits<BrokerableAttachment::AttachmentId>::Read(
596 const base::Pickle* m,
597 base::PickleIterator* iter,
598 param_type* r) {
599 const char* data;
600 if (!iter->ReadBytes(&data, BrokerableAttachment::kNonceSize))
601 return false;
602 memcpy(r->nonce, data, BrokerableAttachment::kNonceSize);
603 return true;
604 }
605
Log(const param_type & p,std::string * l)606 void ParamTraits<BrokerableAttachment::AttachmentId>::Log(const param_type& p,
607 std::string* l) {
608 l->append(base::HexEncode(p.nonce, BrokerableAttachment::kNonceSize));
609 }
610
GetSize(base::PickleSizer * sizer,const param_type & p)611 void ParamTraits<base::DictionaryValue>::GetSize(base::PickleSizer* sizer,
612 const param_type& p) {
613 GetValueSize(sizer, &p, 0);
614 }
615
Write(base::Pickle * m,const param_type & p)616 void ParamTraits<base::DictionaryValue>::Write(base::Pickle* m,
617 const param_type& p) {
618 WriteValue(m, &p, 0);
619 }
620
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)621 bool ParamTraits<base::DictionaryValue>::Read(const base::Pickle* m,
622 base::PickleIterator* iter,
623 param_type* r) {
624 int type;
625 if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_DICTIONARY)
626 return false;
627
628 return ReadDictionaryValue(m, iter, r, 0);
629 }
630
Log(const param_type & p,std::string * l)631 void ParamTraits<base::DictionaryValue>::Log(const param_type& p,
632 std::string* l) {
633 std::string json;
634 base::JSONWriter::Write(p, &json);
635 l->append(json);
636 }
637
638 #if defined(OS_POSIX)
GetSize(base::PickleSizer * sizer,const param_type & p)639 void ParamTraits<base::FileDescriptor>::GetSize(base::PickleSizer* sizer,
640 const param_type& p) {
641 GetParamSize(sizer, p.fd >= 0);
642 if (p.fd >= 0)
643 sizer->AddAttachment();
644 }
645
Write(base::Pickle * m,const param_type & p)646 void ParamTraits<base::FileDescriptor>::Write(base::Pickle* m,
647 const param_type& p) {
648 const bool valid = p.fd >= 0;
649 WriteParam(m, valid);
650
651 if (!valid)
652 return;
653
654 if (p.auto_close) {
655 if (!m->WriteAttachment(
656 new internal::PlatformFileAttachment(base::ScopedFD(p.fd))))
657 NOTREACHED();
658 } else {
659 if (!m->WriteAttachment(new internal::PlatformFileAttachment(p.fd)))
660 NOTREACHED();
661 }
662 }
663
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)664 bool ParamTraits<base::FileDescriptor>::Read(const base::Pickle* m,
665 base::PickleIterator* iter,
666 param_type* r) {
667 *r = base::FileDescriptor();
668
669 bool valid;
670 if (!ReadParam(m, iter, &valid))
671 return false;
672
673 // TODO(morrita): Seems like this should return false.
674 if (!valid)
675 return true;
676
677 scoped_refptr<base::Pickle::Attachment> attachment;
678 if (!m->ReadAttachment(iter, &attachment))
679 return false;
680
681 *r = base::FileDescriptor(
682 static_cast<MessageAttachment*>(attachment.get())->TakePlatformFile(),
683 true);
684 return true;
685 }
686
Log(const param_type & p,std::string * l)687 void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
688 std::string* l) {
689 if (p.auto_close) {
690 l->append(base::StringPrintf("FD(%d auto-close)", p.fd));
691 } else {
692 l->append(base::StringPrintf("FD(%d)", p.fd));
693 }
694 }
695 #endif // defined(OS_POSIX)
696
697 #if defined(OS_MACOSX) && !defined(OS_IOS)
GetSize(base::PickleSizer * sizer,const param_type & p)698 void ParamTraits<base::SharedMemoryHandle>::GetSize(base::PickleSizer* sizer,
699 const param_type& p) {
700 GetParamSize(sizer, p.GetMemoryObject());
701 uint32_t dummy = 0;
702 GetParamSize(sizer, dummy);
703 }
704
Write(base::Pickle * m,const param_type & p)705 void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m,
706 const param_type& p) {
707 MachPortMac mach_port_mac(p.GetMemoryObject());
708 ParamTraits<MachPortMac>::Write(m, mach_port_mac);
709 size_t size = 0;
710 bool result = p.GetSize(&size);
711 DCHECK(result);
712 ParamTraits<uint32_t>::Write(m, static_cast<uint32_t>(size));
713
714 // If the caller intended to pass ownership to the IPC stack, release a
715 // reference.
716 if (p.OwnershipPassesToIPC())
717 p.Close();
718 }
719
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)720 bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m,
721 base::PickleIterator* iter,
722 param_type* r) {
723 MachPortMac mach_port_mac;
724 if (!ParamTraits<MachPortMac>::Read(m, iter, &mach_port_mac))
725 return false;
726
727 uint32_t size;
728 if (!ParamTraits<uint32_t>::Read(m, iter, &size))
729 return false;
730
731 *r = base::SharedMemoryHandle(mach_port_mac.get_mach_port(),
732 static_cast<size_t>(size),
733 base::GetCurrentProcId());
734 return true;
735 }
736
Log(const param_type & p,std::string * l)737 void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p,
738 std::string* l) {
739 l->append("Mach port: ");
740 LogParam(p.GetMemoryObject(), l);
741 }
742
743 #elif defined(OS_WIN)
GetSize(base::PickleSizer * s,const param_type & p)744 void ParamTraits<base::SharedMemoryHandle>::GetSize(base::PickleSizer* s,
745 const param_type& p) {
746 GetParamSize(s, p.NeedsBrokering());
747 if (p.NeedsBrokering()) {
748 GetParamSize(s, p.GetHandle());
749 } else {
750 GetParamSize(s, HandleToLong(p.GetHandle()));
751 }
752 }
753
Write(base::Pickle * m,const param_type & p)754 void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m,
755 const param_type& p) {
756 m->WriteBool(p.NeedsBrokering());
757
758 if (p.NeedsBrokering()) {
759 HandleWin handle_win(p.GetHandle(), HandleWin::DUPLICATE);
760 ParamTraits<HandleWin>::Write(m, handle_win);
761
762 // If the caller intended to pass ownership to the IPC stack, release a
763 // reference.
764 if (p.OwnershipPassesToIPC() && p.BelongsToCurrentProcess())
765 p.Close();
766 } else {
767 m->WriteInt(HandleToLong(p.GetHandle()));
768 }
769 }
770
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)771 bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m,
772 base::PickleIterator* iter,
773 param_type* r) {
774 bool needs_brokering;
775 if (!iter->ReadBool(&needs_brokering))
776 return false;
777
778 if (needs_brokering) {
779 HandleWin handle_win;
780 if (!ParamTraits<HandleWin>::Read(m, iter, &handle_win))
781 return false;
782 *r = base::SharedMemoryHandle(handle_win.get_handle(),
783 base::GetCurrentProcId());
784 return true;
785 }
786
787 int handle_int;
788 if (!iter->ReadInt(&handle_int))
789 return false;
790 HANDLE handle = LongToHandle(handle_int);
791 *r = base::SharedMemoryHandle(handle, base::GetCurrentProcId());
792 return true;
793 }
794
Log(const param_type & p,std::string * l)795 void ParamTraits<base::SharedMemoryHandle>::Log(const param_type& p,
796 std::string* l) {
797 LogParam(p.GetHandle(), l);
798 l->append(" needs brokering: ");
799 LogParam(p.NeedsBrokering(), l);
800 }
801 #endif // defined(OS_MACOSX) && !defined(OS_IOS)
802
GetSize(base::PickleSizer * sizer,const param_type & p)803 void ParamTraits<base::FilePath>::GetSize(base::PickleSizer* sizer,
804 const param_type& p) {
805 p.GetSizeForPickle(sizer);
806 }
807
Write(base::Pickle * m,const param_type & p)808 void ParamTraits<base::FilePath>::Write(base::Pickle* m, const param_type& p) {
809 p.WriteToPickle(m);
810 }
811
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)812 bool ParamTraits<base::FilePath>::Read(const base::Pickle* m,
813 base::PickleIterator* iter,
814 param_type* r) {
815 return r->ReadFromPickle(iter);
816 }
817
Log(const param_type & p,std::string * l)818 void ParamTraits<base::FilePath>::Log(const param_type& p, std::string* l) {
819 ParamTraits<base::FilePath::StringType>::Log(p.value(), l);
820 }
821
GetSize(base::PickleSizer * sizer,const param_type & p)822 void ParamTraits<base::ListValue>::GetSize(base::PickleSizer* sizer,
823 const param_type& p) {
824 GetValueSize(sizer, &p, 0);
825 }
826
Write(base::Pickle * m,const param_type & p)827 void ParamTraits<base::ListValue>::Write(base::Pickle* m, const param_type& p) {
828 WriteValue(m, &p, 0);
829 }
830
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)831 bool ParamTraits<base::ListValue>::Read(const base::Pickle* m,
832 base::PickleIterator* iter,
833 param_type* r) {
834 int type;
835 if (!ReadParam(m, iter, &type) || type != base::Value::TYPE_LIST)
836 return false;
837
838 return ReadListValue(m, iter, r, 0);
839 }
840
Log(const param_type & p,std::string * l)841 void ParamTraits<base::ListValue>::Log(const param_type& p, std::string* l) {
842 std::string json;
843 base::JSONWriter::Write(p, &json);
844 l->append(json);
845 }
846
GetSize(base::PickleSizer * sizer,const param_type & p)847 void ParamTraits<base::NullableString16>::GetSize(base::PickleSizer* sizer,
848 const param_type& p) {
849 GetParamSize(sizer, p.string());
850 GetParamSize(sizer, p.is_null());
851 }
852
Write(base::Pickle * m,const param_type & p)853 void ParamTraits<base::NullableString16>::Write(base::Pickle* m,
854 const param_type& p) {
855 WriteParam(m, p.string());
856 WriteParam(m, p.is_null());
857 }
858
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)859 bool ParamTraits<base::NullableString16>::Read(const base::Pickle* m,
860 base::PickleIterator* iter,
861 param_type* r) {
862 base::string16 string;
863 if (!ReadParam(m, iter, &string))
864 return false;
865 bool is_null;
866 if (!ReadParam(m, iter, &is_null))
867 return false;
868 *r = base::NullableString16(string, is_null);
869 return true;
870 }
871
Log(const param_type & p,std::string * l)872 void ParamTraits<base::NullableString16>::Log(const param_type& p,
873 std::string* l) {
874 l->append("(");
875 LogParam(p.string(), l);
876 l->append(", ");
877 LogParam(p.is_null(), l);
878 l->append(")");
879 }
880
GetSize(base::PickleSizer * sizer,const param_type & p)881 void ParamTraits<base::File::Info>::GetSize(base::PickleSizer* sizer,
882 const param_type& p) {
883 GetParamSize(sizer, p.size);
884 GetParamSize(sizer, p.is_directory);
885 GetParamSize(sizer, p.last_modified.ToDoubleT());
886 GetParamSize(sizer, p.last_accessed.ToDoubleT());
887 GetParamSize(sizer, p.creation_time.ToDoubleT());
888 }
889
Write(base::Pickle * m,const param_type & p)890 void ParamTraits<base::File::Info>::Write(base::Pickle* m,
891 const param_type& p) {
892 WriteParam(m, p.size);
893 WriteParam(m, p.is_directory);
894 WriteParam(m, p.last_modified.ToDoubleT());
895 WriteParam(m, p.last_accessed.ToDoubleT());
896 WriteParam(m, p.creation_time.ToDoubleT());
897 }
898
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * p)899 bool ParamTraits<base::File::Info>::Read(const base::Pickle* m,
900 base::PickleIterator* iter,
901 param_type* p) {
902 double last_modified, last_accessed, creation_time;
903 if (!ReadParam(m, iter, &p->size) ||
904 !ReadParam(m, iter, &p->is_directory) ||
905 !ReadParam(m, iter, &last_modified) ||
906 !ReadParam(m, iter, &last_accessed) ||
907 !ReadParam(m, iter, &creation_time))
908 return false;
909 p->last_modified = base::Time::FromDoubleT(last_modified);
910 p->last_accessed = base::Time::FromDoubleT(last_accessed);
911 p->creation_time = base::Time::FromDoubleT(creation_time);
912 return true;
913 }
914
Log(const param_type & p,std::string * l)915 void ParamTraits<base::File::Info>::Log(const param_type& p,
916 std::string* l) {
917 l->append("(");
918 LogParam(p.size, l);
919 l->append(",");
920 LogParam(p.is_directory, l);
921 l->append(",");
922 LogParam(p.last_modified.ToDoubleT(), l);
923 l->append(",");
924 LogParam(p.last_accessed.ToDoubleT(), l);
925 l->append(",");
926 LogParam(p.creation_time.ToDoubleT(), l);
927 l->append(")");
928 }
929
GetSize(base::PickleSizer * sizer,const param_type & p)930 void ParamTraits<base::Time>::GetSize(base::PickleSizer* sizer,
931 const param_type& p) {
932 sizer->AddInt64();
933 }
934
Write(base::Pickle * m,const param_type & p)935 void ParamTraits<base::Time>::Write(base::Pickle* m, const param_type& p) {
936 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
937 }
938
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)939 bool ParamTraits<base::Time>::Read(const base::Pickle* m,
940 base::PickleIterator* iter,
941 param_type* r) {
942 int64_t value;
943 if (!ParamTraits<int64_t>::Read(m, iter, &value))
944 return false;
945 *r = base::Time::FromInternalValue(value);
946 return true;
947 }
948
Log(const param_type & p,std::string * l)949 void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
950 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
951 }
952
GetSize(base::PickleSizer * sizer,const param_type & p)953 void ParamTraits<base::TimeDelta>::GetSize(base::PickleSizer* sizer,
954 const param_type& p) {
955 sizer->AddInt64();
956 }
957
Write(base::Pickle * m,const param_type & p)958 void ParamTraits<base::TimeDelta>::Write(base::Pickle* m, const param_type& p) {
959 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
960 }
961
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)962 bool ParamTraits<base::TimeDelta>::Read(const base::Pickle* m,
963 base::PickleIterator* iter,
964 param_type* r) {
965 int64_t value;
966 bool ret = ParamTraits<int64_t>::Read(m, iter, &value);
967 if (ret)
968 *r = base::TimeDelta::FromInternalValue(value);
969
970 return ret;
971 }
972
Log(const param_type & p,std::string * l)973 void ParamTraits<base::TimeDelta>::Log(const param_type& p, std::string* l) {
974 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
975 }
976
GetSize(base::PickleSizer * sizer,const param_type & p)977 void ParamTraits<base::TimeTicks>::GetSize(base::PickleSizer* sizer,
978 const param_type& p) {
979 sizer->AddInt64();
980 }
981
Write(base::Pickle * m,const param_type & p)982 void ParamTraits<base::TimeTicks>::Write(base::Pickle* m, const param_type& p) {
983 ParamTraits<int64_t>::Write(m, p.ToInternalValue());
984 }
985
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)986 bool ParamTraits<base::TimeTicks>::Read(const base::Pickle* m,
987 base::PickleIterator* iter,
988 param_type* r) {
989 int64_t value;
990 bool ret = ParamTraits<int64_t>::Read(m, iter, &value);
991 if (ret)
992 *r = base::TimeTicks::FromInternalValue(value);
993
994 return ret;
995 }
996
Log(const param_type & p,std::string * l)997 void ParamTraits<base::TimeTicks>::Log(const param_type& p, std::string* l) {
998 ParamTraits<int64_t>::Log(p.ToInternalValue(), l);
999 }
1000
GetSize(base::PickleSizer * sizer,const param_type & p)1001 void ParamTraits<IPC::ChannelHandle>::GetSize(base::PickleSizer* sizer,
1002 const param_type& p) {
1003 GetParamSize(sizer, p.name);
1004 #if defined(OS_POSIX)
1005 GetParamSize(sizer, p.socket);
1006 #endif
1007 GetParamSize(sizer, p.mojo_handle);
1008 }
1009
Write(base::Pickle * m,const param_type & p)1010 void ParamTraits<IPC::ChannelHandle>::Write(base::Pickle* m,
1011 const param_type& p) {
1012 #if defined(OS_WIN)
1013 // On Windows marshalling pipe handle is not supported.
1014 DCHECK(p.pipe.handle == NULL);
1015 #endif // defined (OS_WIN)
1016 WriteParam(m, p.name);
1017 #if defined(OS_POSIX)
1018 WriteParam(m, p.socket);
1019 #endif
1020 WriteParam(m, p.mojo_handle);
1021 }
1022
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)1023 bool ParamTraits<IPC::ChannelHandle>::Read(const base::Pickle* m,
1024 base::PickleIterator* iter,
1025 param_type* r) {
1026 return ReadParam(m, iter, &r->name)
1027 #if defined(OS_POSIX)
1028 && ReadParam(m, iter, &r->socket)
1029 #endif
1030 && ReadParam(m, iter, &r->mojo_handle);
1031 }
1032
Log(const param_type & p,std::string * l)1033 void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
1034 std::string* l) {
1035 l->append(base::StringPrintf("ChannelHandle(%s", p.name.c_str()));
1036 #if defined(OS_POSIX)
1037 l->append(", ");
1038 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
1039 #endif
1040 l->append(", ");
1041 LogParam(p.mojo_handle, l);
1042 l->append(")");
1043 }
1044
GetSize(base::PickleSizer * sizer,const param_type & p)1045 void ParamTraits<LogData>::GetSize(base::PickleSizer* sizer,
1046 const param_type& p) {
1047 GetParamSize(sizer, p.channel);
1048 GetParamSize(sizer, p.routing_id);
1049 GetParamSize(sizer, p.type);
1050 GetParamSize(sizer, p.flags);
1051 GetParamSize(sizer, p.sent);
1052 GetParamSize(sizer, p.receive);
1053 GetParamSize(sizer, p.dispatch);
1054 GetParamSize(sizer, p.message_name);
1055 GetParamSize(sizer, p.params);
1056 }
1057
Write(base::Pickle * m,const param_type & p)1058 void ParamTraits<LogData>::Write(base::Pickle* m, const param_type& p) {
1059 WriteParam(m, p.channel);
1060 WriteParam(m, p.routing_id);
1061 WriteParam(m, p.type);
1062 WriteParam(m, p.flags);
1063 WriteParam(m, p.sent);
1064 WriteParam(m, p.receive);
1065 WriteParam(m, p.dispatch);
1066 WriteParam(m, p.message_name);
1067 WriteParam(m, p.params);
1068 }
1069
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)1070 bool ParamTraits<LogData>::Read(const base::Pickle* m,
1071 base::PickleIterator* iter,
1072 param_type* r) {
1073 return
1074 ReadParam(m, iter, &r->channel) &&
1075 ReadParam(m, iter, &r->routing_id) &&
1076 ReadParam(m, iter, &r->type) &&
1077 ReadParam(m, iter, &r->flags) &&
1078 ReadParam(m, iter, &r->sent) &&
1079 ReadParam(m, iter, &r->receive) &&
1080 ReadParam(m, iter, &r->dispatch) &&
1081 ReadParam(m, iter, &r->message_name) &&
1082 ReadParam(m, iter, &r->params);
1083 }
1084
Log(const param_type & p,std::string * l)1085 void ParamTraits<LogData>::Log(const param_type& p, std::string* l) {
1086 // Doesn't make sense to implement this!
1087 }
1088
Write(base::Pickle * m,const Message & p)1089 void ParamTraits<Message>::Write(base::Pickle* m, const Message& p) {
1090 #if defined(OS_POSIX)
1091 // We don't serialize the file descriptors in the nested message, so there
1092 // better not be any.
1093 DCHECK(!p.HasAttachments());
1094 #endif
1095
1096 // Don't just write out the message. This is used to send messages between
1097 // NaCl (Posix environment) and the browser (could be on Windows). The message
1098 // header formats differ between these systems (so does handle sharing, but
1099 // we already asserted we don't have any handles). So just write out the
1100 // parts of the header we use.
1101 //
1102 // Be careful also to use only explicitly-sized types. The NaCl environment
1103 // could be 64-bit and the host browser could be 32-bits. The nested message
1104 // may or may not be safe to send between 32-bit and 64-bit systems, but we
1105 // leave that up to the code sending the message to ensure.
1106 m->WriteUInt32(static_cast<uint32_t>(p.routing_id()));
1107 m->WriteUInt32(p.type());
1108 m->WriteUInt32(p.flags());
1109 m->WriteData(p.payload(), static_cast<uint32_t>(p.payload_size()));
1110 }
1111
Read(const base::Pickle * m,base::PickleIterator * iter,Message * r)1112 bool ParamTraits<Message>::Read(const base::Pickle* m,
1113 base::PickleIterator* iter,
1114 Message* r) {
1115 uint32_t routing_id, type, flags;
1116 if (!iter->ReadUInt32(&routing_id) ||
1117 !iter->ReadUInt32(&type) ||
1118 !iter->ReadUInt32(&flags))
1119 return false;
1120
1121 int payload_size;
1122 const char* payload;
1123 if (!iter->ReadData(&payload, &payload_size))
1124 return false;
1125
1126 r->SetHeaderValues(static_cast<int32_t>(routing_id), type, flags);
1127 return r->WriteBytes(payload, payload_size);
1128 }
1129
Log(const Message & p,std::string * l)1130 void ParamTraits<Message>::Log(const Message& p, std::string* l) {
1131 l->append("<IPC::Message>");
1132 }
1133
1134 #if defined(OS_WIN)
GetSize(base::PickleSizer * sizer,const param_type & p)1135 void ParamTraits<HANDLE>::GetSize(base::PickleSizer* sizer,
1136 const param_type& p) {
1137 sizer->AddInt();
1138 }
1139
1140 // Note that HWNDs/HANDLE/HCURSOR/HACCEL etc are always 32 bits, even on 64
1141 // bit systems. That's why we use the Windows macros to convert to 32 bits.
Write(base::Pickle * m,const param_type & p)1142 void ParamTraits<HANDLE>::Write(base::Pickle* m, const param_type& p) {
1143 m->WriteInt(HandleToLong(p));
1144 }
1145
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)1146 bool ParamTraits<HANDLE>::Read(const base::Pickle* m,
1147 base::PickleIterator* iter,
1148 param_type* r) {
1149 int32_t temp;
1150 if (!iter->ReadInt(&temp))
1151 return false;
1152 *r = LongToHandle(temp);
1153 return true;
1154 }
1155
Log(const param_type & p,std::string * l)1156 void ParamTraits<HANDLE>::Log(const param_type& p, std::string* l) {
1157 l->append(base::StringPrintf("0x%p", p));
1158 }
1159
GetSize(base::PickleSizer * sizer,const param_type & p)1160 void ParamTraits<LOGFONT>::GetSize(base::PickleSizer* sizer,
1161 const param_type& p) {
1162 sizer->AddData(sizeof(LOGFONT));
1163 }
1164
Write(base::Pickle * m,const param_type & p)1165 void ParamTraits<LOGFONT>::Write(base::Pickle* m, const param_type& p) {
1166 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(LOGFONT));
1167 }
1168
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)1169 bool ParamTraits<LOGFONT>::Read(const base::Pickle* m,
1170 base::PickleIterator* iter,
1171 param_type* r) {
1172 const char *data;
1173 int data_size = 0;
1174 if (iter->ReadData(&data, &data_size) && data_size == sizeof(LOGFONT)) {
1175 const LOGFONT *font = reinterpret_cast<LOGFONT*>(const_cast<char*>(data));
1176 if (_tcsnlen(font->lfFaceName, LF_FACESIZE) < LF_FACESIZE) {
1177 memcpy(r, data, sizeof(LOGFONT));
1178 return true;
1179 }
1180 }
1181
1182 NOTREACHED();
1183 return false;
1184 }
1185
Log(const param_type & p,std::string * l)1186 void ParamTraits<LOGFONT>::Log(const param_type& p, std::string* l) {
1187 l->append(base::StringPrintf("<LOGFONT>"));
1188 }
1189
GetSize(base::PickleSizer * sizer,const param_type & p)1190 void ParamTraits<MSG>::GetSize(base::PickleSizer* sizer, const param_type& p) {
1191 sizer->AddData(sizeof(MSG));
1192 }
1193
Write(base::Pickle * m,const param_type & p)1194 void ParamTraits<MSG>::Write(base::Pickle* m, const param_type& p) {
1195 m->WriteData(reinterpret_cast<const char*>(&p), sizeof(MSG));
1196 }
1197
Read(const base::Pickle * m,base::PickleIterator * iter,param_type * r)1198 bool ParamTraits<MSG>::Read(const base::Pickle* m,
1199 base::PickleIterator* iter,
1200 param_type* r) {
1201 const char *data;
1202 int data_size = 0;
1203 bool result = iter->ReadData(&data, &data_size);
1204 if (result && data_size == sizeof(MSG)) {
1205 memcpy(r, data, sizeof(MSG));
1206 } else {
1207 result = false;
1208 NOTREACHED();
1209 }
1210
1211 return result;
1212 }
1213
Log(const param_type & p,std::string * l)1214 void ParamTraits<MSG>::Log(const param_type& p, std::string* l) {
1215 l->append("<MSG>");
1216 }
1217
1218 #endif // OS_WIN
1219
1220 } // namespace IPC
1221