OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006-2008 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 "chrome/common/ipc_message_utils.h" | |
6 | |
7 #include "base/gfx/rect.h" | |
8 #include "base/json_writer.h" | |
9 #include "base/scoped_ptr.h" | |
10 #include "base/values.h" | |
11 #include "googleurl/src/gurl.h" | |
12 #ifndef EXCLUDE_SKIA_DEPENDENCIES | |
13 #include "third_party/skia/include/core/SkBitmap.h" | |
14 #endif | |
15 #include "webkit/glue/dom_operations.h" | |
16 | |
17 namespace IPC { | |
18 | |
19 const int kMaxRecursionDepth = 100; | |
20 | |
21 #ifndef EXCLUDE_SKIA_DEPENDENCIES | |
22 | |
23 namespace { | |
24 | |
25 struct SkBitmap_Data { | |
26 // The configuration for the bitmap (bits per pixel, etc). | |
27 SkBitmap::Config fConfig; | |
28 | |
29 // The width of the bitmap in pixels. | |
30 uint32 fWidth; | |
31 | |
32 // The height of the bitmap in pixels. | |
33 uint32 fHeight; | |
34 | |
35 // The number of bytes between subsequent rows of the bitmap. | |
36 uint32 fRowBytes; | |
37 | |
38 void InitSkBitmapDataForTransfer(const SkBitmap& bitmap) { | |
39 fConfig = bitmap.config(); | |
40 fWidth = bitmap.width(); | |
41 fHeight = bitmap.height(); | |
42 fRowBytes = bitmap.rowBytes(); | |
43 } | |
44 | |
45 // Returns whether |bitmap| successfully initialized. | |
46 bool InitSkBitmapFromData(SkBitmap* bitmap, const char* pixels, | |
47 size_t total_pixels) const { | |
48 if (total_pixels) { | |
49 bitmap->setConfig(fConfig, fWidth, fHeight, fRowBytes); | |
50 if (!bitmap->allocPixels()) | |
51 return false; | |
52 if (total_pixels > bitmap->getSize()) | |
53 return false; | |
54 memcpy(bitmap->getPixels(), pixels, total_pixels); | |
55 } | |
56 return true; | |
57 } | |
58 }; | |
59 | |
60 } // namespace | |
61 | |
62 | |
63 void ParamTraits<SkBitmap>::Write(Message* m, const SkBitmap& p) { | |
64 size_t fixed_size = sizeof(SkBitmap_Data); | |
65 SkBitmap_Data bmp_data; | |
66 bmp_data.InitSkBitmapDataForTransfer(p); | |
67 m->WriteData(reinterpret_cast<const char*>(&bmp_data), | |
68 static_cast<int>(fixed_size)); | |
69 size_t pixel_size = p.getSize(); | |
70 SkAutoLockPixels p_lock(p); | |
71 m->WriteData(reinterpret_cast<const char*>(p.getPixels()), | |
72 static_cast<int>(pixel_size)); | |
73 } | |
74 | |
75 bool ParamTraits<SkBitmap>::Read(const Message* m, void** iter, SkBitmap* r) { | |
76 const char* fixed_data; | |
77 int fixed_data_size = 0; | |
78 if (!m->ReadData(iter, &fixed_data, &fixed_data_size) || | |
79 (fixed_data_size <= 0)) { | |
80 NOTREACHED(); | |
81 return false; | |
82 } | |
83 if (fixed_data_size != sizeof(SkBitmap_Data)) | |
84 return false; // Message is malformed. | |
85 | |
86 const char* variable_data; | |
87 int variable_data_size = 0; | |
88 if (!m->ReadData(iter, &variable_data, &variable_data_size) || | |
89 (variable_data_size < 0)) { | |
90 NOTREACHED(); | |
91 return false; | |
92 } | |
93 const SkBitmap_Data* bmp_data = | |
94 reinterpret_cast<const SkBitmap_Data*>(fixed_data); | |
95 return bmp_data->InitSkBitmapFromData(r, variable_data, variable_data_size); | |
96 } | |
97 | |
98 void ParamTraits<SkBitmap>::Log(const SkBitmap& p, std::wstring* l) { | |
99 l->append(StringPrintf(L"<SkBitmap>")); | |
100 } | |
101 | |
102 #endif // EXCLUDE_SKIA_DEPENDENCIES | |
103 | |
104 void ParamTraits<GURL>::Write(Message* m, const GURL& p) { | |
105 m->WriteString(p.possibly_invalid_spec()); | |
106 // TODO(brettw) bug 684583: Add encoding for query params. | |
107 } | |
108 | |
109 bool ParamTraits<GURL>::Read(const Message* m, void** iter, GURL* p) { | |
110 std::string s; | |
111 if (!m->ReadString(iter, &s)) { | |
112 *p = GURL(); | |
113 return false; | |
114 } | |
115 *p = GURL(s); | |
116 return true; | |
117 } | |
118 | |
119 void ParamTraits<GURL>::Log(const GURL& p, std::wstring* l) { | |
120 l->append(UTF8ToWide(p.spec())); | |
121 } | |
122 | |
123 void ParamTraits<gfx::Point>::Write(Message* m, const gfx::Point& p) { | |
124 m->WriteInt(p.x()); | |
125 m->WriteInt(p.y()); | |
126 } | |
127 | |
128 bool ParamTraits<gfx::Point>::Read(const Message* m, void** iter, | |
129 gfx::Point* r) { | |
130 int x, y; | |
131 if (!m->ReadInt(iter, &x) || | |
132 !m->ReadInt(iter, &y)) | |
133 return false; | |
134 r->set_x(x); | |
135 r->set_y(y); | |
136 return true; | |
137 } | |
138 | |
139 void ParamTraits<gfx::Point>::Log(const gfx::Point& p, std::wstring* l) { | |
140 l->append(StringPrintf(L"(%d, %d)", p.x(), p.y())); | |
141 } | |
142 | |
143 | |
144 void ParamTraits<gfx::Rect>::Write(Message* m, const gfx::Rect& p) { | |
145 m->WriteInt(p.x()); | |
146 m->WriteInt(p.y()); | |
147 m->WriteInt(p.width()); | |
148 m->WriteInt(p.height()); | |
149 } | |
150 | |
151 bool ParamTraits<gfx::Rect>::Read(const Message* m, void** iter, gfx::Rect* r) { | |
152 int x, y, w, h; | |
153 if (!m->ReadInt(iter, &x) || | |
154 !m->ReadInt(iter, &y) || | |
155 !m->ReadInt(iter, &w) || | |
156 !m->ReadInt(iter, &h)) | |
157 return false; | |
158 r->set_x(x); | |
159 r->set_y(y); | |
160 r->set_width(w); | |
161 r->set_height(h); | |
162 return true; | |
163 } | |
164 | |
165 void ParamTraits<gfx::Rect>::Log(const gfx::Rect& p, std::wstring* l) { | |
166 l->append(StringPrintf(L"(%d, %d, %d, %d)", p.x(), p.y(), | |
167 p.width(), p.height())); | |
168 } | |
169 | |
170 | |
171 void ParamTraits<gfx::Size>::Write(Message* m, const gfx::Size& p) { | |
172 m->WriteInt(p.width()); | |
173 m->WriteInt(p.height()); | |
174 } | |
175 | |
176 bool ParamTraits<gfx::Size>::Read(const Message* m, void** iter, gfx::Size* r) { | |
177 int w, h; | |
178 if (!m->ReadInt(iter, &w) || | |
179 !m->ReadInt(iter, &h)) | |
180 return false; | |
181 r->set_width(w); | |
182 r->set_height(h); | |
183 return true; | |
184 } | |
185 | |
186 void ParamTraits<gfx::Size>::Log(const gfx::Size& p, std::wstring* l) { | |
187 l->append(StringPrintf(L"(%d, %d)", p.width(), p.height())); | |
188 } | |
189 | |
190 void ParamTraits<webkit_glue::WebApplicationInfo>::Write( | |
191 Message* m, const webkit_glue::WebApplicationInfo& p) { | |
192 WriteParam(m, p.title); | |
193 WriteParam(m, p.description); | |
194 WriteParam(m, p.app_url); | |
195 WriteParam(m, p.icons.size()); | |
196 for (size_t i = 0; i < p.icons.size(); ++i) { | |
197 WriteParam(m, p.icons[i].url); | |
198 WriteParam(m, p.icons[i].width); | |
199 WriteParam(m, p.icons[i].height); | |
200 } | |
201 } | |
202 | |
203 bool ParamTraits<webkit_glue::WebApplicationInfo>::Read( | |
204 const Message* m, void** iter, webkit_glue::WebApplicationInfo* r) { | |
205 size_t icon_count; | |
206 bool result = | |
207 ReadParam(m, iter, &r->title) && | |
208 ReadParam(m, iter, &r->description) && | |
209 ReadParam(m, iter, &r->app_url) && | |
210 ReadParam(m, iter, &icon_count); | |
211 if (!result) | |
212 return false; | |
213 for (size_t i = 0; i < icon_count && result; ++i) { | |
214 param_type::IconInfo icon_info; | |
215 result = | |
216 ReadParam(m, iter, &icon_info.url) && | |
217 ReadParam(m, iter, &icon_info.width) && | |
218 ReadParam(m, iter, &icon_info.height); | |
219 r->icons.push_back(icon_info); | |
220 } | |
221 return result; | |
222 } | |
223 | |
224 void ParamTraits<webkit_glue::WebApplicationInfo>::Log( | |
225 const webkit_glue::WebApplicationInfo& p, std::wstring* l) { | |
226 l->append(L"<WebApplicationInfo>"); | |
227 } | |
228 | |
229 // Value serialization | |
230 | |
231 static bool ReadValue(const Message* m, void** iter, Value** value, | |
232 int recursion); | |
233 | |
234 static void WriteValue(Message* m, const Value* value, int recursion) { | |
235 if (recursion > kMaxRecursionDepth) { | |
236 LOG(WARNING) << "Max recursion depth hit in WriteValue."; | |
237 return; | |
238 } | |
239 | |
240 m->WriteInt(value->GetType()); | |
241 | |
242 switch (value->GetType()) { | |
243 case Value::TYPE_NULL: | |
244 break; | |
245 case Value::TYPE_BOOLEAN: { | |
246 bool val; | |
247 value->GetAsBoolean(&val); | |
248 WriteParam(m, val); | |
249 break; | |
250 } | |
251 case Value::TYPE_INTEGER: { | |
252 int val; | |
253 value->GetAsInteger(&val); | |
254 WriteParam(m, val); | |
255 break; | |
256 } | |
257 case Value::TYPE_REAL: { | |
258 double val; | |
259 value->GetAsReal(&val); | |
260 WriteParam(m, val); | |
261 break; | |
262 } | |
263 case Value::TYPE_STRING: { | |
264 std::string val; | |
265 value->GetAsString(&val); | |
266 WriteParam(m, val); | |
267 break; | |
268 } | |
269 case Value::TYPE_BINARY: { | |
270 NOTREACHED() << "Don't send BinaryValues over IPC."; | |
271 } | |
272 case Value::TYPE_DICTIONARY: { | |
273 const DictionaryValue* dict = static_cast<const DictionaryValue*>(value); | |
274 | |
275 WriteParam(m, static_cast<int>(dict->GetSize())); | |
276 | |
277 for (DictionaryValue::key_iterator it = dict->begin_keys(); | |
278 it != dict->end_keys(); ++it) { | |
279 Value* subval; | |
280 if (dict->Get(*it, &subval)) { | |
281 WriteParam(m, *it); | |
282 WriteValue(m, subval, recursion + 1); | |
283 } else { | |
284 NOTREACHED() << "DictionaryValue iterators are filthy liars."; | |
285 } | |
286 } | |
287 break; | |
288 } | |
289 case Value::TYPE_LIST: { | |
290 const ListValue* list = static_cast<const ListValue*>(value); | |
291 WriteParam(m, static_cast<int>(list->GetSize())); | |
292 for (size_t i = 0; i < list->GetSize(); ++i) { | |
293 Value* subval; | |
294 if (list->Get(i, &subval)) { | |
295 WriteValue(m, subval, recursion + 1); | |
296 } else { | |
297 NOTREACHED() << "ListValue::GetSize is a filthy liar."; | |
298 } | |
299 } | |
300 break; | |
301 } | |
302 } | |
303 } | |
304 | |
305 // Helper for ReadValue that reads a DictionaryValue into a pre-allocated | |
306 // object. | |
307 static bool ReadDictionaryValue(const Message* m, void** iter, | |
308 DictionaryValue* value, int recursion) { | |
309 int size; | |
310 if (!ReadParam(m, iter, &size)) | |
311 return false; | |
312 | |
313 for (int i = 0; i < size; ++i) { | |
314 std::wstring key; | |
315 Value* subval; | |
316 if (!ReadParam(m, iter, &key) || | |
317 !ReadValue(m, iter, &subval, recursion + 1)) | |
318 return false; | |
319 value->Set(key, subval); | |
320 } | |
321 | |
322 return true; | |
323 } | |
324 | |
325 // Helper for ReadValue that reads a ReadListValue into a pre-allocated | |
326 // object. | |
327 static bool ReadListValue(const Message* m, void** iter, | |
328 ListValue* value, int recursion) { | |
329 int size; | |
330 if (!ReadParam(m, iter, &size)) | |
331 return false; | |
332 | |
333 for (int i = 0; i < size; ++i) { | |
334 Value* subval; | |
335 if (!ReadValue(m, iter, &subval, recursion + 1)) | |
336 return false; | |
337 value->Set(i, subval); | |
338 } | |
339 | |
340 return true; | |
341 } | |
342 | |
343 static bool ReadValue(const Message* m, void** iter, Value** value, | |
344 int recursion) { | |
345 if (recursion > kMaxRecursionDepth) { | |
346 LOG(WARNING) << "Max recursion depth hit in ReadValue."; | |
347 return false; | |
348 } | |
349 | |
350 int type; | |
351 if (!ReadParam(m, iter, &type)) | |
352 return false; | |
353 | |
354 switch (type) { | |
355 case Value::TYPE_NULL: | |
356 *value = Value::CreateNullValue(); | |
357 break; | |
358 case Value::TYPE_BOOLEAN: { | |
359 bool val; | |
360 if (!ReadParam(m, iter, &val)) | |
361 return false; | |
362 *value = Value::CreateBooleanValue(val); | |
363 break; | |
364 } | |
365 case Value::TYPE_INTEGER: { | |
366 int val; | |
367 if (!ReadParam(m, iter, &val)) | |
368 return false; | |
369 *value = Value::CreateIntegerValue(val); | |
370 break; | |
371 } | |
372 case Value::TYPE_REAL: { | |
373 double val; | |
374 if (!ReadParam(m, iter, &val)) | |
375 return false; | |
376 *value = Value::CreateRealValue(val); | |
377 break; | |
378 } | |
379 case Value::TYPE_STRING: { | |
380 std::string val; | |
381 if (!ReadParam(m, iter, &val)) | |
382 return false; | |
383 *value = Value::CreateStringValue(val); | |
384 break; | |
385 } | |
386 case Value::TYPE_BINARY: { | |
387 NOTREACHED() << "Don't send BinaryValues over IPC."; | |
388 break; | |
389 } | |
390 case Value::TYPE_DICTIONARY: { | |
391 scoped_ptr<DictionaryValue> val(new DictionaryValue()); | |
392 if (!ReadDictionaryValue(m, iter, val.get(), recursion)) | |
393 return false; | |
394 *value = val.release(); | |
395 break; | |
396 } | |
397 case Value::TYPE_LIST: { | |
398 scoped_ptr<ListValue> val(new ListValue()); | |
399 if (!ReadListValue(m, iter, val.get(), recursion)) | |
400 return false; | |
401 *value = val.release(); | |
402 break; | |
403 } | |
404 default: | |
405 return false; | |
406 } | |
407 | |
408 return true; | |
409 } | |
410 | |
411 void ParamTraits<DictionaryValue>::Write(Message* m, const param_type& p) { | |
412 WriteValue(m, &p, 0); | |
413 } | |
414 | |
415 bool ParamTraits<DictionaryValue>::Read( | |
416 const Message* m, void** iter, param_type* r) { | |
417 int type; | |
418 if (!ReadParam(m, iter, &type) || type != Value::TYPE_DICTIONARY) | |
419 return false; | |
420 | |
421 return ReadDictionaryValue(m, iter, r, 0); | |
422 } | |
423 | |
424 void ParamTraits<DictionaryValue>::Log(const param_type& p, std::wstring* l) { | |
425 std::string json; | |
426 JSONWriter::Write(&p, false, &json); | |
427 l->append(UTF8ToWide(json)); | |
428 } | |
429 | |
430 void ParamTraits<ListValue>::Write(Message* m, const param_type& p) { | |
431 WriteValue(m, &p, 0); | |
432 } | |
433 | |
434 bool ParamTraits<ListValue>::Read( | |
435 const Message* m, void** iter, param_type* r) { | |
436 int type; | |
437 if (!ReadParam(m, iter, &type) || type != Value::TYPE_LIST) | |
438 return false; | |
439 | |
440 return ReadListValue(m, iter, r, 0); | |
441 } | |
442 | |
443 void ParamTraits<ListValue>::Log(const param_type& p, std::wstring* l) { | |
444 std::string json; | |
445 JSONWriter::Write(&p, false, &json); | |
446 l->append(UTF8ToWide(json)); | |
447 } | |
448 } // namespace IPC | |
OLD | NEW |