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 "ppapi/proxy/ppapi_param_traits.h" 6 7#include <string.h> // For memcpy 8 9#include "ppapi/c/pp_resource.h" 10#include "ppapi/proxy/ppapi_messages.h" 11#include "ppapi/proxy/serialized_var.h" 12#include "ppapi/proxy/serialized_flash_menu.h" 13#include "ppapi/shared_impl/host_resource.h" 14#include "ppapi/shared_impl/private/ppb_x509_certificate_private_shared.h" 15 16namespace IPC { 17 18namespace { 19 20// Deserializes a vector from IPC. This special version must be used instead 21// of the default IPC version when the vector contains a SerializedVar, either 22// directly or indirectly (i.e. a vector of objects that have a SerializedVar 23// inside them). 24// 25// The default vector deserializer does resize and then we deserialize into 26// those allocated slots. However, the implementation of vector (at least in 27// GCC's implementation), creates a new empty object using the default 28// constructor, and then sets the rest of the items to that empty one using the 29// copy constructor. 30// 31// Since we allocate the inner class when you call the default constructor and 32// transfer the inner class when you do operator=, the entire vector will end 33// up referring to the same inner class. Deserializing into this will just end 34// up overwriting the same item over and over, since all the SerializedVars 35// will refer to the same thing. 36// 37// The solution is to make a new object for each deserialized item, and then 38// add it to the vector one at a time. 39template<typename T> 40bool ReadVectorWithoutCopy(const Message* m, 41 PickleIterator* iter, 42 std::vector<T>* output) { 43 // This part is just a copy of the the default ParamTraits vector Read(). 44 int size; 45 // ReadLength() checks for < 0 itself. 46 if (!m->ReadLength(iter, &size)) 47 return false; 48 // Resizing beforehand is not safe, see BUG 1006367 for details. 49 if (INT_MAX / sizeof(T) <= static_cast<size_t>(size)) 50 return false; 51 52 output->reserve(size); 53 for (int i = 0; i < size; i++) { 54 T cur; 55 if (!ReadParam(m, iter, &cur)) 56 return false; 57 output->push_back(cur); 58 } 59 return true; 60} 61 62// This serializes the vector of items to the IPC message in exactly the same 63// way as the "regular" IPC vector serializer does. But having the code here 64// saves us from having to copy this code into all ParamTraits that use the 65// ReadVectorWithoutCopy function for deserializing. 66template<typename T> 67void WriteVectorWithoutCopy(Message* m, const std::vector<T>& p) { 68 WriteParam(m, static_cast<int>(p.size())); 69 for (size_t i = 0; i < p.size(); i++) 70 WriteParam(m, p[i]); 71} 72 73} // namespace 74 75// PP_Bool --------------------------------------------------------------------- 76 77// static 78void ParamTraits<PP_Bool>::Write(Message* m, const param_type& p) { 79 ParamTraits<bool>::Write(m, PP_ToBool(p)); 80} 81 82// static 83bool ParamTraits<PP_Bool>::Read(const Message* m, 84 PickleIterator* iter, 85 param_type* r) { 86 // We specifically want to be strict here about what types of input we accept, 87 // which ParamTraits<bool> does for us. We don't want to deserialize "2" into 88 // a PP_Bool, for example. 89 bool result = false; 90 if (!ParamTraits<bool>::Read(m, iter, &result)) 91 return false; 92 *r = PP_FromBool(result); 93 return true; 94} 95 96// static 97void ParamTraits<PP_Bool>::Log(const param_type& p, std::string* l) { 98} 99 100// PP_NetAddress_Private ------------------------------------------------------- 101 102// static 103void ParamTraits<PP_NetAddress_Private>::Write(Message* m, 104 const param_type& p) { 105 WriteParam(m, p.size); 106 m->WriteBytes(p.data, static_cast<int>(p.size)); 107} 108 109// static 110bool ParamTraits<PP_NetAddress_Private>::Read(const Message* m, 111 PickleIterator* iter, 112 param_type* p) { 113 uint16 size; 114 if (!ReadParam(m, iter, &size)) 115 return false; 116 if (size > sizeof(p->data)) 117 return false; 118 p->size = size; 119 120 const char* data; 121 if (!m->ReadBytes(iter, &data, size)) 122 return false; 123 memcpy(p->data, data, size); 124 return true; 125} 126 127// static 128void ParamTraits<PP_NetAddress_Private>::Log(const param_type& p, 129 std::string* l) { 130 l->append("<PP_NetAddress_Private ("); 131 LogParam(p.size, l); 132 l->append(" bytes)>"); 133} 134 135// HostResource ---------------------------------------------------------------- 136 137// static 138void ParamTraits<ppapi::HostResource>::Write(Message* m, 139 const param_type& p) { 140 ParamTraits<PP_Instance>::Write(m, p.instance()); 141 ParamTraits<PP_Resource>::Write(m, p.host_resource()); 142} 143 144// static 145bool ParamTraits<ppapi::HostResource>::Read(const Message* m, 146 PickleIterator* iter, 147 param_type* r) { 148 PP_Instance instance; 149 PP_Resource resource; 150 if (!ParamTraits<PP_Instance>::Read(m, iter, &instance) || 151 !ParamTraits<PP_Resource>::Read(m, iter, &resource)) 152 return false; 153 r->SetHostResource(instance, resource); 154 return true; 155} 156 157// static 158void ParamTraits<ppapi::HostResource>::Log(const param_type& p, 159 std::string* l) { 160} 161 162// SerializedVar --------------------------------------------------------------- 163 164// static 165void ParamTraits<ppapi::proxy::SerializedVar>::Write(Message* m, 166 const param_type& p) { 167 p.WriteToMessage(m); 168} 169 170// static 171bool ParamTraits<ppapi::proxy::SerializedVar>::Read(const Message* m, 172 PickleIterator* iter, 173 param_type* r) { 174 return r->ReadFromMessage(m, iter); 175} 176 177// static 178void ParamTraits<ppapi::proxy::SerializedVar>::Log(const param_type& p, 179 std::string* l) { 180} 181 182// std::vector<SerializedVar> -------------------------------------------------- 183 184void ParamTraits< std::vector<ppapi::proxy::SerializedVar> >::Write( 185 Message* m, 186 const param_type& p) { 187 WriteVectorWithoutCopy(m, p); 188} 189 190// static 191bool ParamTraits< std::vector<ppapi::proxy::SerializedVar> >::Read( 192 const Message* m, 193 PickleIterator* iter, 194 param_type* r) { 195 return ReadVectorWithoutCopy(m, iter, r); 196} 197 198// static 199void ParamTraits< std::vector<ppapi::proxy::SerializedVar> >::Log( 200 const param_type& p, 201 std::string* l) { 202} 203 204// ppapi::PpapiPermissions ----------------------------------------------------- 205 206void ParamTraits<ppapi::PpapiPermissions>::Write(Message* m, 207 const param_type& p) { 208 ParamTraits<uint32_t>::Write(m, p.GetBits()); 209} 210 211// static 212bool ParamTraits<ppapi::PpapiPermissions>::Read(const Message* m, 213 PickleIterator* iter, 214 param_type* r) { 215 uint32_t bits; 216 if (!ParamTraits<uint32_t>::Read(m, iter, &bits)) 217 return false; 218 *r = ppapi::PpapiPermissions(bits); 219 return true; 220} 221 222// static 223void ParamTraits<ppapi::PpapiPermissions>::Log(const param_type& p, 224 std::string* l) { 225} 226 227// SerializedHandle ------------------------------------------------------------ 228 229// static 230void ParamTraits<ppapi::proxy::SerializedHandle>::Write(Message* m, 231 const param_type& p) { 232 ppapi::proxy::SerializedHandle::WriteHeader(p.header(), m); 233 switch (p.type()) { 234 case ppapi::proxy::SerializedHandle::SHARED_MEMORY: 235 ParamTraits<base::SharedMemoryHandle>::Write(m, p.shmem()); 236 break; 237 case ppapi::proxy::SerializedHandle::SOCKET: 238 case ppapi::proxy::SerializedHandle::FILE: 239 ParamTraits<IPC::PlatformFileForTransit>::Write(m, p.descriptor()); 240 break; 241 case ppapi::proxy::SerializedHandle::INVALID: 242 break; 243 // No default so the compiler will warn on new types. 244 } 245} 246 247// static 248bool ParamTraits<ppapi::proxy::SerializedHandle>::Read(const Message* m, 249 PickleIterator* iter, 250 param_type* r) { 251 ppapi::proxy::SerializedHandle::Header header; 252 if (!ppapi::proxy::SerializedHandle::ReadHeader(iter, &header)) 253 return false; 254 switch (header.type) { 255 case ppapi::proxy::SerializedHandle::SHARED_MEMORY: { 256 base::SharedMemoryHandle handle; 257 if (ParamTraits<base::SharedMemoryHandle>::Read(m, iter, &handle)) { 258 r->set_shmem(handle, header.size); 259 return true; 260 } 261 break; 262 } 263 case ppapi::proxy::SerializedHandle::SOCKET: { 264 IPC::PlatformFileForTransit socket; 265 if (ParamTraits<IPC::PlatformFileForTransit>::Read(m, iter, &socket)) { 266 r->set_socket(socket); 267 return true; 268 } 269 break; 270 } 271 case ppapi::proxy::SerializedHandle::FILE: { 272 IPC::PlatformFileForTransit desc; 273 if (ParamTraits<IPC::PlatformFileForTransit>::Read(m, iter, &desc)) { 274 r->set_file_handle(desc, header.open_flags, header.file_io); 275 return true; 276 } 277 break; 278 } 279 case ppapi::proxy::SerializedHandle::INVALID: 280 return true; 281 // No default so the compiler will warn us if a new type is added. 282 } 283 return false; 284} 285 286// static 287void ParamTraits<ppapi::proxy::SerializedHandle>::Log(const param_type& p, 288 std::string* l) { 289} 290 291// PPBURLLoader_UpdateProgress_Params ------------------------------------------ 292 293// static 294void ParamTraits<ppapi::proxy::PPBURLLoader_UpdateProgress_Params>::Write( 295 Message* m, 296 const param_type& p) { 297 ParamTraits<PP_Instance>::Write(m, p.instance); 298 ParamTraits<ppapi::HostResource>::Write(m, p.resource); 299 ParamTraits<int64_t>::Write(m, p.bytes_sent); 300 ParamTraits<int64_t>::Write(m, p.total_bytes_to_be_sent); 301 ParamTraits<int64_t>::Write(m, p.bytes_received); 302 ParamTraits<int64_t>::Write(m, p.total_bytes_to_be_received); 303} 304 305// static 306bool ParamTraits<ppapi::proxy::PPBURLLoader_UpdateProgress_Params>::Read( 307 const Message* m, 308 PickleIterator* iter, 309 param_type* r) { 310 return 311 ParamTraits<PP_Instance>::Read(m, iter, &r->instance) && 312 ParamTraits<ppapi::HostResource>::Read(m, iter, &r->resource) && 313 ParamTraits<int64_t>::Read(m, iter, &r->bytes_sent) && 314 ParamTraits<int64_t>::Read(m, iter, &r->total_bytes_to_be_sent) && 315 ParamTraits<int64_t>::Read(m, iter, &r->bytes_received) && 316 ParamTraits<int64_t>::Read(m, iter, &r->total_bytes_to_be_received); 317} 318 319// static 320void ParamTraits<ppapi::proxy::PPBURLLoader_UpdateProgress_Params>::Log( 321 const param_type& p, 322 std::string* l) { 323} 324 325#if !defined(OS_NACL) && !defined(NACL_WIN64) 326// PPBFlash_DrawGlyphs_Params -------------------------------------------------- 327// static 328void ParamTraits<ppapi::proxy::PPBFlash_DrawGlyphs_Params>::Write( 329 Message* m, 330 const param_type& p) { 331 ParamTraits<PP_Instance>::Write(m, p.instance); 332 ParamTraits<ppapi::HostResource>::Write(m, p.image_data); 333 ParamTraits<ppapi::proxy::SerializedFontDescription>::Write(m, p.font_desc); 334 ParamTraits<uint32_t>::Write(m, p.color); 335 ParamTraits<PP_Point>::Write(m, p.position); 336 ParamTraits<PP_Rect>::Write(m, p.clip); 337 ParamTraits<float>::Write(m, p.transformation[0][0]); 338 ParamTraits<float>::Write(m, p.transformation[0][1]); 339 ParamTraits<float>::Write(m, p.transformation[0][2]); 340 ParamTraits<float>::Write(m, p.transformation[1][0]); 341 ParamTraits<float>::Write(m, p.transformation[1][1]); 342 ParamTraits<float>::Write(m, p.transformation[1][2]); 343 ParamTraits<float>::Write(m, p.transformation[2][0]); 344 ParamTraits<float>::Write(m, p.transformation[2][1]); 345 ParamTraits<float>::Write(m, p.transformation[2][2]); 346 ParamTraits<PP_Bool>::Write(m, p.allow_subpixel_aa); 347 ParamTraits<std::vector<uint16_t> >::Write(m, p.glyph_indices); 348 ParamTraits<std::vector<PP_Point> >::Write(m, p.glyph_advances); 349} 350 351// static 352bool ParamTraits<ppapi::proxy::PPBFlash_DrawGlyphs_Params>::Read( 353 const Message* m, 354 PickleIterator* iter, 355 param_type* r) { 356 return 357 ParamTraits<PP_Instance>::Read(m, iter, &r->instance) && 358 ParamTraits<ppapi::HostResource>::Read(m, iter, &r->image_data) && 359 ParamTraits<ppapi::proxy::SerializedFontDescription>::Read(m, iter, 360 &r->font_desc) && 361 ParamTraits<uint32_t>::Read(m, iter, &r->color) && 362 ParamTraits<PP_Point>::Read(m, iter, &r->position) && 363 ParamTraits<PP_Rect>::Read(m, iter, &r->clip) && 364 ParamTraits<float>::Read(m, iter, &r->transformation[0][0]) && 365 ParamTraits<float>::Read(m, iter, &r->transformation[0][1]) && 366 ParamTraits<float>::Read(m, iter, &r->transformation[0][2]) && 367 ParamTraits<float>::Read(m, iter, &r->transformation[1][0]) && 368 ParamTraits<float>::Read(m, iter, &r->transformation[1][1]) && 369 ParamTraits<float>::Read(m, iter, &r->transformation[1][2]) && 370 ParamTraits<float>::Read(m, iter, &r->transformation[2][0]) && 371 ParamTraits<float>::Read(m, iter, &r->transformation[2][1]) && 372 ParamTraits<float>::Read(m, iter, &r->transformation[2][2]) && 373 ParamTraits<PP_Bool>::Read(m, iter, &r->allow_subpixel_aa) && 374 ParamTraits<std::vector<uint16_t> >::Read(m, iter, &r->glyph_indices) && 375 ParamTraits<std::vector<PP_Point> >::Read(m, iter, &r->glyph_advances) && 376 r->glyph_indices.size() == r->glyph_advances.size(); 377} 378 379// static 380void ParamTraits<ppapi::proxy::PPBFlash_DrawGlyphs_Params>::Log( 381 const param_type& p, 382 std::string* l) { 383} 384 385// SerializedDirEntry ---------------------------------------------------------- 386 387// static 388void ParamTraits<ppapi::proxy::SerializedDirEntry>::Write(Message* m, 389 const param_type& p) { 390 ParamTraits<std::string>::Write(m, p.name); 391 ParamTraits<bool>::Write(m, p.is_dir); 392} 393 394// static 395bool ParamTraits<ppapi::proxy::SerializedDirEntry>::Read(const Message* m, 396 PickleIterator* iter, 397 param_type* r) { 398 return ParamTraits<std::string>::Read(m, iter, &r->name) && 399 ParamTraits<bool>::Read(m, iter, &r->is_dir); 400} 401 402// static 403void ParamTraits<ppapi::proxy::SerializedDirEntry>::Log(const param_type& p, 404 std::string* l) { 405} 406 407// ppapi::proxy::SerializedFontDescription ------------------------------------- 408 409// static 410void ParamTraits<ppapi::proxy::SerializedFontDescription>::Write( 411 Message* m, 412 const param_type& p) { 413 ParamTraits<std::string>::Write(m, p.face); 414 ParamTraits<int32_t>::Write(m, p.family); 415 ParamTraits<uint32_t>::Write(m, p.size); 416 ParamTraits<int32_t>::Write(m, p.weight); 417 ParamTraits<PP_Bool>::Write(m, p.italic); 418 ParamTraits<PP_Bool>::Write(m, p.small_caps); 419 ParamTraits<int32_t>::Write(m, p.letter_spacing); 420 ParamTraits<int32_t>::Write(m, p.word_spacing); 421} 422 423// static 424bool ParamTraits<ppapi::proxy::SerializedFontDescription>::Read( 425 const Message* m, 426 PickleIterator* iter, 427 param_type* r) { 428 return 429 ParamTraits<std::string>::Read(m, iter, &r->face) && 430 ParamTraits<int32_t>::Read(m, iter, &r->family) && 431 ParamTraits<uint32_t>::Read(m, iter, &r->size) && 432 ParamTraits<int32_t>::Read(m, iter, &r->weight) && 433 ParamTraits<PP_Bool>::Read(m, iter, &r->italic) && 434 ParamTraits<PP_Bool>::Read(m, iter, &r->small_caps) && 435 ParamTraits<int32_t>::Read(m, iter, &r->letter_spacing) && 436 ParamTraits<int32_t>::Read(m, iter, &r->word_spacing); 437} 438 439// static 440void ParamTraits<ppapi::proxy::SerializedFontDescription>::Log( 441 const param_type& p, 442 std::string* l) { 443} 444#endif // !defined(OS_NACL) && !defined(NACL_WIN64) 445 446// ppapi::proxy::SerializedTrueTypeFontDesc ------------------------------------ 447 448// static 449void ParamTraits<ppapi::proxy::SerializedTrueTypeFontDesc>::Write( 450 Message* m, 451 const param_type& p) { 452 ParamTraits<std::string>::Write(m, p.family); 453 ParamTraits<PP_TrueTypeFontFamily_Dev>::Write(m, p.generic_family); 454 ParamTraits<PP_TrueTypeFontStyle_Dev>::Write(m, p.style); 455 ParamTraits<PP_TrueTypeFontWeight_Dev>::Write(m, p.weight); 456 ParamTraits<PP_TrueTypeFontWidth_Dev>::Write(m, p.width); 457 ParamTraits<PP_TrueTypeFontCharset_Dev>::Write(m, p.charset); 458} 459 460// static 461bool ParamTraits<ppapi::proxy::SerializedTrueTypeFontDesc>::Read( 462 const Message* m, 463 PickleIterator* iter, 464 param_type* r) { 465 return 466 ParamTraits<std::string>::Read(m, iter, &r->family) && 467 ParamTraits<PP_TrueTypeFontFamily_Dev>::Read(m, iter, 468 &r->generic_family) && 469 ParamTraits<PP_TrueTypeFontStyle_Dev>::Read(m, iter, &r->style) && 470 ParamTraits<PP_TrueTypeFontWeight_Dev>::Read(m, iter, &r->weight) && 471 ParamTraits<PP_TrueTypeFontWidth_Dev>::Read(m, iter, &r->width) && 472 ParamTraits<PP_TrueTypeFontCharset_Dev>::Read(m, iter, &r->charset); 473} 474 475// static 476void ParamTraits<ppapi::proxy::SerializedTrueTypeFontDesc>::Log( 477 const param_type& p, 478 std::string* l) { 479} 480 481#if !defined(OS_NACL) && !defined(NACL_WIN64) 482// ppapi::PepperFilePath ------------------------------------------------------- 483 484// static 485void ParamTraits<ppapi::PepperFilePath>::Write(Message* m, 486 const param_type& p) { 487 WriteParam(m, static_cast<unsigned>(p.domain())); 488 WriteParam(m, p.path()); 489} 490 491// static 492bool ParamTraits<ppapi::PepperFilePath>::Read(const Message* m, 493 PickleIterator* iter, 494 param_type* p) { 495 unsigned domain; 496 base::FilePath path; 497 if (!ReadParam(m, iter, &domain) || !ReadParam(m, iter, &path)) 498 return false; 499 if (domain > ppapi::PepperFilePath::DOMAIN_MAX_VALID) 500 return false; 501 502 *p = ppapi::PepperFilePath( 503 static_cast<ppapi::PepperFilePath::Domain>(domain), path); 504 return true; 505} 506 507// static 508void ParamTraits<ppapi::PepperFilePath>::Log(const param_type& p, 509 std::string* l) { 510 l->append("("); 511 LogParam(static_cast<unsigned>(p.domain()), l); 512 l->append(", "); 513 LogParam(p.path(), l); 514 l->append(")"); 515} 516 517// SerializedFlashMenu --------------------------------------------------------- 518 519// static 520void ParamTraits<ppapi::proxy::SerializedFlashMenu>::Write( 521 Message* m, 522 const param_type& p) { 523 p.WriteToMessage(m); 524} 525 526// static 527bool ParamTraits<ppapi::proxy::SerializedFlashMenu>::Read(const Message* m, 528 PickleIterator* iter, 529 param_type* r) { 530 return r->ReadFromMessage(m, iter); 531} 532 533// static 534void ParamTraits<ppapi::proxy::SerializedFlashMenu>::Log(const param_type& p, 535 std::string* l) { 536} 537#endif // !defined(OS_NACL) && !defined(NACL_WIN64) 538 539// PPB_X509Certificate_Fields -------------------------------------------------- 540 541// static 542void ParamTraits<ppapi::PPB_X509Certificate_Fields>::Write( 543 Message* m, 544 const param_type& p) { 545 ParamTraits<base::ListValue>::Write(m, p.values_); 546} 547 548// static 549bool ParamTraits<ppapi::PPB_X509Certificate_Fields>::Read(const Message* m, 550 PickleIterator* iter, 551 param_type* r) { 552 return ParamTraits<base::ListValue>::Read(m, iter, &(r->values_)); 553} 554 555// static 556void ParamTraits<ppapi::PPB_X509Certificate_Fields>::Log(const param_type& p, 557 std::string* l) { 558} 559 560// ppapi::SocketOptionData ----------------------------------------------------- 561 562// static 563void ParamTraits<ppapi::SocketOptionData>::Write(Message* m, 564 const param_type& p) { 565 ppapi::SocketOptionData::Type type = p.GetType(); 566 ParamTraits<int32_t>::Write(m, static_cast<int32_t>(type)); 567 switch (type) { 568 case ppapi::SocketOptionData::TYPE_INVALID: { 569 break; 570 } 571 case ppapi::SocketOptionData::TYPE_BOOL: { 572 bool out_value = false; 573 bool result = p.GetBool(&out_value); 574 // Suppress unused variable warnings. 575 static_cast<void>(result); 576 DCHECK(result); 577 578 ParamTraits<bool>::Write(m, out_value); 579 break; 580 } 581 case ppapi::SocketOptionData::TYPE_INT32: { 582 int32_t out_value = 0; 583 bool result = p.GetInt32(&out_value); 584 // Suppress unused variable warnings. 585 static_cast<void>(result); 586 DCHECK(result); 587 588 ParamTraits<int32_t>::Write(m, out_value); 589 break; 590 } 591 // No default so the compiler will warn on new types. 592 } 593} 594 595// static 596bool ParamTraits<ppapi::SocketOptionData>::Read(const Message* m, 597 PickleIterator* iter, 598 param_type* r) { 599 *r = ppapi::SocketOptionData(); 600 int32_t type = 0; 601 if (!ParamTraits<int32_t>::Read(m, iter, &type)) 602 return false; 603 if (type != ppapi::SocketOptionData::TYPE_INVALID && 604 type != ppapi::SocketOptionData::TYPE_BOOL && 605 type != ppapi::SocketOptionData::TYPE_INT32) { 606 return false; 607 } 608 switch (static_cast<ppapi::SocketOptionData::Type>(type)) { 609 case ppapi::SocketOptionData::TYPE_INVALID: { 610 return true; 611 } 612 case ppapi::SocketOptionData::TYPE_BOOL: { 613 bool value = false; 614 if (!ParamTraits<bool>::Read(m, iter, &value)) 615 return false; 616 r->SetBool(value); 617 return true; 618 } 619 case ppapi::SocketOptionData::TYPE_INT32: { 620 int32_t value = 0; 621 if (!ParamTraits<int32_t>::Read(m, iter, &value)) 622 return false; 623 r->SetInt32(value); 624 return true; 625 } 626 // No default so the compiler will warn on new types. 627 } 628 return false; 629} 630 631// static 632void ParamTraits<ppapi::SocketOptionData>::Log(const param_type& p, 633 std::string* l) { 634} 635 636// ppapi::CompositorLayerData -------------------------------------------------- 637 638// static 639void ParamTraits<ppapi::CompositorLayerData::Transform>::Write( 640 Message* m, 641 const param_type& p) { 642 for (size_t i = 0; i < arraysize(p.matrix); i++) 643 ParamTraits<float>::Write(m, p.matrix[i]); 644} 645 646// static 647bool ParamTraits<ppapi::CompositorLayerData::Transform>::Read( 648 const Message* m, 649 PickleIterator* iter, 650 param_type* r) { 651 for (size_t i = 0; i < arraysize(r->matrix);i++) { 652 if (!ParamTraits<float>::Read(m, iter, &r->matrix[i])) 653 return false; 654 } 655 return true; 656} 657 658void ParamTraits<ppapi::CompositorLayerData::Transform>::Log( 659 const param_type& p, 660 std::string* l) { 661} 662 663} // namespace IPC 664