ash: Extend launcher first button to include leading inset.
[chromium-blink-merge.git] / ipc / ipc_message_utils.cc
blob8f27c52c3f0c05220976504028952672362dcd66
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/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 #if defined(OS_POSIX)
16 #include "ipc/file_descriptor_set_posix.h"
17 #endif
18 #include "ipc/ipc_channel_handle.h"
20 namespace IPC {
22 const int kMaxRecursionDepth = 100;
24 // Value serialization
26 static bool ReadValue(const Message* m, PickleIterator* iter, Value** value,
27 int recursion);
29 static void WriteValue(Message* m, const Value* value, int recursion) {
30 if (recursion > kMaxRecursionDepth) {
31 LOG(WARNING) << "Max recursion depth hit in WriteValue.";
32 return;
35 m->WriteInt(value->GetType());
37 switch (value->GetType()) {
38 case Value::TYPE_NULL:
39 break;
40 case Value::TYPE_BOOLEAN: {
41 bool val;
42 value->GetAsBoolean(&val);
43 WriteParam(m, val);
44 break;
46 case Value::TYPE_INTEGER: {
47 int val;
48 value->GetAsInteger(&val);
49 WriteParam(m, val);
50 break;
52 case Value::TYPE_DOUBLE: {
53 double val;
54 value->GetAsDouble(&val);
55 WriteParam(m, val);
56 break;
58 case Value::TYPE_STRING: {
59 std::string val;
60 value->GetAsString(&val);
61 WriteParam(m, val);
62 break;
64 case Value::TYPE_BINARY: {
65 const base::BinaryValue* binary =
66 static_cast<const base::BinaryValue*>(value);
67 m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
68 break;
70 case Value::TYPE_DICTIONARY: {
71 const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
73 WriteParam(m, static_cast<int>(dict->size()));
75 for (DictionaryValue::key_iterator it = dict->begin_keys();
76 it != dict->end_keys(); ++it) {
77 Value* subval;
78 if (dict->GetWithoutPathExpansion(*it, &subval)) {
79 WriteParam(m, *it);
80 WriteValue(m, subval, recursion + 1);
81 } else {
82 NOTREACHED() << "DictionaryValue iterators are filthy liars.";
85 break;
87 case Value::TYPE_LIST: {
88 const ListValue* list = static_cast<const ListValue*>(value);
89 WriteParam(m, static_cast<int>(list->GetSize()));
90 for (size_t i = 0; i < list->GetSize(); ++i) {
91 Value* subval;
92 if (list->Get(i, &subval)) {
93 WriteValue(m, subval, recursion + 1);
94 } else {
95 NOTREACHED() << "ListValue::GetSize is a filthy liar.";
98 break;
103 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated
104 // object.
105 static bool ReadDictionaryValue(const Message* m, PickleIterator* iter,
106 DictionaryValue* value, int recursion) {
107 int size;
108 if (!ReadParam(m, iter, &size))
109 return false;
111 for (int i = 0; i < size; ++i) {
112 std::string key;
113 Value* subval;
114 if (!ReadParam(m, iter, &key) ||
115 !ReadValue(m, iter, &subval, recursion + 1))
116 return false;
117 value->SetWithoutPathExpansion(key, subval);
120 return true;
123 // Helper for ReadValue that reads a ReadListValue into a pre-allocated
124 // object.
125 static bool ReadListValue(const Message* m, PickleIterator* iter,
126 ListValue* value, int recursion) {
127 int size;
128 if (!ReadParam(m, iter, &size))
129 return false;
131 for (int i = 0; i < size; ++i) {
132 Value* subval;
133 if (!ReadValue(m, iter, &subval, recursion + 1))
134 return false;
135 value->Set(i, subval);
138 return true;
141 static bool ReadValue(const Message* m, PickleIterator* iter, Value** value,
142 int recursion) {
143 if (recursion > kMaxRecursionDepth) {
144 LOG(WARNING) << "Max recursion depth hit in ReadValue.";
145 return false;
148 int type;
149 if (!ReadParam(m, iter, &type))
150 return false;
152 switch (type) {
153 case Value::TYPE_NULL:
154 *value = Value::CreateNullValue();
155 break;
156 case Value::TYPE_BOOLEAN: {
157 bool val;
158 if (!ReadParam(m, iter, &val))
159 return false;
160 *value = Value::CreateBooleanValue(val);
161 break;
163 case Value::TYPE_INTEGER: {
164 int val;
165 if (!ReadParam(m, iter, &val))
166 return false;
167 *value = Value::CreateIntegerValue(val);
168 break;
170 case Value::TYPE_DOUBLE: {
171 double val;
172 if (!ReadParam(m, iter, &val))
173 return false;
174 *value = Value::CreateDoubleValue(val);
175 break;
177 case Value::TYPE_STRING: {
178 std::string val;
179 if (!ReadParam(m, iter, &val))
180 return false;
181 *value = Value::CreateStringValue(val);
182 break;
184 case Value::TYPE_BINARY: {
185 const char* data;
186 int length;
187 if (!m->ReadData(iter, &data, &length))
188 return false;
189 *value = base::BinaryValue::CreateWithCopiedBuffer(data, length);
190 break;
192 case Value::TYPE_DICTIONARY: {
193 scoped_ptr<DictionaryValue> val(new DictionaryValue());
194 if (!ReadDictionaryValue(m, iter, val.get(), recursion))
195 return false;
196 *value = val.release();
197 break;
199 case Value::TYPE_LIST: {
200 scoped_ptr<ListValue> val(new ListValue());
201 if (!ReadListValue(m, iter, val.get(), recursion))
202 return false;
203 *value = val.release();
204 break;
206 default:
207 return false;
210 return true;
213 void ParamTraits<int>::Log(const param_type& p, std::string* l) {
214 l->append(base::IntToString(p));
217 void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
218 l->append(base::UintToString(p));
221 void ParamTraits<long>::Log(const param_type& p, std::string* l) {
222 l->append(base::Int64ToString(static_cast<int64>(p)));
225 void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
226 l->append(base::Uint64ToString(static_cast<uint64>(p)));
229 void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
230 l->append(base::Int64ToString(static_cast<int64>(p)));
233 void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
234 l->append(base::Uint64ToString(p));
237 void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) {
238 m->WriteBytes(&p, sizeof(param_type));
241 bool ParamTraits<unsigned short>::Read(const Message* m, PickleIterator* iter,
242 param_type* r) {
243 const char* data;
244 if (!m->ReadBytes(iter, &data, sizeof(param_type)))
245 return false;
246 memcpy(r, data, sizeof(param_type));
247 return true;
250 void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
251 l->append(base::UintToString(p));
254 void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
255 ParamTraits<int64>::Write(m, p.ToInternalValue());
258 bool ParamTraits<base::Time>::Read(const Message* m, PickleIterator* iter,
259 param_type* r) {
260 int64 value;
261 if (!ParamTraits<int64>::Read(m, iter, &value))
262 return false;
263 *r = base::Time::FromInternalValue(value);
264 return true;
267 void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
268 ParamTraits<int64>::Log(p.ToInternalValue(), l);
271 void ParamTraits<base::TimeDelta> ::Write(Message* m, const param_type& p) {
272 ParamTraits<int64> ::Write(m, p.ToInternalValue());
275 bool ParamTraits<base::TimeDelta> ::Read(const Message* m,
276 PickleIterator* iter,
277 param_type* r) {
278 int64 value;
279 bool ret = ParamTraits<int64> ::Read(m, iter, &value);
280 if (ret)
281 *r = base::TimeDelta::FromInternalValue(value);
283 return ret;
286 void ParamTraits<base::TimeDelta> ::Log(const param_type& p, std::string* l) {
287 ParamTraits<int64> ::Log(p.ToInternalValue(), l);
290 void ParamTraits<base::TimeTicks> ::Write(Message* m, const param_type& p) {
291 ParamTraits<int64> ::Write(m, p.ToInternalValue());
294 bool ParamTraits<base::TimeTicks> ::Read(const Message* m,
295 PickleIterator* iter,
296 param_type* r) {
297 int64 value;
298 bool ret = ParamTraits<int64> ::Read(m, iter, &value);
299 if (ret)
300 *r = base::TimeTicks::FromInternalValue(value);
302 return ret;
305 void ParamTraits<base::TimeTicks> ::Log(const param_type& p, std::string* l) {
306 ParamTraits<int64> ::Log(p.ToInternalValue(), l);
309 void ParamTraits<DictionaryValue>::Write(Message* m, const param_type& p) {
310 WriteValue(m, &p, 0);
313 bool ParamTraits<DictionaryValue>::Read(
314 const Message* m, PickleIterator* iter, param_type* r) {
315 int type;
316 if (!ReadParam(m, iter, &type) || type != Value::TYPE_DICTIONARY)
317 return false;
319 return ReadDictionaryValue(m, iter, r, 0);
322 void ParamTraits<DictionaryValue>::Log(const param_type& p, std::string* l) {
323 std::string json;
324 base::JSONWriter::Write(&p, &json);
325 l->append(json);
328 void ParamTraits<ListValue>::Write(Message* m, const param_type& p) {
329 WriteValue(m, &p, 0);
332 bool ParamTraits<ListValue>::Read(
333 const Message* m, PickleIterator* iter, param_type* r) {
334 int type;
335 if (!ReadParam(m, iter, &type) || type != Value::TYPE_LIST)
336 return false;
338 return ReadListValue(m, iter, r, 0);
341 void ParamTraits<ListValue>::Log(const param_type& p, std::string* l) {
342 std::string json;
343 base::JSONWriter::Write(&p, &json);
344 l->append(json);
347 void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
348 l->append(WideToUTF8(p));
351 void ParamTraits<NullableString16>::Write(Message* m, const param_type& p) {
352 WriteParam(m, p.string());
353 WriteParam(m, p.is_null());
356 bool ParamTraits<NullableString16>::Read(const Message* m, PickleIterator* iter,
357 param_type* r) {
358 string16 string;
359 if (!ReadParam(m, iter, &string))
360 return false;
361 bool is_null;
362 if (!ReadParam(m, iter, &is_null))
363 return false;
364 *r = NullableString16(string, is_null);
365 return true;
368 void ParamTraits<NullableString16>::Log(const param_type& p, std::string* l) {
369 l->append("(");
370 LogParam(p.string(), l);
371 l->append(", ");
372 LogParam(p.is_null(), l);
373 l->append(")");
376 #if !defined(WCHAR_T_IS_UTF16)
377 void ParamTraits<string16>::Log(const param_type& p, std::string* l) {
378 l->append(UTF16ToUTF8(p));
380 #endif
383 void ParamTraits<FilePath>::Write(Message* m, const param_type& p) {
384 ParamTraits<FilePath::StringType>::Write(m, p.value());
387 bool ParamTraits<FilePath>::Read(const Message* m,
388 PickleIterator* iter,
389 param_type* r) {
390 FilePath::StringType value;
391 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
392 return false;
393 *r = FilePath(value);
394 return true;
397 void ParamTraits<FilePath>::Log(const param_type& p, std::string* l) {
398 ParamTraits<FilePath::StringType>::Log(p.value(), l);
401 #if defined(OS_POSIX)
402 void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
403 const bool valid = p.fd >= 0;
404 WriteParam(m, valid);
406 if (valid) {
407 if (!m->WriteFileDescriptor(p))
408 NOTREACHED();
412 bool ParamTraits<base::FileDescriptor>::Read(const Message* m,
413 PickleIterator* iter,
414 param_type* r) {
415 bool valid;
416 if (!ReadParam(m, iter, &valid))
417 return false;
419 if (!valid) {
420 r->fd = -1;
421 r->auto_close = false;
422 return true;
425 return m->ReadFileDescriptor(iter, r);
428 void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
429 std::string* l) {
430 if (p.auto_close) {
431 l->append(StringPrintf("FD(%d auto-close)", p.fd));
432 } else {
433 l->append(StringPrintf("FD(%d)", p.fd));
436 #endif // defined(OS_POSIX)
438 void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
439 #if defined(OS_WIN)
440 // On Windows marshalling pipe handle is not supported.
441 DCHECK(p.pipe.handle == NULL);
442 #endif // defined (OS_WIN)
443 WriteParam(m, p.name);
444 #if defined(OS_POSIX)
445 WriteParam(m, p.socket);
446 #endif
449 bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m,
450 PickleIterator* iter,
451 param_type* r) {
452 return ReadParam(m, iter, &r->name)
453 #if defined(OS_POSIX)
454 && ReadParam(m, iter, &r->socket)
455 #endif
459 void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
460 std::string* l) {
461 l->append(StringPrintf("ChannelHandle(%s", p.name.c_str()));
462 #if defined(OS_POSIX)
463 l->append(", ");
464 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
465 #endif
466 l->append(")");
469 LogData::LogData()
470 : routing_id(0),
471 type(0),
472 sent(0),
473 receive(0),
474 dispatch(0) {
477 LogData::~LogData() {
480 void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
481 WriteParam(m, p.channel);
482 WriteParam(m, p.routing_id);
483 WriteParam(m, p.type);
484 WriteParam(m, p.flags);
485 WriteParam(m, p.sent);
486 WriteParam(m, p.receive);
487 WriteParam(m, p.dispatch);
488 WriteParam(m, p.params);
491 bool ParamTraits<LogData>::Read(const Message* m,
492 PickleIterator* iter,
493 param_type* r) {
494 return
495 ReadParam(m, iter, &r->channel) &&
496 ReadParam(m, iter, &r->routing_id) &&
497 ReadParam(m, iter, &r->type) &&
498 ReadParam(m, iter, &r->flags) &&
499 ReadParam(m, iter, &r->sent) &&
500 ReadParam(m, iter, &r->receive) &&
501 ReadParam(m, iter, &r->dispatch) &&
502 ReadParam(m, iter, &r->params);
505 } // namespace IPC