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