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