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.
5 #include "ppapi/proxy/ppapi_param_traits.h"
7 #include <string.h> // For memcpy
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"
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
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
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.
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.
40 bool ReadVectorWithoutCopy(const Message
* m
,
41 base::PickleIterator
* iter
,
42 std::vector
<T
>* output
) {
43 // This part is just a copy of the the default ParamTraits vector Read().
45 // ReadLength() checks for < 0 itself.
46 if (!iter
->ReadLength(&size
))
48 // Resizing beforehand is not safe, see BUG 1006367 for details.
49 if (INT_MAX
/ sizeof(T
) <= static_cast<size_t>(size
))
52 output
->reserve(size
);
53 for (int i
= 0; i
< size
; i
++) {
55 if (!ReadParam(m
, iter
, &cur
))
57 output
->push_back(cur
);
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.
67 void 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
++)
75 // PP_Bool ---------------------------------------------------------------------
78 void ParamTraits
<PP_Bool
>::Write(Message
* m
, const param_type
& p
) {
79 ParamTraits
<bool>::Write(m
, PP_ToBool(p
));
83 bool ParamTraits
<PP_Bool
>::Read(const Message
* m
,
84 base::PickleIterator
* iter
,
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.
90 if (!ParamTraits
<bool>::Read(m
, iter
, &result
))
92 *r
= PP_FromBool(result
);
97 void ParamTraits
<PP_Bool
>::Log(const param_type
& p
, std::string
* l
) {
100 // PP_KeyInformation -------------------------------------------------------
103 void ParamTraits
<PP_KeyInformation
>::Write(Message
* m
, const param_type
& p
) {
104 WriteParam(m
, p
.key_id_size
);
105 m
->WriteBytes(p
.key_id
, static_cast<int>(p
.key_id_size
));
106 WriteParam(m
, p
.key_status
);
107 WriteParam(m
, p
.system_code
);
111 bool ParamTraits
<PP_KeyInformation
>::Read(const Message
* m
,
112 base::PickleIterator
* iter
,
115 if (!ReadParam(m
, iter
, &size
))
117 if (size
> sizeof(p
->key_id
))
119 p
->key_id_size
= size
;
122 if (!iter
->ReadBytes(&data
, size
))
124 memcpy(p
->key_id
, data
, size
);
126 PP_CdmKeyStatus key_status
;
127 if (!ReadParam(m
, iter
, &key_status
))
129 p
->key_status
= key_status
;
131 uint32_t system_code
;
132 if (!ReadParam(m
, iter
, &system_code
))
134 p
->system_code
= system_code
;
140 void ParamTraits
<PP_KeyInformation
>::Log(const param_type
& p
, std::string
* l
) {
141 l
->append("<PP_KeyInformation (");
142 LogParam(p
.key_id_size
, l
);
143 l
->append(" bytes)>");
146 // PP_NetAddress_Private -------------------------------------------------------
149 void ParamTraits
<PP_NetAddress_Private
>::Write(Message
* m
,
150 const param_type
& p
) {
151 WriteParam(m
, p
.size
);
152 m
->WriteBytes(p
.data
, static_cast<int>(p
.size
));
156 bool ParamTraits
<PP_NetAddress_Private
>::Read(const Message
* m
,
157 base::PickleIterator
* iter
,
160 if (!ReadParam(m
, iter
, &size
))
162 if (size
> sizeof(p
->data
))
167 if (!iter
->ReadBytes(&data
, size
))
169 memcpy(p
->data
, data
, size
);
174 void ParamTraits
<PP_NetAddress_Private
>::Log(const param_type
& p
,
176 l
->append("<PP_NetAddress_Private (");
178 l
->append(" bytes)>");
181 // HostResource ----------------------------------------------------------------
184 void ParamTraits
<ppapi::HostResource
>::Write(Message
* m
,
185 const param_type
& p
) {
186 ParamTraits
<PP_Instance
>::Write(m
, p
.instance());
187 ParamTraits
<PP_Resource
>::Write(m
, p
.host_resource());
191 bool ParamTraits
<ppapi::HostResource
>::Read(const Message
* m
,
192 base::PickleIterator
* iter
,
194 PP_Instance instance
;
195 PP_Resource resource
;
196 if (!ParamTraits
<PP_Instance
>::Read(m
, iter
, &instance
) ||
197 !ParamTraits
<PP_Resource
>::Read(m
, iter
, &resource
))
199 r
->SetHostResource(instance
, resource
);
204 void ParamTraits
<ppapi::HostResource
>::Log(const param_type
& p
,
208 // SerializedVar ---------------------------------------------------------------
211 void ParamTraits
<ppapi::proxy::SerializedVar
>::Write(Message
* m
,
212 const param_type
& p
) {
217 bool ParamTraits
<ppapi::proxy::SerializedVar
>::Read(const Message
* m
,
218 base::PickleIterator
* iter
,
220 return r
->ReadFromMessage(m
, iter
);
224 void ParamTraits
<ppapi::proxy::SerializedVar
>::Log(const param_type
& p
,
228 // std::vector<SerializedVar> --------------------------------------------------
230 void ParamTraits
< std::vector
<ppapi::proxy::SerializedVar
> >::Write(
232 const param_type
& p
) {
233 WriteVectorWithoutCopy(m
, p
);
237 bool ParamTraits
<std::vector
<ppapi::proxy::SerializedVar
>>::Read(
239 base::PickleIterator
* iter
,
241 return ReadVectorWithoutCopy(m
, iter
, r
);
245 void ParamTraits
< std::vector
<ppapi::proxy::SerializedVar
> >::Log(
250 // ppapi::PpapiPermissions -----------------------------------------------------
252 void ParamTraits
<ppapi::PpapiPermissions
>::Write(Message
* m
,
253 const param_type
& p
) {
254 ParamTraits
<uint32_t>::Write(m
, p
.GetBits());
258 bool ParamTraits
<ppapi::PpapiPermissions
>::Read(const Message
* m
,
259 base::PickleIterator
* iter
,
262 if (!ParamTraits
<uint32_t>::Read(m
, iter
, &bits
))
264 *r
= ppapi::PpapiPermissions(bits
);
269 void ParamTraits
<ppapi::PpapiPermissions
>::Log(const param_type
& p
,
273 // SerializedHandle ------------------------------------------------------------
276 void ParamTraits
<ppapi::proxy::SerializedHandle
>::Write(Message
* m
,
277 const param_type
& p
) {
278 ppapi::proxy::SerializedHandle::WriteHeader(p
.header(), m
);
280 case ppapi::proxy::SerializedHandle::SHARED_MEMORY
:
281 ParamTraits
<base::SharedMemoryHandle
>::Write(m
, p
.shmem());
283 case ppapi::proxy::SerializedHandle::SOCKET
:
284 case ppapi::proxy::SerializedHandle::FILE:
285 ParamTraits
<IPC::PlatformFileForTransit
>::Write(m
, p
.descriptor());
287 case ppapi::proxy::SerializedHandle::INVALID
:
289 // No default so the compiler will warn on new types.
294 bool ParamTraits
<ppapi::proxy::SerializedHandle
>::Read(
296 base::PickleIterator
* iter
,
298 ppapi::proxy::SerializedHandle::Header header
;
299 if (!ppapi::proxy::SerializedHandle::ReadHeader(iter
, &header
))
301 switch (header
.type
) {
302 case ppapi::proxy::SerializedHandle::SHARED_MEMORY
: {
303 base::SharedMemoryHandle handle
;
304 if (ParamTraits
<base::SharedMemoryHandle
>::Read(m
, iter
, &handle
)) {
305 r
->set_shmem(handle
, header
.size
);
310 case ppapi::proxy::SerializedHandle::SOCKET
: {
311 IPC::PlatformFileForTransit socket
;
312 if (ParamTraits
<IPC::PlatformFileForTransit
>::Read(m
, iter
, &socket
)) {
313 r
->set_socket(socket
);
318 case ppapi::proxy::SerializedHandle::FILE: {
319 IPC::PlatformFileForTransit desc
;
320 if (ParamTraits
<IPC::PlatformFileForTransit
>::Read(m
, iter
, &desc
)) {
321 r
->set_file_handle(desc
, header
.open_flags
, header
.file_io
);
326 case ppapi::proxy::SerializedHandle::INVALID
:
328 // No default so the compiler will warn us if a new type is added.
334 void ParamTraits
<ppapi::proxy::SerializedHandle
>::Log(const param_type
& p
,
338 // PPBURLLoader_UpdateProgress_Params ------------------------------------------
341 void ParamTraits
<ppapi::proxy::PPBURLLoader_UpdateProgress_Params
>::Write(
343 const param_type
& p
) {
344 ParamTraits
<PP_Instance
>::Write(m
, p
.instance
);
345 ParamTraits
<ppapi::HostResource
>::Write(m
, p
.resource
);
346 ParamTraits
<int64_t>::Write(m
, p
.bytes_sent
);
347 ParamTraits
<int64_t>::Write(m
, p
.total_bytes_to_be_sent
);
348 ParamTraits
<int64_t>::Write(m
, p
.bytes_received
);
349 ParamTraits
<int64_t>::Write(m
, p
.total_bytes_to_be_received
);
353 bool ParamTraits
<ppapi::proxy::PPBURLLoader_UpdateProgress_Params
>::Read(
355 base::PickleIterator
* iter
,
358 ParamTraits
<PP_Instance
>::Read(m
, iter
, &r
->instance
) &&
359 ParamTraits
<ppapi::HostResource
>::Read(m
, iter
, &r
->resource
) &&
360 ParamTraits
<int64_t>::Read(m
, iter
, &r
->bytes_sent
) &&
361 ParamTraits
<int64_t>::Read(m
, iter
, &r
->total_bytes_to_be_sent
) &&
362 ParamTraits
<int64_t>::Read(m
, iter
, &r
->bytes_received
) &&
363 ParamTraits
<int64_t>::Read(m
, iter
, &r
->total_bytes_to_be_received
);
367 void ParamTraits
<ppapi::proxy::PPBURLLoader_UpdateProgress_Params
>::Log(
372 #if !defined(OS_NACL) && !defined(NACL_WIN64)
373 // PPBFlash_DrawGlyphs_Params --------------------------------------------------
375 void ParamTraits
<ppapi::proxy::PPBFlash_DrawGlyphs_Params
>::Write(
377 const param_type
& p
) {
378 ParamTraits
<PP_Instance
>::Write(m
, p
.instance
);
379 ParamTraits
<ppapi::HostResource
>::Write(m
, p
.image_data
);
380 ParamTraits
<ppapi::proxy::SerializedFontDescription
>::Write(m
, p
.font_desc
);
381 ParamTraits
<uint32_t>::Write(m
, p
.color
);
382 ParamTraits
<PP_Point
>::Write(m
, p
.position
);
383 ParamTraits
<PP_Rect
>::Write(m
, p
.clip
);
384 ParamTraits
<float>::Write(m
, p
.transformation
[0][0]);
385 ParamTraits
<float>::Write(m
, p
.transformation
[0][1]);
386 ParamTraits
<float>::Write(m
, p
.transformation
[0][2]);
387 ParamTraits
<float>::Write(m
, p
.transformation
[1][0]);
388 ParamTraits
<float>::Write(m
, p
.transformation
[1][1]);
389 ParamTraits
<float>::Write(m
, p
.transformation
[1][2]);
390 ParamTraits
<float>::Write(m
, p
.transformation
[2][0]);
391 ParamTraits
<float>::Write(m
, p
.transformation
[2][1]);
392 ParamTraits
<float>::Write(m
, p
.transformation
[2][2]);
393 ParamTraits
<PP_Bool
>::Write(m
, p
.allow_subpixel_aa
);
394 ParamTraits
<std::vector
<uint16_t> >::Write(m
, p
.glyph_indices
);
395 ParamTraits
<std::vector
<PP_Point
> >::Write(m
, p
.glyph_advances
);
399 bool ParamTraits
<ppapi::proxy::PPBFlash_DrawGlyphs_Params
>::Read(
401 base::PickleIterator
* iter
,
404 ParamTraits
<PP_Instance
>::Read(m
, iter
, &r
->instance
) &&
405 ParamTraits
<ppapi::HostResource
>::Read(m
, iter
, &r
->image_data
) &&
406 ParamTraits
<ppapi::proxy::SerializedFontDescription
>::Read(m
, iter
,
408 ParamTraits
<uint32_t>::Read(m
, iter
, &r
->color
) &&
409 ParamTraits
<PP_Point
>::Read(m
, iter
, &r
->position
) &&
410 ParamTraits
<PP_Rect
>::Read(m
, iter
, &r
->clip
) &&
411 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[0][0]) &&
412 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[0][1]) &&
413 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[0][2]) &&
414 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[1][0]) &&
415 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[1][1]) &&
416 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[1][2]) &&
417 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[2][0]) &&
418 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[2][1]) &&
419 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[2][2]) &&
420 ParamTraits
<PP_Bool
>::Read(m
, iter
, &r
->allow_subpixel_aa
) &&
421 ParamTraits
<std::vector
<uint16_t> >::Read(m
, iter
, &r
->glyph_indices
) &&
422 ParamTraits
<std::vector
<PP_Point
> >::Read(m
, iter
, &r
->glyph_advances
) &&
423 r
->glyph_indices
.size() == r
->glyph_advances
.size();
427 void ParamTraits
<ppapi::proxy::PPBFlash_DrawGlyphs_Params
>::Log(
432 // SerializedDirEntry ----------------------------------------------------------
435 void ParamTraits
<ppapi::proxy::SerializedDirEntry
>::Write(Message
* m
,
436 const param_type
& p
) {
437 ParamTraits
<std::string
>::Write(m
, p
.name
);
438 ParamTraits
<bool>::Write(m
, p
.is_dir
);
442 bool ParamTraits
<ppapi::proxy::SerializedDirEntry
>::Read(
444 base::PickleIterator
* iter
,
446 return ParamTraits
<std::string
>::Read(m
, iter
, &r
->name
) &&
447 ParamTraits
<bool>::Read(m
, iter
, &r
->is_dir
);
451 void ParamTraits
<ppapi::proxy::SerializedDirEntry
>::Log(const param_type
& p
,
455 // ppapi::proxy::SerializedFontDescription -------------------------------------
458 void ParamTraits
<ppapi::proxy::SerializedFontDescription
>::Write(
460 const param_type
& p
) {
461 ParamTraits
<std::string
>::Write(m
, p
.face
);
462 ParamTraits
<int32_t>::Write(m
, p
.family
);
463 ParamTraits
<uint32_t>::Write(m
, p
.size
);
464 ParamTraits
<int32_t>::Write(m
, p
.weight
);
465 ParamTraits
<PP_Bool
>::Write(m
, p
.italic
);
466 ParamTraits
<PP_Bool
>::Write(m
, p
.small_caps
);
467 ParamTraits
<int32_t>::Write(m
, p
.letter_spacing
);
468 ParamTraits
<int32_t>::Write(m
, p
.word_spacing
);
472 bool ParamTraits
<ppapi::proxy::SerializedFontDescription
>::Read(
474 base::PickleIterator
* iter
,
477 ParamTraits
<std::string
>::Read(m
, iter
, &r
->face
) &&
478 ParamTraits
<int32_t>::Read(m
, iter
, &r
->family
) &&
479 ParamTraits
<uint32_t>::Read(m
, iter
, &r
->size
) &&
480 ParamTraits
<int32_t>::Read(m
, iter
, &r
->weight
) &&
481 ParamTraits
<PP_Bool
>::Read(m
, iter
, &r
->italic
) &&
482 ParamTraits
<PP_Bool
>::Read(m
, iter
, &r
->small_caps
) &&
483 ParamTraits
<int32_t>::Read(m
, iter
, &r
->letter_spacing
) &&
484 ParamTraits
<int32_t>::Read(m
, iter
, &r
->word_spacing
);
488 void ParamTraits
<ppapi::proxy::SerializedFontDescription
>::Log(
492 #endif // !defined(OS_NACL) && !defined(NACL_WIN64)
494 // ppapi::proxy::SerializedTrueTypeFontDesc ------------------------------------
497 void ParamTraits
<ppapi::proxy::SerializedTrueTypeFontDesc
>::Write(
499 const param_type
& p
) {
500 ParamTraits
<std::string
>::Write(m
, p
.family
);
501 ParamTraits
<PP_TrueTypeFontFamily_Dev
>::Write(m
, p
.generic_family
);
502 ParamTraits
<PP_TrueTypeFontStyle_Dev
>::Write(m
, p
.style
);
503 ParamTraits
<PP_TrueTypeFontWeight_Dev
>::Write(m
, p
.weight
);
504 ParamTraits
<PP_TrueTypeFontWidth_Dev
>::Write(m
, p
.width
);
505 ParamTraits
<PP_TrueTypeFontCharset_Dev
>::Write(m
, p
.charset
);
509 bool ParamTraits
<ppapi::proxy::SerializedTrueTypeFontDesc
>::Read(
511 base::PickleIterator
* iter
,
514 ParamTraits
<std::string
>::Read(m
, iter
, &r
->family
) &&
515 ParamTraits
<PP_TrueTypeFontFamily_Dev
>::Read(m
, iter
,
516 &r
->generic_family
) &&
517 ParamTraits
<PP_TrueTypeFontStyle_Dev
>::Read(m
, iter
, &r
->style
) &&
518 ParamTraits
<PP_TrueTypeFontWeight_Dev
>::Read(m
, iter
, &r
->weight
) &&
519 ParamTraits
<PP_TrueTypeFontWidth_Dev
>::Read(m
, iter
, &r
->width
) &&
520 ParamTraits
<PP_TrueTypeFontCharset_Dev
>::Read(m
, iter
, &r
->charset
);
524 void ParamTraits
<ppapi::proxy::SerializedTrueTypeFontDesc
>::Log(
529 #if !defined(OS_NACL) && !defined(NACL_WIN64)
530 // ppapi::PepperFilePath -------------------------------------------------------
533 void ParamTraits
<ppapi::PepperFilePath
>::Write(Message
* m
,
534 const param_type
& p
) {
535 WriteParam(m
, static_cast<unsigned>(p
.domain()));
536 WriteParam(m
, p
.path());
540 bool ParamTraits
<ppapi::PepperFilePath
>::Read(const Message
* m
,
541 base::PickleIterator
* iter
,
545 if (!ReadParam(m
, iter
, &domain
) || !ReadParam(m
, iter
, &path
))
547 if (domain
> ppapi::PepperFilePath::DOMAIN_MAX_VALID
)
550 *p
= ppapi::PepperFilePath(
551 static_cast<ppapi::PepperFilePath::Domain
>(domain
), path
);
556 void ParamTraits
<ppapi::PepperFilePath
>::Log(const param_type
& p
,
559 LogParam(static_cast<unsigned>(p
.domain()), l
);
561 LogParam(p
.path(), l
);
565 // SerializedFlashMenu ---------------------------------------------------------
568 void ParamTraits
<ppapi::proxy::SerializedFlashMenu
>::Write(
570 const param_type
& p
) {
575 bool ParamTraits
<ppapi::proxy::SerializedFlashMenu
>::Read(
577 base::PickleIterator
* iter
,
579 return r
->ReadFromMessage(m
, iter
);
583 void ParamTraits
<ppapi::proxy::SerializedFlashMenu
>::Log(const param_type
& p
,
586 #endif // !defined(OS_NACL) && !defined(NACL_WIN64)
588 // PPB_X509Certificate_Fields --------------------------------------------------
591 void ParamTraits
<ppapi::PPB_X509Certificate_Fields
>::Write(
593 const param_type
& p
) {
594 ParamTraits
<base::ListValue
>::Write(m
, p
.values_
);
598 bool ParamTraits
<ppapi::PPB_X509Certificate_Fields
>::Read(
600 base::PickleIterator
* iter
,
602 return ParamTraits
<base::ListValue
>::Read(m
, iter
, &(r
->values_
));
606 void ParamTraits
<ppapi::PPB_X509Certificate_Fields
>::Log(const param_type
& p
,
610 // ppapi::SocketOptionData -----------------------------------------------------
613 void ParamTraits
<ppapi::SocketOptionData
>::Write(Message
* m
,
614 const param_type
& p
) {
615 ppapi::SocketOptionData::Type type
= p
.GetType();
616 ParamTraits
<int32_t>::Write(m
, static_cast<int32_t>(type
));
618 case ppapi::SocketOptionData::TYPE_INVALID
: {
621 case ppapi::SocketOptionData::TYPE_BOOL
: {
622 bool out_value
= false;
623 bool result
= p
.GetBool(&out_value
);
624 // Suppress unused variable warnings.
625 static_cast<void>(result
);
628 ParamTraits
<bool>::Write(m
, out_value
);
631 case ppapi::SocketOptionData::TYPE_INT32
: {
632 int32_t out_value
= 0;
633 bool result
= p
.GetInt32(&out_value
);
634 // Suppress unused variable warnings.
635 static_cast<void>(result
);
638 ParamTraits
<int32_t>::Write(m
, out_value
);
641 // No default so the compiler will warn on new types.
646 bool ParamTraits
<ppapi::SocketOptionData
>::Read(const Message
* m
,
647 base::PickleIterator
* iter
,
649 *r
= ppapi::SocketOptionData();
651 if (!ParamTraits
<int32_t>::Read(m
, iter
, &type
))
653 if (type
!= ppapi::SocketOptionData::TYPE_INVALID
&&
654 type
!= ppapi::SocketOptionData::TYPE_BOOL
&&
655 type
!= ppapi::SocketOptionData::TYPE_INT32
) {
658 switch (static_cast<ppapi::SocketOptionData::Type
>(type
)) {
659 case ppapi::SocketOptionData::TYPE_INVALID
: {
662 case ppapi::SocketOptionData::TYPE_BOOL
: {
664 if (!ParamTraits
<bool>::Read(m
, iter
, &value
))
669 case ppapi::SocketOptionData::TYPE_INT32
: {
671 if (!ParamTraits
<int32_t>::Read(m
, iter
, &value
))
676 // No default so the compiler will warn on new types.
682 void ParamTraits
<ppapi::SocketOptionData
>::Log(const param_type
& p
,
686 // ppapi::CompositorLayerData --------------------------------------------------
689 void ParamTraits
<ppapi::CompositorLayerData::Transform
>::Write(
691 const param_type
& p
) {
692 for (size_t i
= 0; i
< arraysize(p
.matrix
); i
++)
693 ParamTraits
<float>::Write(m
, p
.matrix
[i
]);
697 bool ParamTraits
<ppapi::CompositorLayerData::Transform
>::Read(
699 base::PickleIterator
* iter
,
701 for (size_t i
= 0; i
< arraysize(r
->matrix
);i
++) {
702 if (!ParamTraits
<float>::Read(m
, iter
, &r
->matrix
[i
]))
708 void ParamTraits
<ppapi::CompositorLayerData::Transform
>::Log(