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