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 "content/public/common/common_param_traits.h"
6
7#include "content/public/common/content_constants.h"
8#include "content/public/common/page_state.h"
9#include "content/public/common/referrer.h"
10#include "content/public/common/url_utils.h"
11#include "net/base/host_port_pair.h"
12#include "third_party/skia/include/core/SkBitmap.h"
13#include "ui/gfx/rect.h"
14#include "ui/gfx/rect_f.h"
15
16namespace {
17
18struct SkBitmap_Data {
19  // The configuration for the bitmap (bits per pixel, etc).
20  SkBitmap::Config fConfig;
21
22  // The width of the bitmap in pixels.
23  uint32 fWidth;
24
25  // The height of the bitmap in pixels.
26  uint32 fHeight;
27
28  void InitSkBitmapDataForTransfer(const SkBitmap& bitmap) {
29    fConfig = bitmap.config();
30    fWidth = bitmap.width();
31    fHeight = bitmap.height();
32  }
33
34  // Returns whether |bitmap| successfully initialized.
35  bool InitSkBitmapFromData(SkBitmap* bitmap, const char* pixels,
36                            size_t total_pixels) const {
37    if (total_pixels) {
38      bitmap->setConfig(fConfig, fWidth, fHeight, 0);
39      if (!bitmap->allocPixels())
40        return false;
41      if (total_pixels != bitmap->getSize())
42        return false;
43      memcpy(bitmap->getPixels(), pixels, total_pixels);
44    }
45    return true;
46  }
47};
48
49}  // namespace
50
51namespace IPC {
52
53void ParamTraits<GURL>::Write(Message* m, const GURL& p) {
54  DCHECK(p.possibly_invalid_spec().length() <= content::GetMaxURLChars());
55
56  // Beware of print-parse inconsistency which would change an invalid
57  // URL into a valid one. Ideally, the message would contain this flag
58  // so that the read side could make the check, but performing it here
59  // avoids changing the on-the-wire representation of such a fundamental
60  // type as GURL. See https://crbug.com/166486 for additional work in
61  // this area.
62  if (!p.is_valid()) {
63    m->WriteString(std::string());
64    return;
65  }
66
67  m->WriteString(p.possibly_invalid_spec());
68  // TODO(brettw) bug 684583: Add encoding for query params.
69}
70
71bool ParamTraits<GURL>::Read(const Message* m, PickleIterator* iter, GURL* p) {
72  std::string s;
73  if (!m->ReadString(iter, &s) || s.length() > content::GetMaxURLChars()) {
74    *p = GURL();
75    return false;
76  }
77  *p = GURL(s);
78  if (!s.empty() && !p->is_valid()) {
79    *p = GURL();
80    return false;
81  }
82  return true;
83}
84
85void ParamTraits<GURL>::Log(const GURL& p, std::string* l) {
86  l->append(p.spec());
87}
88
89void ParamTraits<net::HostPortPair>::Write(Message* m, const param_type& p) {
90  WriteParam(m, p.host());
91  WriteParam(m, p.port());
92}
93
94bool ParamTraits<net::HostPortPair>::Read(const Message* m,
95                                          PickleIterator* iter,
96                                          param_type* r) {
97  std::string host;
98  uint16 port;
99  if (!ReadParam(m, iter, &host) || !ReadParam(m, iter, &port))
100    return false;
101
102  r->set_host(host);
103  r->set_port(port);
104  return true;
105}
106
107void ParamTraits<net::HostPortPair>::Log(const param_type& p, std::string* l) {
108  l->append(p.ToString());
109}
110
111void ParamTraits<content::PageState>::Write(
112    Message* m, const param_type& p) {
113  WriteParam(m, p.ToEncodedData());
114}
115
116bool ParamTraits<content::PageState>::Read(
117    const Message* m, PickleIterator* iter, param_type* r) {
118  std::string data;
119  if (!ReadParam(m, iter, &data))
120    return false;
121  *r = content::PageState::CreateFromEncodedData(data);
122  return true;
123}
124
125void ParamTraits<content::PageState>::Log(
126    const param_type& p, std::string* l) {
127  l->append("(");
128  LogParam(p.ToEncodedData(), l);
129  l->append(")");
130}
131
132void ParamTraits<content::Referrer>::Write(
133    Message* m, const param_type& p) {
134  WriteParam(m, p.url);
135  WriteParam(m, p.policy);
136}
137
138bool ParamTraits<content::Referrer>::Read(
139    const Message* m, PickleIterator* iter, param_type* r) {
140  return ReadParam(m, iter, &r->url) && ReadParam(m, iter, &r->policy);
141}
142
143void ParamTraits<content::Referrer>::Log(
144    const param_type& p, std::string* l) {
145  l->append("(");
146  LogParam(p.url, l);
147  l->append(",");
148  LogParam(p.policy, l);
149  l->append(")");
150}
151
152void ParamTraits<gfx::Point>::Write(Message* m, const gfx::Point& p) {
153  m->WriteInt(p.x());
154  m->WriteInt(p.y());
155}
156
157bool ParamTraits<gfx::Point>::Read(const Message* m, PickleIterator* iter,
158                                   gfx::Point* r) {
159  int x, y;
160  if (!m->ReadInt(iter, &x) ||
161      !m->ReadInt(iter, &y))
162    return false;
163  r->set_x(x);
164  r->set_y(y);
165  return true;
166}
167
168void ParamTraits<gfx::Point>::Log(const gfx::Point& p, std::string* l) {
169  l->append(base::StringPrintf("(%d, %d)", p.x(), p.y()));
170}
171
172void ParamTraits<gfx::PointF>::Write(Message* m, const gfx::PointF& v) {
173  ParamTraits<float>::Write(m, v.x());
174  ParamTraits<float>::Write(m, v.y());
175}
176
177bool ParamTraits<gfx::PointF>::Read(const Message* m,
178                                      PickleIterator* iter,
179                                      gfx::PointF* r) {
180  float x, y;
181  if (!ParamTraits<float>::Read(m, iter, &x) ||
182      !ParamTraits<float>::Read(m, iter, &y))
183    return false;
184  r->set_x(x);
185  r->set_y(y);
186  return true;
187}
188
189void ParamTraits<gfx::PointF>::Log(const gfx::PointF& v, std::string* l) {
190  l->append(base::StringPrintf("(%f, %f)", v.x(), v.y()));
191}
192
193void ParamTraits<gfx::Size>::Write(Message* m, const gfx::Size& p) {
194  DCHECK_GE(p.width(), 0);
195  DCHECK_GE(p.height(), 0);
196  int values[2] = { p.width(), p.height() };
197  m->WriteBytes(&values, sizeof(int) * 2);
198}
199
200bool ParamTraits<gfx::Size>::Read(const Message* m,
201                                  PickleIterator* iter,
202                                  gfx::Size* r) {
203  const char* char_values;
204  if (!m->ReadBytes(iter, &char_values, sizeof(int) * 2))
205    return false;
206  const int* values = reinterpret_cast<const int*>(char_values);
207  if (values[0] < 0 || values[1] < 0)
208    return false;
209  r->set_width(values[0]);
210  r->set_height(values[1]);
211  return true;
212}
213
214void ParamTraits<gfx::Size>::Log(const gfx::Size& p, std::string* l) {
215  l->append(base::StringPrintf("(%d, %d)", p.width(), p.height()));
216}
217
218void ParamTraits<gfx::SizeF>::Write(Message* m, const gfx::SizeF& p) {
219  float values[2] = { p.width(), p.height() };
220  m->WriteBytes(&values, sizeof(float) * 2);
221}
222
223bool ParamTraits<gfx::SizeF>::Read(const Message* m,
224                                   PickleIterator* iter,
225                                   gfx::SizeF* r) {
226  const char* char_values;
227  if (!m->ReadBytes(iter, &char_values, sizeof(float) * 2))
228    return false;
229  const float* values = reinterpret_cast<const float*>(char_values);
230  r->set_width(values[0]);
231  r->set_height(values[1]);
232  return true;
233}
234
235void ParamTraits<gfx::SizeF>::Log(const gfx::SizeF& p, std::string* l) {
236  l->append(base::StringPrintf("(%f, %f)", p.width(), p.height()));
237}
238
239void ParamTraits<gfx::Vector2d>::Write(Message* m, const gfx::Vector2d& p) {
240  int values[2] = { p.x(), p.y() };
241  m->WriteBytes(&values, sizeof(int) * 2);
242}
243
244bool ParamTraits<gfx::Vector2d>::Read(const Message* m,
245                                      PickleIterator* iter,
246                                      gfx::Vector2d* r) {
247  const char* char_values;
248  if (!m->ReadBytes(iter, &char_values, sizeof(int) * 2))
249    return false;
250  const int* values = reinterpret_cast<const int*>(char_values);
251  r->set_x(values[0]);
252  r->set_y(values[1]);
253  return true;
254}
255
256void ParamTraits<gfx::Vector2d>::Log(const gfx::Vector2d& v, std::string* l) {
257  l->append(base::StringPrintf("(%d, %d)", v.x(), v.y()));
258}
259
260void ParamTraits<gfx::Vector2dF>::Write(Message* m, const gfx::Vector2dF& p) {
261  float values[2] = { p.x(), p.y() };
262  m->WriteBytes(&values, sizeof(float) * 2);
263}
264
265bool ParamTraits<gfx::Vector2dF>::Read(const Message* m,
266                                      PickleIterator* iter,
267                                      gfx::Vector2dF* r) {
268  const char* char_values;
269  if (!m->ReadBytes(iter, &char_values, sizeof(float) * 2))
270    return false;
271  const float* values = reinterpret_cast<const float*>(char_values);
272  r->set_x(values[0]);
273  r->set_y(values[1]);
274  return true;
275}
276
277void ParamTraits<gfx::Vector2dF>::Log(const gfx::Vector2dF& v, std::string* l) {
278  l->append(base::StringPrintf("(%f, %f)", v.x(), v.y()));
279}
280
281void ParamTraits<gfx::Rect>::Write(Message* m, const gfx::Rect& p) {
282  int values[4] = { p.x(), p.y(), p.width(), p.height() };
283  m->WriteBytes(&values, sizeof(int) * 4);
284}
285
286bool ParamTraits<gfx::Rect>::Read(const Message* m,
287                                  PickleIterator* iter,
288                                  gfx::Rect* r) {
289  const char* char_values;
290  if (!m->ReadBytes(iter, &char_values, sizeof(int) * 4))
291    return false;
292  const int* values = reinterpret_cast<const int*>(char_values);
293  if (values[2] < 0 || values[3] < 0)
294    return false;
295  r->SetRect(values[0], values[1], values[2], values[3]);
296  return true;
297}
298
299void ParamTraits<gfx::Rect>::Log(const gfx::Rect& p, std::string* l) {
300  l->append(base::StringPrintf("(%d, %d, %d, %d)", p.x(), p.y(),
301                               p.width(), p.height()));
302}
303
304void ParamTraits<gfx::RectF>::Write(Message* m, const gfx::RectF& p) {
305  float values[4] = { p.x(), p.y(), p.width(), p.height() };
306  m->WriteBytes(&values, sizeof(float) * 4);
307}
308
309bool ParamTraits<gfx::RectF>::Read(const Message* m,
310                                   PickleIterator* iter,
311                                   gfx::RectF* r) {
312  const char* char_values;
313  if (!m->ReadBytes(iter, &char_values, sizeof(float) * 4))
314    return false;
315  const float* values = reinterpret_cast<const float*>(char_values);
316  r->SetRect(values[0], values[1], values[2], values[3]);
317  return true;
318}
319
320void ParamTraits<gfx::RectF>::Log(const gfx::RectF& p, std::string* l) {
321  l->append(base::StringPrintf("(%f, %f, %f, %f)", p.x(), p.y(),
322                               p.width(), p.height()));
323}
324
325void ParamTraits<SkBitmap>::Write(Message* m, const SkBitmap& p) {
326  size_t fixed_size = sizeof(SkBitmap_Data);
327  SkBitmap_Data bmp_data;
328  bmp_data.InitSkBitmapDataForTransfer(p);
329  m->WriteData(reinterpret_cast<const char*>(&bmp_data),
330               static_cast<int>(fixed_size));
331  size_t pixel_size = p.getSize();
332  SkAutoLockPixels p_lock(p);
333  m->WriteData(reinterpret_cast<const char*>(p.getPixels()),
334               static_cast<int>(pixel_size));
335}
336
337bool ParamTraits<SkBitmap>::Read(const Message* m,
338                                 PickleIterator* iter,
339                                 SkBitmap* r) {
340  const char* fixed_data;
341  int fixed_data_size = 0;
342  if (!m->ReadData(iter, &fixed_data, &fixed_data_size) ||
343     (fixed_data_size <= 0)) {
344    NOTREACHED();
345    return false;
346  }
347  if (fixed_data_size != sizeof(SkBitmap_Data))
348    return false;  // Message is malformed.
349
350  const char* variable_data;
351  int variable_data_size = 0;
352  if (!m->ReadData(iter, &variable_data, &variable_data_size) ||
353     (variable_data_size < 0)) {
354    NOTREACHED();
355    return false;
356  }
357  const SkBitmap_Data* bmp_data =
358      reinterpret_cast<const SkBitmap_Data*>(fixed_data);
359  return bmp_data->InitSkBitmapFromData(r, variable_data, variable_data_size);
360}
361
362void ParamTraits<SkBitmap>::Log(const SkBitmap& p, std::string* l) {
363  l->append("<SkBitmap>");
364}
365
366}  // namespace IPC
367
368// Generate param traits write methods.
369#include "ipc/param_traits_write_macros.h"
370namespace IPC {
371#undef CONTENT_PUBLIC_COMMON_COMMON_PARAM_TRAITS_MACROS_H_
372#include "content/public/common/common_param_traits_macros.h"
373}  // namespace IPC
374
375// Generate param traits read methods.
376#include "ipc/param_traits_read_macros.h"
377namespace IPC {
378#undef CONTENT_PUBLIC_COMMON_COMMON_PARAM_TRAITS_MACROS_H_
379#include "content/public/common/common_param_traits_macros.h"
380}  // namespace IPC
381
382// Generate param traits log methods.
383#include "ipc/param_traits_log_macros.h"
384namespace IPC {
385#undef CONTENT_PUBLIC_COMMON_COMMON_PARAM_TRAITS_MACROS_H_
386#include "content/public/common/common_param_traits_macros.h"
387}  // namespace IPC
388