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
,
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
,
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 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 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 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 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 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 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(const Message
* m
,
295 PickleIterator
* iter
,
297 ppapi::proxy::SerializedHandle::Header header
;
298 if (!ppapi::proxy::SerializedHandle::ReadHeader(iter
, &header
))
300 switch (header
.type
) {
301 case ppapi::proxy::SerializedHandle::SHARED_MEMORY
: {
302 base::SharedMemoryHandle handle
;
303 if (ParamTraits
<base::SharedMemoryHandle
>::Read(m
, iter
, &handle
)) {
304 r
->set_shmem(handle
, header
.size
);
309 case ppapi::proxy::SerializedHandle::SOCKET
: {
310 IPC::PlatformFileForTransit socket
;
311 if (ParamTraits
<IPC::PlatformFileForTransit
>::Read(m
, iter
, &socket
)) {
312 r
->set_socket(socket
);
317 case ppapi::proxy::SerializedHandle::FILE: {
318 IPC::PlatformFileForTransit desc
;
319 if (ParamTraits
<IPC::PlatformFileForTransit
>::Read(m
, iter
, &desc
)) {
320 r
->set_file_handle(desc
, header
.open_flags
, header
.file_io
);
325 case ppapi::proxy::SerializedHandle::INVALID
:
327 // No default so the compiler will warn us if a new type is added.
333 void ParamTraits
<ppapi::proxy::SerializedHandle
>::Log(const param_type
& p
,
337 // PPBURLLoader_UpdateProgress_Params ------------------------------------------
340 void ParamTraits
<ppapi::proxy::PPBURLLoader_UpdateProgress_Params
>::Write(
342 const param_type
& p
) {
343 ParamTraits
<PP_Instance
>::Write(m
, p
.instance
);
344 ParamTraits
<ppapi::HostResource
>::Write(m
, p
.resource
);
345 ParamTraits
<int64_t>::Write(m
, p
.bytes_sent
);
346 ParamTraits
<int64_t>::Write(m
, p
.total_bytes_to_be_sent
);
347 ParamTraits
<int64_t>::Write(m
, p
.bytes_received
);
348 ParamTraits
<int64_t>::Write(m
, p
.total_bytes_to_be_received
);
352 bool ParamTraits
<ppapi::proxy::PPBURLLoader_UpdateProgress_Params
>::Read(
354 PickleIterator
* iter
,
357 ParamTraits
<PP_Instance
>::Read(m
, iter
, &r
->instance
) &&
358 ParamTraits
<ppapi::HostResource
>::Read(m
, iter
, &r
->resource
) &&
359 ParamTraits
<int64_t>::Read(m
, iter
, &r
->bytes_sent
) &&
360 ParamTraits
<int64_t>::Read(m
, iter
, &r
->total_bytes_to_be_sent
) &&
361 ParamTraits
<int64_t>::Read(m
, iter
, &r
->bytes_received
) &&
362 ParamTraits
<int64_t>::Read(m
, iter
, &r
->total_bytes_to_be_received
);
366 void ParamTraits
<ppapi::proxy::PPBURLLoader_UpdateProgress_Params
>::Log(
371 #if !defined(OS_NACL) && !defined(NACL_WIN64)
372 // PPBFlash_DrawGlyphs_Params --------------------------------------------------
374 void ParamTraits
<ppapi::proxy::PPBFlash_DrawGlyphs_Params
>::Write(
376 const param_type
& p
) {
377 ParamTraits
<PP_Instance
>::Write(m
, p
.instance
);
378 ParamTraits
<ppapi::HostResource
>::Write(m
, p
.image_data
);
379 ParamTraits
<ppapi::proxy::SerializedFontDescription
>::Write(m
, p
.font_desc
);
380 ParamTraits
<uint32_t>::Write(m
, p
.color
);
381 ParamTraits
<PP_Point
>::Write(m
, p
.position
);
382 ParamTraits
<PP_Rect
>::Write(m
, p
.clip
);
383 ParamTraits
<float>::Write(m
, p
.transformation
[0][0]);
384 ParamTraits
<float>::Write(m
, p
.transformation
[0][1]);
385 ParamTraits
<float>::Write(m
, p
.transformation
[0][2]);
386 ParamTraits
<float>::Write(m
, p
.transformation
[1][0]);
387 ParamTraits
<float>::Write(m
, p
.transformation
[1][1]);
388 ParamTraits
<float>::Write(m
, p
.transformation
[1][2]);
389 ParamTraits
<float>::Write(m
, p
.transformation
[2][0]);
390 ParamTraits
<float>::Write(m
, p
.transformation
[2][1]);
391 ParamTraits
<float>::Write(m
, p
.transformation
[2][2]);
392 ParamTraits
<PP_Bool
>::Write(m
, p
.allow_subpixel_aa
);
393 ParamTraits
<std::vector
<uint16_t> >::Write(m
, p
.glyph_indices
);
394 ParamTraits
<std::vector
<PP_Point
> >::Write(m
, p
.glyph_advances
);
398 bool ParamTraits
<ppapi::proxy::PPBFlash_DrawGlyphs_Params
>::Read(
400 PickleIterator
* iter
,
403 ParamTraits
<PP_Instance
>::Read(m
, iter
, &r
->instance
) &&
404 ParamTraits
<ppapi::HostResource
>::Read(m
, iter
, &r
->image_data
) &&
405 ParamTraits
<ppapi::proxy::SerializedFontDescription
>::Read(m
, iter
,
407 ParamTraits
<uint32_t>::Read(m
, iter
, &r
->color
) &&
408 ParamTraits
<PP_Point
>::Read(m
, iter
, &r
->position
) &&
409 ParamTraits
<PP_Rect
>::Read(m
, iter
, &r
->clip
) &&
410 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[0][0]) &&
411 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[0][1]) &&
412 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[0][2]) &&
413 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[1][0]) &&
414 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[1][1]) &&
415 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[1][2]) &&
416 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[2][0]) &&
417 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[2][1]) &&
418 ParamTraits
<float>::Read(m
, iter
, &r
->transformation
[2][2]) &&
419 ParamTraits
<PP_Bool
>::Read(m
, iter
, &r
->allow_subpixel_aa
) &&
420 ParamTraits
<std::vector
<uint16_t> >::Read(m
, iter
, &r
->glyph_indices
) &&
421 ParamTraits
<std::vector
<PP_Point
> >::Read(m
, iter
, &r
->glyph_advances
) &&
422 r
->glyph_indices
.size() == r
->glyph_advances
.size();
426 void ParamTraits
<ppapi::proxy::PPBFlash_DrawGlyphs_Params
>::Log(
431 // SerializedDirEntry ----------------------------------------------------------
434 void ParamTraits
<ppapi::proxy::SerializedDirEntry
>::Write(Message
* m
,
435 const param_type
& p
) {
436 ParamTraits
<std::string
>::Write(m
, p
.name
);
437 ParamTraits
<bool>::Write(m
, p
.is_dir
);
441 bool ParamTraits
<ppapi::proxy::SerializedDirEntry
>::Read(const Message
* m
,
442 PickleIterator
* iter
,
444 return ParamTraits
<std::string
>::Read(m
, iter
, &r
->name
) &&
445 ParamTraits
<bool>::Read(m
, iter
, &r
->is_dir
);
449 void ParamTraits
<ppapi::proxy::SerializedDirEntry
>::Log(const param_type
& p
,
453 // ppapi::proxy::SerializedFontDescription -------------------------------------
456 void ParamTraits
<ppapi::proxy::SerializedFontDescription
>::Write(
458 const param_type
& p
) {
459 ParamTraits
<std::string
>::Write(m
, p
.face
);
460 ParamTraits
<int32_t>::Write(m
, p
.family
);
461 ParamTraits
<uint32_t>::Write(m
, p
.size
);
462 ParamTraits
<int32_t>::Write(m
, p
.weight
);
463 ParamTraits
<PP_Bool
>::Write(m
, p
.italic
);
464 ParamTraits
<PP_Bool
>::Write(m
, p
.small_caps
);
465 ParamTraits
<int32_t>::Write(m
, p
.letter_spacing
);
466 ParamTraits
<int32_t>::Write(m
, p
.word_spacing
);
470 bool ParamTraits
<ppapi::proxy::SerializedFontDescription
>::Read(
472 PickleIterator
* iter
,
475 ParamTraits
<std::string
>::Read(m
, iter
, &r
->face
) &&
476 ParamTraits
<int32_t>::Read(m
, iter
, &r
->family
) &&
477 ParamTraits
<uint32_t>::Read(m
, iter
, &r
->size
) &&
478 ParamTraits
<int32_t>::Read(m
, iter
, &r
->weight
) &&
479 ParamTraits
<PP_Bool
>::Read(m
, iter
, &r
->italic
) &&
480 ParamTraits
<PP_Bool
>::Read(m
, iter
, &r
->small_caps
) &&
481 ParamTraits
<int32_t>::Read(m
, iter
, &r
->letter_spacing
) &&
482 ParamTraits
<int32_t>::Read(m
, iter
, &r
->word_spacing
);
486 void ParamTraits
<ppapi::proxy::SerializedFontDescription
>::Log(
490 #endif // !defined(OS_NACL) && !defined(NACL_WIN64)
492 // ppapi::proxy::SerializedTrueTypeFontDesc ------------------------------------
495 void ParamTraits
<ppapi::proxy::SerializedTrueTypeFontDesc
>::Write(
497 const param_type
& p
) {
498 ParamTraits
<std::string
>::Write(m
, p
.family
);
499 ParamTraits
<PP_TrueTypeFontFamily_Dev
>::Write(m
, p
.generic_family
);
500 ParamTraits
<PP_TrueTypeFontStyle_Dev
>::Write(m
, p
.style
);
501 ParamTraits
<PP_TrueTypeFontWeight_Dev
>::Write(m
, p
.weight
);
502 ParamTraits
<PP_TrueTypeFontWidth_Dev
>::Write(m
, p
.width
);
503 ParamTraits
<PP_TrueTypeFontCharset_Dev
>::Write(m
, p
.charset
);
507 bool ParamTraits
<ppapi::proxy::SerializedTrueTypeFontDesc
>::Read(
509 PickleIterator
* iter
,
512 ParamTraits
<std::string
>::Read(m
, iter
, &r
->family
) &&
513 ParamTraits
<PP_TrueTypeFontFamily_Dev
>::Read(m
, iter
,
514 &r
->generic_family
) &&
515 ParamTraits
<PP_TrueTypeFontStyle_Dev
>::Read(m
, iter
, &r
->style
) &&
516 ParamTraits
<PP_TrueTypeFontWeight_Dev
>::Read(m
, iter
, &r
->weight
) &&
517 ParamTraits
<PP_TrueTypeFontWidth_Dev
>::Read(m
, iter
, &r
->width
) &&
518 ParamTraits
<PP_TrueTypeFontCharset_Dev
>::Read(m
, iter
, &r
->charset
);
522 void ParamTraits
<ppapi::proxy::SerializedTrueTypeFontDesc
>::Log(
527 #if !defined(OS_NACL) && !defined(NACL_WIN64)
528 // ppapi::PepperFilePath -------------------------------------------------------
531 void ParamTraits
<ppapi::PepperFilePath
>::Write(Message
* m
,
532 const param_type
& p
) {
533 WriteParam(m
, static_cast<unsigned>(p
.domain()));
534 WriteParam(m
, p
.path());
538 bool ParamTraits
<ppapi::PepperFilePath
>::Read(const Message
* m
,
539 PickleIterator
* iter
,
543 if (!ReadParam(m
, iter
, &domain
) || !ReadParam(m
, iter
, &path
))
545 if (domain
> ppapi::PepperFilePath::DOMAIN_MAX_VALID
)
548 *p
= ppapi::PepperFilePath(
549 static_cast<ppapi::PepperFilePath::Domain
>(domain
), path
);
554 void ParamTraits
<ppapi::PepperFilePath
>::Log(const param_type
& p
,
557 LogParam(static_cast<unsigned>(p
.domain()), l
);
559 LogParam(p
.path(), l
);
563 // SerializedFlashMenu ---------------------------------------------------------
566 void ParamTraits
<ppapi::proxy::SerializedFlashMenu
>::Write(
568 const param_type
& p
) {
573 bool ParamTraits
<ppapi::proxy::SerializedFlashMenu
>::Read(const Message
* m
,
574 PickleIterator
* iter
,
576 return r
->ReadFromMessage(m
, iter
);
580 void ParamTraits
<ppapi::proxy::SerializedFlashMenu
>::Log(const param_type
& p
,
583 #endif // !defined(OS_NACL) && !defined(NACL_WIN64)
585 // PPB_X509Certificate_Fields --------------------------------------------------
588 void ParamTraits
<ppapi::PPB_X509Certificate_Fields
>::Write(
590 const param_type
& p
) {
591 ParamTraits
<base::ListValue
>::Write(m
, p
.values_
);
595 bool ParamTraits
<ppapi::PPB_X509Certificate_Fields
>::Read(const Message
* m
,
596 PickleIterator
* iter
,
598 return ParamTraits
<base::ListValue
>::Read(m
, iter
, &(r
->values_
));
602 void ParamTraits
<ppapi::PPB_X509Certificate_Fields
>::Log(const param_type
& p
,
606 // ppapi::SocketOptionData -----------------------------------------------------
609 void ParamTraits
<ppapi::SocketOptionData
>::Write(Message
* m
,
610 const param_type
& p
) {
611 ppapi::SocketOptionData::Type type
= p
.GetType();
612 ParamTraits
<int32_t>::Write(m
, static_cast<int32_t>(type
));
614 case ppapi::SocketOptionData::TYPE_INVALID
: {
617 case ppapi::SocketOptionData::TYPE_BOOL
: {
618 bool out_value
= false;
619 bool result
= p
.GetBool(&out_value
);
620 // Suppress unused variable warnings.
621 static_cast<void>(result
);
624 ParamTraits
<bool>::Write(m
, out_value
);
627 case ppapi::SocketOptionData::TYPE_INT32
: {
628 int32_t out_value
= 0;
629 bool result
= p
.GetInt32(&out_value
);
630 // Suppress unused variable warnings.
631 static_cast<void>(result
);
634 ParamTraits
<int32_t>::Write(m
, out_value
);
637 // No default so the compiler will warn on new types.
642 bool ParamTraits
<ppapi::SocketOptionData
>::Read(const Message
* m
,
643 PickleIterator
* iter
,
645 *r
= ppapi::SocketOptionData();
647 if (!ParamTraits
<int32_t>::Read(m
, iter
, &type
))
649 if (type
!= ppapi::SocketOptionData::TYPE_INVALID
&&
650 type
!= ppapi::SocketOptionData::TYPE_BOOL
&&
651 type
!= ppapi::SocketOptionData::TYPE_INT32
) {
654 switch (static_cast<ppapi::SocketOptionData::Type
>(type
)) {
655 case ppapi::SocketOptionData::TYPE_INVALID
: {
658 case ppapi::SocketOptionData::TYPE_BOOL
: {
660 if (!ParamTraits
<bool>::Read(m
, iter
, &value
))
665 case ppapi::SocketOptionData::TYPE_INT32
: {
667 if (!ParamTraits
<int32_t>::Read(m
, iter
, &value
))
672 // No default so the compiler will warn on new types.
678 void ParamTraits
<ppapi::SocketOptionData
>::Log(const param_type
& p
,
682 // ppapi::CompositorLayerData --------------------------------------------------
685 void ParamTraits
<ppapi::CompositorLayerData::Transform
>::Write(
687 const param_type
& p
) {
688 for (size_t i
= 0; i
< arraysize(p
.matrix
); i
++)
689 ParamTraits
<float>::Write(m
, p
.matrix
[i
]);
693 bool ParamTraits
<ppapi::CompositorLayerData::Transform
>::Read(
695 PickleIterator
* iter
,
697 for (size_t i
= 0; i
< arraysize(r
->matrix
);i
++) {
698 if (!ParamTraits
<float>::Read(m
, iter
, &r
->matrix
[i
]))
704 void ParamTraits
<ppapi::CompositorLayerData::Transform
>::Log(