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