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