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/resource_message_params.h"
6
7#include "base/logging.h"
8#include "ppapi/c/pp_errors.h"
9#include "ppapi/proxy/ppapi_messages.h"
10
11namespace ppapi {
12namespace proxy {
13
14ResourceMessageParams::SerializedHandles::SerializedHandles()
15    : should_close_(false) {
16}
17
18ResourceMessageParams::SerializedHandles::~SerializedHandles() {
19  if (should_close_) {
20    for (std::vector<SerializedHandle>::iterator iter = data_.begin();
21         iter != data_.end(); ++iter) {
22      iter->Close();
23    }
24  }
25}
26
27ResourceMessageParams::ResourceMessageParams()
28    : pp_resource_(0),
29      sequence_(0),
30      handles_(new SerializedHandles()) {
31}
32
33ResourceMessageParams::ResourceMessageParams(PP_Resource resource,
34                                             int32_t sequence)
35    : pp_resource_(resource),
36      sequence_(sequence),
37      handles_(new SerializedHandles()) {
38}
39
40ResourceMessageParams::~ResourceMessageParams() {
41}
42
43void ResourceMessageParams::Serialize(IPC::Message* msg) const {
44  WriteHeader(msg);
45  WriteHandles(msg);
46}
47
48bool ResourceMessageParams::Deserialize(const IPC::Message* msg,
49                                        PickleIterator* iter) {
50  return ReadHeader(msg, iter) && ReadHandles(msg, iter);
51}
52
53void ResourceMessageParams::WriteHeader(IPC::Message* msg) const {
54  IPC::ParamTraits<PP_Resource>::Write(msg, pp_resource_);
55  IPC::ParamTraits<int32_t>::Write(msg, sequence_);
56}
57
58void ResourceMessageParams::WriteHandles(IPC::Message* msg) const {
59  IPC::ParamTraits<std::vector<SerializedHandle> >::Write(msg,
60                                                          handles_->data());
61}
62
63bool ResourceMessageParams::ReadHeader(const IPC::Message* msg,
64                                       PickleIterator* iter) {
65  DCHECK(handles_->data().empty());
66  handles_->set_should_close(true);
67  return IPC::ParamTraits<PP_Resource>::Read(msg, iter, &pp_resource_) &&
68         IPC::ParamTraits<int32_t>::Read(msg, iter, &sequence_);
69}
70
71bool ResourceMessageParams::ReadHandles(const IPC::Message* msg,
72                                        PickleIterator* iter) {
73  return IPC::ParamTraits<std::vector<SerializedHandle> >::Read(
74             msg, iter, &handles_->data());
75}
76
77void ResourceMessageParams::ConsumeHandles() const {
78  // Note: we must not invalidate the handles. This is used for converting
79  // handles from the host OS to NaCl, and that conversion will not work if we
80  // invalidate the handles (see HandleConverter).
81  handles_->set_should_close(false);
82}
83
84SerializedHandle ResourceMessageParams::TakeHandleOfTypeAtIndex(
85    size_t index,
86    SerializedHandle::Type type) const {
87  SerializedHandle handle;
88  std::vector<SerializedHandle>& data = handles_->data();
89  if (index < data.size() && data[index].type() == type) {
90    handle = data[index];
91    data[index] = SerializedHandle();
92  }
93  return handle;
94}
95
96bool ResourceMessageParams::TakeSharedMemoryHandleAtIndex(
97    size_t index,
98    base::SharedMemoryHandle* handle) const {
99  SerializedHandle serialized = TakeHandleOfTypeAtIndex(
100      index, SerializedHandle::SHARED_MEMORY);
101  if (!serialized.is_shmem())
102    return false;
103  *handle = serialized.shmem();
104  return true;
105}
106
107bool ResourceMessageParams::TakeSocketHandleAtIndex(
108    size_t index,
109    IPC::PlatformFileForTransit* handle) const {
110  SerializedHandle serialized = TakeHandleOfTypeAtIndex(
111      index, SerializedHandle::SOCKET);
112  if (!serialized.is_socket())
113    return false;
114  *handle = serialized.descriptor();
115  return true;
116}
117
118bool ResourceMessageParams::TakeFileHandleAtIndex(
119    size_t index,
120    IPC::PlatformFileForTransit* handle) const {
121  SerializedHandle serialized = TakeHandleOfTypeAtIndex(
122      index, SerializedHandle::FILE);
123  if (!serialized.is_file())
124    return false;
125  *handle = serialized.descriptor();
126  return true;
127}
128
129void ResourceMessageParams::TakeAllSharedMemoryHandles(
130    std::vector<base::SharedMemoryHandle>* handles) const {
131  for (size_t i = 0; i < handles_->data().size(); ++i) {
132    base::SharedMemoryHandle handle;
133    if (TakeSharedMemoryHandleAtIndex(i, &handle))
134      handles->push_back(handle);
135  }
136}
137
138void ResourceMessageParams::AppendHandle(const SerializedHandle& handle) const {
139  handles_->data().push_back(handle);
140}
141
142ResourceMessageCallParams::ResourceMessageCallParams()
143    : ResourceMessageParams(),
144      has_callback_(0) {
145}
146
147ResourceMessageCallParams::ResourceMessageCallParams(PP_Resource resource,
148                                                     int32_t sequence)
149    : ResourceMessageParams(resource, sequence),
150      has_callback_(0) {
151}
152
153ResourceMessageCallParams::~ResourceMessageCallParams() {
154}
155
156void ResourceMessageCallParams::Serialize(IPC::Message* msg) const {
157  ResourceMessageParams::Serialize(msg);
158  IPC::ParamTraits<bool>::Write(msg, has_callback_);
159}
160
161bool ResourceMessageCallParams::Deserialize(const IPC::Message* msg,
162                                            PickleIterator* iter) {
163  if (!ResourceMessageParams::Deserialize(msg, iter))
164    return false;
165  return IPC::ParamTraits<bool>::Read(msg, iter, &has_callback_);
166}
167
168ResourceMessageReplyParams::ResourceMessageReplyParams()
169    : ResourceMessageParams(),
170      result_(PP_OK) {
171}
172
173ResourceMessageReplyParams::ResourceMessageReplyParams(PP_Resource resource,
174                                                       int32_t sequence)
175    : ResourceMessageParams(resource, sequence),
176      result_(PP_OK) {
177}
178
179ResourceMessageReplyParams::~ResourceMessageReplyParams() {
180}
181
182void ResourceMessageReplyParams::Serialize(IPC::Message* msg) const {
183  // Rather than serialize all of ResourceMessageParams first, we serialize all
184  // non-handle data first, then the handles. When transferring to NaCl on
185  // Windows, we need to be able to translate Windows-style handles to POSIX-
186  // style handles, and it's easier to put all the regular stuff at the front.
187  WriteReplyHeader(msg);
188  WriteHandles(msg);
189}
190
191bool ResourceMessageReplyParams::Deserialize(const IPC::Message* msg,
192                                             PickleIterator* iter) {
193  return (ReadHeader(msg, iter) &&
194          IPC::ParamTraits<int32_t>::Read(msg, iter, &result_) &&
195          ReadHandles(msg, iter));
196}
197
198void ResourceMessageReplyParams::WriteReplyHeader(IPC::Message* msg) const {
199  WriteHeader(msg);
200  IPC::ParamTraits<int32_t>::Write(msg, result_);
201}
202
203}  // namespace proxy
204}  // namespace ppapi
205