Multi-tab: Renaming TabStripModelObserver::TabDeselected to TabDeactivated
[chromium-blink-merge.git] / ipc / ipc_message_utils.cc
blob9492a1110781f68bfc04c173108825993c3cfd79
1 // Copyright (c) 2011 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, void** 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 BinaryValue* binary = static_cast<const BinaryValue*>(value);
66 m->WriteData(binary->GetBuffer(), static_cast<int>(binary->GetSize()));
67 break;
69 case Value::TYPE_DICTIONARY: {
70 const DictionaryValue* dict = static_cast<const DictionaryValue*>(value);
72 WriteParam(m, static_cast<int>(dict->size()));
74 for (DictionaryValue::key_iterator it = dict->begin_keys();
75 it != dict->end_keys(); ++it) {
76 Value* subval;
77 if (dict->GetWithoutPathExpansion(*it, &subval)) {
78 WriteParam(m, *it);
79 WriteValue(m, subval, recursion + 1);
80 } else {
81 NOTREACHED() << "DictionaryValue iterators are filthy liars.";
84 break;
86 case Value::TYPE_LIST: {
87 const ListValue* list = static_cast<const ListValue*>(value);
88 WriteParam(m, static_cast<int>(list->GetSize()));
89 for (size_t i = 0; i < list->GetSize(); ++i) {
90 Value* subval;
91 if (list->Get(i, &subval)) {
92 WriteValue(m, subval, recursion + 1);
93 } else {
94 NOTREACHED() << "ListValue::GetSize is a filthy liar.";
97 break;
102 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated
103 // object.
104 static bool ReadDictionaryValue(const Message* m, void** iter,
105 DictionaryValue* value, int recursion) {
106 int size;
107 if (!ReadParam(m, iter, &size))
108 return false;
110 for (int i = 0; i < size; ++i) {
111 std::string key;
112 Value* subval;
113 if (!ReadParam(m, iter, &key) ||
114 !ReadValue(m, iter, &subval, recursion + 1))
115 return false;
116 value->Set(key, subval);
119 return true;
122 // Helper for ReadValue that reads a ReadListValue into a pre-allocated
123 // object.
124 static bool ReadListValue(const Message* m, void** iter,
125 ListValue* value, int recursion) {
126 int size;
127 if (!ReadParam(m, iter, &size))
128 return false;
130 for (int i = 0; i < size; ++i) {
131 Value* subval;
132 if (!ReadValue(m, iter, &subval, recursion + 1))
133 return false;
134 value->Set(i, subval);
137 return true;
140 static bool ReadValue(const Message* m, void** iter, Value** value,
141 int recursion) {
142 if (recursion > kMaxRecursionDepth) {
143 LOG(WARNING) << "Max recursion depth hit in ReadValue.";
144 return false;
147 int type;
148 if (!ReadParam(m, iter, &type))
149 return false;
151 switch (type) {
152 case Value::TYPE_NULL:
153 *value = Value::CreateNullValue();
154 break;
155 case Value::TYPE_BOOLEAN: {
156 bool val;
157 if (!ReadParam(m, iter, &val))
158 return false;
159 *value = Value::CreateBooleanValue(val);
160 break;
162 case Value::TYPE_INTEGER: {
163 int val;
164 if (!ReadParam(m, iter, &val))
165 return false;
166 *value = Value::CreateIntegerValue(val);
167 break;
169 case Value::TYPE_DOUBLE: {
170 double val;
171 if (!ReadParam(m, iter, &val))
172 return false;
173 *value = Value::CreateDoubleValue(val);
174 break;
176 case Value::TYPE_STRING: {
177 std::string val;
178 if (!ReadParam(m, iter, &val))
179 return false;
180 *value = Value::CreateStringValue(val);
181 break;
183 case Value::TYPE_BINARY: {
184 const char* data;
185 int length;
186 if (!m->ReadData(iter, &data, &length))
187 return false;
188 *value = BinaryValue::CreateWithCopiedBuffer(data, length);
189 break;
191 case Value::TYPE_DICTIONARY: {
192 scoped_ptr<DictionaryValue> val(new DictionaryValue());
193 if (!ReadDictionaryValue(m, iter, val.get(), recursion))
194 return false;
195 *value = val.release();
196 break;
198 case Value::TYPE_LIST: {
199 scoped_ptr<ListValue> val(new ListValue());
200 if (!ReadListValue(m, iter, val.get(), recursion))
201 return false;
202 *value = val.release();
203 break;
205 default:
206 return false;
209 return true;
212 void ParamTraits<int>::Log(const param_type& p, std::string* l) {
213 l->append(base::IntToString(p));
216 void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) {
217 l->append(base::UintToString(p));
220 void ParamTraits<long>::Log(const param_type& p, std::string* l) {
221 l->append(base::Int64ToString(static_cast<int64>(p)));
224 void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) {
225 l->append(base::Uint64ToString(static_cast<uint64>(p)));
228 void ParamTraits<long long>::Log(const param_type& p, std::string* l) {
229 l->append(base::Int64ToString(static_cast<int64>(p)));
232 void ParamTraits<unsigned long long>::Log(const param_type& p, std::string* l) {
233 l->append(base::Uint64ToString(p));
236 void ParamTraits<unsigned short>::Write(Message* m, const param_type& p) {
237 m->WriteBytes(&p, sizeof(param_type));
240 bool ParamTraits<unsigned short>::Read(const Message* m, void** iter,
241 param_type* r) {
242 const char* data;
243 if (!m->ReadBytes(iter, &data, sizeof(param_type)))
244 return false;
245 memcpy(r, data, sizeof(param_type));
246 return true;
249 void ParamTraits<unsigned short>::Log(const param_type& p, std::string* l) {
250 l->append(base::UintToString(p));
253 void ParamTraits<base::Time>::Write(Message* m, const param_type& p) {
254 ParamTraits<int64>::Write(m, p.ToInternalValue());
257 bool ParamTraits<base::Time>::Read(const Message* m, void** iter,
258 param_type* r) {
259 int64 value;
260 if (!ParamTraits<int64>::Read(m, iter, &value))
261 return false;
262 *r = base::Time::FromInternalValue(value);
263 return true;
266 void ParamTraits<base::Time>::Log(const param_type& p, std::string* l) {
267 ParamTraits<int64>::Log(p.ToInternalValue(), l);
270 void ParamTraits<base::TimeDelta> ::Write(Message* m, const param_type& p) {
271 ParamTraits<int64> ::Write(m, p.InMicroseconds());
274 bool ParamTraits<base::TimeDelta> ::Read(const Message* m,
275 void** iter,
276 param_type* r) {
277 int64 value;
278 bool ret = ParamTraits<int64> ::Read(m, iter, &value);
279 if (ret)
280 *r = base::TimeDelta::FromMicroseconds(value);
282 return ret;
285 void ParamTraits<base::TimeDelta> ::Log(const param_type& p, std::string* l) {
286 ParamTraits<int64> ::Log(p.InMicroseconds(), l);
289 void ParamTraits<DictionaryValue>::Write(Message* m, const param_type& p) {
290 WriteValue(m, &p, 0);
293 bool ParamTraits<DictionaryValue>::Read(
294 const Message* m, void** iter, param_type* r) {
295 int type;
296 if (!ReadParam(m, iter, &type) || type != Value::TYPE_DICTIONARY)
297 return false;
299 return ReadDictionaryValue(m, iter, r, 0);
302 void ParamTraits<DictionaryValue>::Log(const param_type& p, std::string* l) {
303 std::string json;
304 base::JSONWriter::Write(&p, false, &json);
305 l->append(json);
308 void ParamTraits<ListValue>::Write(Message* m, const param_type& p) {
309 WriteValue(m, &p, 0);
312 bool ParamTraits<ListValue>::Read(
313 const Message* m, void** iter, param_type* r) {
314 int type;
315 if (!ReadParam(m, iter, &type) || type != Value::TYPE_LIST)
316 return false;
318 return ReadListValue(m, iter, r, 0);
321 void ParamTraits<ListValue>::Log(const param_type& p, std::string* l) {
322 std::string json;
323 base::JSONWriter::Write(&p, false, &json);
324 l->append(json);
327 void ParamTraits<std::wstring>::Log(const param_type& p, std::string* l) {
328 l->append(WideToUTF8(p));
331 void ParamTraits<NullableString16>::Write(Message* m, const param_type& p) {
332 WriteParam(m, p.string());
333 WriteParam(m, p.is_null());
336 bool ParamTraits<NullableString16>::Read(const Message* m, void** iter,
337 param_type* r) {
338 string16 string;
339 if (!ReadParam(m, iter, &string))
340 return false;
341 bool is_null;
342 if (!ReadParam(m, iter, &is_null))
343 return false;
344 *r = NullableString16(string, is_null);
345 return true;
348 void ParamTraits<NullableString16>::Log(const param_type& p, std::string* l) {
349 l->append("(");
350 LogParam(p.string(), l);
351 l->append(", ");
352 LogParam(p.is_null(), l);
353 l->append(")");
356 #if !defined(WCHAR_T_IS_UTF16)
357 void ParamTraits<string16>::Log(const param_type& p, std::string* l) {
358 l->append(UTF16ToUTF8(p));
360 #endif
363 void ParamTraits<FilePath>::Write(Message* m, const param_type& p) {
364 ParamTraits<FilePath::StringType>::Write(m, p.value());
367 bool ParamTraits<FilePath>::Read(const Message* m, void** iter, param_type* r) {
368 FilePath::StringType value;
369 if (!ParamTraits<FilePath::StringType>::Read(m, iter, &value))
370 return false;
371 *r = FilePath(value);
372 return true;
375 void ParamTraits<FilePath>::Log(const param_type& p, std::string* l) {
376 ParamTraits<FilePath::StringType>::Log(p.value(), l);
379 #if defined(OS_POSIX)
380 void ParamTraits<base::FileDescriptor>::Write(Message* m, const param_type& p) {
381 const bool valid = p.fd >= 0;
382 WriteParam(m, valid);
384 if (valid) {
385 if (!m->WriteFileDescriptor(p))
386 NOTREACHED();
390 bool ParamTraits<base::FileDescriptor>::Read(const Message* m, void** iter,
391 param_type* r) {
392 bool valid;
393 if (!ReadParam(m, iter, &valid))
394 return false;
396 if (!valid) {
397 r->fd = -1;
398 r->auto_close = false;
399 return true;
402 return m->ReadFileDescriptor(iter, r);
405 void ParamTraits<base::FileDescriptor>::Log(const param_type& p,
406 std::string* l) {
407 if (p.auto_close) {
408 l->append(StringPrintf("FD(%d auto-close)", p.fd));
409 } else {
410 l->append(StringPrintf("FD(%d)", p.fd));
413 #endif // defined(OS_POSIX)
415 void ParamTraits<IPC::ChannelHandle>::Write(Message* m, const param_type& p) {
416 WriteParam(m, p.name);
417 #if defined(OS_POSIX)
418 WriteParam(m, p.socket);
419 #endif
422 bool ParamTraits<IPC::ChannelHandle>::Read(const Message* m, void** iter,
423 param_type* r) {
424 return ReadParam(m, iter, &r->name)
425 #if defined(OS_POSIX)
426 && ReadParam(m, iter, &r->socket)
427 #endif
431 void ParamTraits<IPC::ChannelHandle>::Log(const param_type& p,
432 std::string* l) {
433 l->append(StringPrintf("ChannelHandle(%s", p.name.c_str()));
434 #if defined(OS_POSIX)
435 ParamTraits<base::FileDescriptor>::Log(p.socket, l);
436 #endif
437 l->append(")");
440 LogData::LogData()
441 : routing_id(0),
442 type(0),
443 sent(0),
444 receive(0),
445 dispatch(0) {
448 LogData::~LogData() {
451 void ParamTraits<LogData>::Write(Message* m, const param_type& p) {
452 WriteParam(m, p.channel);
453 WriteParam(m, p.routing_id);
454 WriteParam(m, static_cast<int>(p.type));
455 WriteParam(m, p.flags);
456 WriteParam(m, p.sent);
457 WriteParam(m, p.receive);
458 WriteParam(m, p.dispatch);
459 WriteParam(m, p.params);
462 bool ParamTraits<LogData>::Read(const Message* m, void** iter, param_type* r) {
463 int type = -1;
464 bool result =
465 ReadParam(m, iter, &r->channel) &&
466 ReadParam(m, iter, &r->routing_id) &&
467 ReadParam(m, iter, &type) &&
468 ReadParam(m, iter, &r->flags) &&
469 ReadParam(m, iter, &r->sent) &&
470 ReadParam(m, iter, &r->receive) &&
471 ReadParam(m, iter, &r->dispatch) &&
472 ReadParam(m, iter, &r->params);
473 r->type = static_cast<uint16>(type);
474 return result;
477 } // namespace IPC