blob: 5011501cf98a6ffac28e2a11b7f7219e0a7ec20f [file] [log] [blame]
[email protected]6276b492013-11-02 13:38:311// Copyright 2013 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/nacl_message_scanner.h"
6
avie029c4132015-12-23 06:45:227#include <stddef.h>
8
dchengd2b9f612015-12-18 19:08:519#include <utility>
[email protected]6276b492013-11-02 13:38:3110#include <vector>
dchengd2b9f612015-12-18 19:08:5111
[email protected]6276b492013-11-02 13:38:3112#include "base/bind.h"
avie029c4132015-12-23 06:45:2213#include "build/build_config.h"
[email protected]6276b492013-11-02 13:38:3114#include "ipc/ipc_message.h"
15#include "ipc/ipc_message_macros.h"
16#include "ppapi/proxy/ppapi_messages.h"
17#include "ppapi/proxy/resource_message_params.h"
18#include "ppapi/proxy/serialized_handle.h"
19#include "ppapi/proxy/serialized_var.h"
20
21class NaClDescImcShm;
22
23namespace IPC {
24class Message;
25}
26
[email protected]7a90b852013-12-28 17:54:2727using ppapi::proxy::ResourceMessageReplyParams;
28using ppapi::proxy::SerializedHandle;
29using ppapi::proxy::SerializedVar;
30
[email protected]6276b492013-11-02 13:38:3131namespace {
32
[email protected]7a90b852013-12-28 17:54:2733typedef std::vector<SerializedHandle> Handles;
[email protected]6276b492013-11-02 13:38:3134
35struct ScanningResults {
[email protected]7a90b852013-12-28 17:54:2736 ScanningResults() : handle_index(0), pp_resource(0) {}
[email protected]6276b492013-11-02 13:38:3137
38 // Vector to hold handles found in the message.
39 Handles handles;
40 // Current handle index in the rewritten message. During the scan, it will be
41 // be less than or equal to handles.size(). After the scan it should be equal.
42 int handle_index;
43 // The rewritten message. This may be NULL, so all ScanParam overloads should
[email protected]e74d2d12013-11-02 16:17:3744 // check for NULL before writing to it. In some cases, a ScanParam overload
45 // may set this to NULL when it can determine that there are no parameters
46 // that need conversion. (See the ResourceMessageReplyParams overload.)
[email protected]6276b492013-11-02 13:38:3147 scoped_ptr<IPC::Message> new_msg;
[email protected]7a90b852013-12-28 17:54:2748 // Resource id for resource messages. Save this when scanning resource replies
49 // so when we audit the nested message, we know which resource it is for.
50 PP_Resource pp_resource;
51 // Callback to receive the nested message in a resource message or reply.
52 base::Callback<void(PP_Resource, const IPC::Message&, SerializedHandle*)>
53 nested_msg_callback;
[email protected]6276b492013-11-02 13:38:3154};
55
56void WriteHandle(int handle_index,
[email protected]7a90b852013-12-28 17:54:2757 const SerializedHandle& handle,
[email protected]6276b492013-11-02 13:38:3158 IPC::Message* msg) {
[email protected]7a90b852013-12-28 17:54:2759 SerializedHandle::WriteHeader(handle.header(), msg);
[email protected]6276b492013-11-02 13:38:3160
Justin TerAvestcffdd032014-09-10 19:21:5661 if (handle.type() != SerializedHandle::INVALID) {
62 // Now write the handle itself in POSIX style.
63 // See ParamTraits<FileDescriptor>::Read for where these values are read.
64 msg->WriteBool(true); // valid == true
erikchenae6d3212015-10-10 02:43:4965 msg->WriteBool(false); // brokerable == false
Justin TerAvestcffdd032014-09-10 19:21:5666 msg->WriteInt(handle_index);
67 }
[email protected]6276b492013-11-02 13:38:3168}
69
70// Define overloads for each kind of message parameter that requires special
71// handling. See ScanTuple for how these get used.
72
73// Overload to match SerializedHandle.
[email protected]7a90b852013-12-28 17:54:2774void ScanParam(const SerializedHandle& handle, ScanningResults* results) {
[email protected]6276b492013-11-02 13:38:3175 results->handles.push_back(handle);
76 if (results->new_msg)
77 WriteHandle(results->handle_index++, handle, results->new_msg.get());
78}
79
80void HandleWriter(int* handle_index,
81 IPC::Message* m,
[email protected]7a90b852013-12-28 17:54:2782 const SerializedHandle& handle) {
[email protected]6276b492013-11-02 13:38:3183 WriteHandle((*handle_index)++, handle, m);
84}
85
86// Overload to match SerializedVar, which can contain handles.
[email protected]7a90b852013-12-28 17:54:2787void ScanParam(const SerializedVar& var, ScanningResults* results) {
88 std::vector<SerializedHandle*> var_handles = var.GetHandles();
[email protected]e74d2d12013-11-02 16:17:3789 // Copy any handles and then rewrite the message.
[email protected]6276b492013-11-02 13:38:3190 for (size_t i = 0; i < var_handles.size(); ++i)
91 results->handles.push_back(*var_handles[i]);
92 if (results->new_msg)
93 var.WriteDataToMessage(results->new_msg.get(),
94 base::Bind(&HandleWriter, &results->handle_index));
95}
96
97// For PpapiMsg_ResourceReply and the reply to PpapiHostMsg_ResourceSyncCall,
98// the handles are carried inside the ResourceMessageReplyParams.
99// NOTE: We only intercept handles from host->NaCl. The only kind of
100// ResourceMessageParams that travels this direction is
101// ResourceMessageReplyParams, so that's the only one we need to handle.
[email protected]7a90b852013-12-28 17:54:27102void ScanParam(const ResourceMessageReplyParams& params,
[email protected]6276b492013-11-02 13:38:31103 ScanningResults* results) {
[email protected]7a90b852013-12-28 17:54:27104 results->pp_resource = params.pp_resource();
[email protected]e74d2d12013-11-02 16:17:37105 // If the resource reply params don't contain handles, NULL the new message
106 // pointer to cancel further rewriting.
107 // NOTE: This works because only handles currently need rewriting, and we
108 // know at this point that this message has none.
109 if (params.handles().empty()) {
110 results->new_msg.reset(NULL);
111 return;
112 }
113
[email protected]6276b492013-11-02 13:38:31114 // If we need to rewrite the message, write everything before the handles
115 // (there's nothing after the handles).
116 if (results->new_msg) {
117 params.WriteReplyHeader(results->new_msg.get());
118 // IPC writes the vector length as an int before the contents of the
119 // vector.
120 results->new_msg->WriteInt(static_cast<int>(params.handles().size()));
121 }
122 for (Handles::const_iterator iter = params.handles().begin();
123 iter != params.handles().end();
124 ++iter) {
125 // ScanParam will write each handle to the new message, if necessary.
126 ScanParam(*iter, results);
127 }
128 // Tell ResourceMessageReplyParams that we have taken the handles, so it
129 // shouldn't close them. The NaCl runtime will take ownership of them.
130 params.ConsumeHandles();
131}
132
[email protected]7a90b852013-12-28 17:54:27133// Overload to match nested messages. If we need to rewrite the message, write
134// the parameter.
135void ScanParam(const IPC::Message& param, ScanningResults* results) {
136 if (results->pp_resource && !results->nested_msg_callback.is_null()) {
137 SerializedHandle* handle = NULL;
138 if (results->handles.size() == 1)
139 handle = &results->handles[0];
140 results->nested_msg_callback.Run(results->pp_resource, param, handle);
141 }
142 if (results->new_msg)
143 IPC::WriteParam(results->new_msg.get(), param);
144}
145
mseaborn3bedcdc2016-01-04 21:14:13146template <class T>
147void ScanParam(const std::vector<T>& vec, ScanningResults* results) {
148 if (results->new_msg)
149 IPC::WriteParam(results->new_msg.get(), static_cast<int>(vec.size()));
150 for (const T& element : vec) {
151 ScanParam(element, results);
152 }
153}
154
[email protected]7a90b852013-12-28 17:54:27155// Overload to match all other types. If we need to rewrite the message, write
156// the parameter.
[email protected]6276b492013-11-02 13:38:31157template <class T>
158void ScanParam(const T& param, ScanningResults* results) {
159 if (results->new_msg)
160 IPC::WriteParam(results->new_msg.get(), param);
161}
162
163// These just break apart the given tuple and run ScanParam over each param.
164// The idea is to scan elements in the tuple which require special handling,
165// and write them into the |results| struct.
166template <class A>
brettwd5ca2bc2015-05-29 22:15:47167void ScanTuple(const base::Tuple<A>& t1, ScanningResults* results) {
168 ScanParam(base::get<0>(t1), results);
[email protected]6276b492013-11-02 13:38:31169}
170template <class A, class B>
brettwd5ca2bc2015-05-29 22:15:47171void ScanTuple(const base::Tuple<A, B>& t1, ScanningResults* results) {
172 ScanParam(base::get<0>(t1), results);
173 ScanParam(base::get<1>(t1), results);
[email protected]6276b492013-11-02 13:38:31174}
175template <class A, class B, class C>
brettwd5ca2bc2015-05-29 22:15:47176void ScanTuple(const base::Tuple<A, B, C>& t1, ScanningResults* results) {
177 ScanParam(base::get<0>(t1), results);
178 ScanParam(base::get<1>(t1), results);
179 ScanParam(base::get<2>(t1), results);
[email protected]6276b492013-11-02 13:38:31180}
181template <class A, class B, class C, class D>
brettwd5ca2bc2015-05-29 22:15:47182void ScanTuple(const base::Tuple<A, B, C, D>& t1, ScanningResults* results) {
183 ScanParam(base::get<0>(t1), results);
184 ScanParam(base::get<1>(t1), results);
185 ScanParam(base::get<2>(t1), results);
186 ScanParam(base::get<3>(t1), results);
[email protected]6276b492013-11-02 13:38:31187}
188
189template <class MessageType>
190class MessageScannerImpl {
191 public:
192 explicit MessageScannerImpl(const IPC::Message* msg)
193 : msg_(static_cast<const MessageType*>(msg)) {
194 }
195 bool ScanMessage(ScanningResults* results) {
brettwd5ca2bc2015-05-29 22:15:47196 typename base::TupleTypes<typename MessageType::Schema::Param>::ValueTuple
197 params;
[email protected]6276b492013-11-02 13:38:31198 if (!MessageType::Read(msg_, &params))
199 return false;
200 ScanTuple(params, results);
201 return true;
202 }
203
mseaborn3bedcdc2016-01-04 21:14:13204 bool ScanSyncMessage(ScanningResults* results) {
205 typename base::TupleTypes<typename MessageType::Schema::SendParam>
206 ::ValueTuple params;
207 if (!MessageType::ReadSendParam(msg_, &params))
208 return false;
209 // If we need to rewrite the message, write the message id first.
210 if (results->new_msg) {
211 results->new_msg->set_sync();
212 int id = IPC::SyncMessage::GetMessageId(*msg_);
213 results->new_msg->WriteInt(id);
214 }
215 ScanTuple(params, results);
216 return true;
217 }
218
[email protected]6276b492013-11-02 13:38:31219 bool ScanReply(ScanningResults* results) {
brettwd5ca2bc2015-05-29 22:15:47220 typename base::TupleTypes<typename MessageType::Schema::ReplyParam>
221 ::ValueTuple params;
[email protected]6276b492013-11-02 13:38:31222 if (!MessageType::ReadReplyParam(msg_, &params))
223 return false;
224 // If we need to rewrite the message, write the message id first.
225 if (results->new_msg) {
226 results->new_msg->set_reply();
227 int id = IPC::SyncMessage::GetMessageId(*msg_);
228 results->new_msg->WriteInt(id);
229 }
230 ScanTuple(params, results);
231 return true;
232 }
[email protected]6276b492013-11-02 13:38:31233
234 private:
235 const MessageType* msg_;
236};
237
238} // namespace
239
240#define CASE_FOR_MESSAGE(MESSAGE_TYPE) \
241 case MESSAGE_TYPE::ID: { \
242 MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
243 if (rewrite_msg) \
244 results.new_msg.reset( \
[email protected]753bb252013-11-04 22:28:12245 new IPC::Message(msg.routing_id(), msg.type(), \
246 IPC::Message::PRIORITY_NORMAL)); \
[email protected]6276b492013-11-02 13:38:31247 if (!scanner.ScanMessage(&results)) \
248 return false; \
249 break; \
250 }
mseaborn3bedcdc2016-01-04 21:14:13251#define CASE_FOR_SYNC_MESSAGE(MESSAGE_TYPE) \
252 case MESSAGE_TYPE::ID: { \
253 MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
254 if (rewrite_msg) \
255 results.new_msg.reset( \
256 new IPC::Message(msg.routing_id(), msg.type(), \
257 IPC::Message::PRIORITY_NORMAL)); \
258 if (!scanner.ScanSyncMessage(&results)) \
259 return false; \
260 break; \
261 }
[email protected]6276b492013-11-02 13:38:31262#define CASE_FOR_REPLY(MESSAGE_TYPE) \
263 case MESSAGE_TYPE::ID: { \
264 MessageScannerImpl<MESSAGE_TYPE> scanner(&msg); \
265 if (rewrite_msg) \
266 results.new_msg.reset( \
[email protected]753bb252013-11-04 22:28:12267 new IPC::Message(msg.routing_id(), msg.type(), \
268 IPC::Message::PRIORITY_NORMAL)); \
[email protected]6276b492013-11-02 13:38:31269 if (!scanner.ScanReply(&results)) \
270 return false; \
271 break; \
272 }
273
274namespace ppapi {
275namespace proxy {
276
277class SerializedHandle;
278
[email protected]7a90b852013-12-28 17:54:27279NaClMessageScanner::FileSystem::FileSystem()
280 : reserved_quota_(0) {
281}
282
283NaClMessageScanner::FileSystem::~FileSystem() {
284}
285
286bool NaClMessageScanner::FileSystem::UpdateReservedQuota(int64_t delta) {
287 base::AutoLock lock(lock_);
288 if (std::numeric_limits<int64_t>::max() - reserved_quota_ < delta)
289 return false; // reserved_quota_ + delta would overflow.
290 if (reserved_quota_ + delta < 0)
291 return false;
292 reserved_quota_ += delta;
293 return true;
294}
295
296NaClMessageScanner::FileIO::FileIO(FileSystem* file_system,
297 int64_t max_written_offset)
298 : file_system_(file_system),
299 max_written_offset_(max_written_offset) {
300}
301
302NaClMessageScanner::FileIO::~FileIO() {
303}
304
305void NaClMessageScanner::FileIO::SetMaxWrittenOffset(
306 int64_t max_written_offset) {
307 base::AutoLock lock(lock_);
308 max_written_offset_ = max_written_offset;
309}
310
311bool NaClMessageScanner::FileIO::Grow(int64_t amount) {
312 base::AutoLock lock(lock_);
313 DCHECK(amount > 0);
314 if (!file_system_->UpdateReservedQuota(-amount))
315 return false;
316 max_written_offset_ += amount;
317 return true;
318}
319
[email protected]6276b492013-11-02 13:38:31320NaClMessageScanner::NaClMessageScanner() {
321}
322
[email protected]7a90b852013-12-28 17:54:27323NaClMessageScanner::~NaClMessageScanner() {
324 for (FileSystemMap::iterator it = file_systems_.begin();
325 it != file_systems_.end(); ++it)
326 delete it->second;
327 for (FileIOMap::iterator it = files_.begin(); it != files_.end(); ++it)
328 delete it->second;
329}
330
[email protected]6276b492013-11-02 13:38:31331// Windows IPC differs from POSIX in that native handles are serialized in the
332// message body, rather than passed in a separate FileDescriptorSet. Therefore,
333// on Windows, any message containing handles must be rewritten in the POSIX
334// format before we can send it to the NaCl plugin.
scottmgd19b4f72015-06-19 22:51:00335// On Mac, base::SharedMemoryHandle has a different serialization than
336// base::FileDescriptor (which base::SharedMemoryHandle is typedef-ed to in
337// OS_NACL).
[email protected]6276b492013-11-02 13:38:31338bool NaClMessageScanner::ScanMessage(
339 const IPC::Message& msg,
[email protected]c8f326a2014-08-21 23:19:07340 uint32_t type,
[email protected]6276b492013-11-02 13:38:31341 std::vector<SerializedHandle>* handles,
342 scoped_ptr<IPC::Message>* new_msg_ptr) {
343 DCHECK(handles);
344 DCHECK(handles->empty());
345 DCHECK(new_msg_ptr);
346 DCHECK(!new_msg_ptr->get());
347
348 bool rewrite_msg =
scottmgd19b4f72015-06-19 22:51:00349#if defined(OS_WIN) || defined(OS_MACOSX)
[email protected]6276b492013-11-02 13:38:31350 true;
351#else
[email protected]73af6332014-02-06 23:28:10352 false;
[email protected]6276b492013-11-02 13:38:31353#endif
354
355 // We can't always tell from the message ID if rewriting is needed. Therefore,
[email protected]e74d2d12013-11-02 16:17:37356 // scan any message types that might contain a handle. If we later determine
357 // that there are no handles, we can cancel the rewriting by clearing the
358 // results.new_msg pointer.
[email protected]6276b492013-11-02 13:38:31359 ScanningResults results;
[email protected]7a90b852013-12-28 17:54:27360 results.nested_msg_callback =
361 base::Bind(&NaClMessageScanner::AuditNestedMessage,
362 base::Unretained(this));
[email protected]c8f326a2014-08-21 23:19:07363 switch (type) {
[email protected]6276b492013-11-02 13:38:31364 CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated)
365 CASE_FOR_MESSAGE(PpapiMsg_PPPMessaging_HandleMessage)
366 CASE_FOR_MESSAGE(PpapiPluginMsg_ResourceReply)
mseaborn3bedcdc2016-01-04 21:14:13367 CASE_FOR_SYNC_MESSAGE(PpapiMsg_PnaclTranslatorLink)
Justin TerAvestcffdd032014-09-10 19:21:56368 CASE_FOR_REPLY(PpapiHostMsg_OpenResource)
penghuanga206fb492014-09-09 21:27:32369 CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_Create)
[email protected]c8f326a2014-08-21 23:19:07370 CASE_FOR_REPLY(PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer)
371 CASE_FOR_REPLY(PpapiHostMsg_PPBImageData_CreateSimple)
372 CASE_FOR_REPLY(PpapiHostMsg_ResourceSyncCall)
373 CASE_FOR_REPLY(PpapiHostMsg_SharedMemory_CreateSharedMemory)
[email protected]6276b492013-11-02 13:38:31374 default:
375 // Do nothing for messages we don't know.
376 break;
377 }
378
379 // Only messages containing handles need to be rewritten. If no handles are
380 // found, don't return the rewritten message either. This must be changed if
381 // we ever add new param types that also require rewriting.
382 if (!results.handles.empty()) {
383 handles->swap(results.handles);
dchengd2b9f612015-12-18 19:08:51384 *new_msg_ptr = std::move(results.new_msg);
[email protected]6276b492013-11-02 13:38:31385 }
386 return true;
387}
388
[email protected]c586216c2013-12-18 21:59:17389void NaClMessageScanner::ScanUntrustedMessage(
390 const IPC::Message& untrusted_msg,
391 scoped_ptr<IPC::Message>* new_msg_ptr) {
[email protected]7a90b852013-12-28 17:54:27392 // Audit FileIO and FileSystem messages to ensure that the plugin doesn't
393 // exceed its file quota. If we find the message is malformed, just pass it
394 // through - we only care about well formed messages to the host.
395 if (untrusted_msg.type() == PpapiHostMsg_ResourceCall::ID) {
396 ResourceMessageCallParams params;
397 IPC::Message nested_msg;
398 if (!UnpackMessage<PpapiHostMsg_ResourceCall>(
399 untrusted_msg, &params, &nested_msg))
400 return;
401
402 switch (nested_msg.type()) {
403 case PpapiHostMsg_FileIO_Close::ID: {
404 FileIOMap::iterator it = files_.find(params.pp_resource());
405 if (it == files_.end())
406 return;
407 // Audit FileIO Close messages to make sure the plugin reports an
408 // accurate file size.
[email protected]540d6af42014-01-28 21:19:03409 FileGrowth file_growth;
[email protected]7a90b852013-12-28 17:54:27410 if (!UnpackMessage<PpapiHostMsg_FileIO_Close>(
[email protected]540d6af42014-01-28 21:19:03411 nested_msg, &file_growth))
[email protected]7a90b852013-12-28 17:54:27412 return;
413
414 int64_t trusted_max_written_offset = it->second->max_written_offset();
415 delete it->second;
416 files_.erase(it);
417 // If the plugin is under-reporting, rewrite the message with the
418 // trusted value.
[email protected]540d6af42014-01-28 21:19:03419 if (trusted_max_written_offset > file_growth.max_written_offset) {
[email protected]7a90b852013-12-28 17:54:27420 new_msg_ptr->reset(
421 new PpapiHostMsg_ResourceCall(
422 params,
[email protected]540d6af42014-01-28 21:19:03423 PpapiHostMsg_FileIO_Close(
424 FileGrowth(trusted_max_written_offset, 0))));
[email protected]7a90b852013-12-28 17:54:27425 }
[email protected]2d585cbd2014-06-03 02:13:22426 break;
[email protected]7a90b852013-12-28 17:54:27427 }
428 case PpapiHostMsg_FileIO_SetLength::ID: {
429 FileIOMap::iterator it = files_.find(params.pp_resource());
430 if (it == files_.end())
431 return;
432 // Audit FileIO SetLength messages to make sure the plugin is within
433 // the current quota reservation. In addition, deduct the file size
434 // increase from the quota reservation.
435 int64_t length = 0;
436 if (!UnpackMessage<PpapiHostMsg_FileIO_SetLength>(
437 nested_msg, &length))
438 return;
439
440 // Calculate file size increase, taking care to avoid overflows.
441 if (length < 0)
442 return;
443 int64_t trusted_max_written_offset = it->second->max_written_offset();
444 int64_t increase = length - trusted_max_written_offset;
445 if (increase <= 0)
446 return;
447 if (!it->second->Grow(increase)) {
448 new_msg_ptr->reset(
449 new PpapiHostMsg_ResourceCall(
450 params,
451 PpapiHostMsg_FileIO_SetLength(-1)));
452 }
453 break;
454 }
455 case PpapiHostMsg_FileSystem_ReserveQuota::ID: {
456 // Audit FileSystem ReserveQuota messages to make sure the plugin
457 // reports accurate file sizes.
458 int64_t amount = 0;
[email protected]540d6af42014-01-28 21:19:03459 FileGrowthMap file_growths;
[email protected]7a90b852013-12-28 17:54:27460 if (!UnpackMessage<PpapiHostMsg_FileSystem_ReserveQuota>(
[email protected]540d6af42014-01-28 21:19:03461 nested_msg, &amount, &file_growths))
[email protected]7a90b852013-12-28 17:54:27462 return;
463
464 bool audit_failed = false;
[email protected]540d6af42014-01-28 21:19:03465 for (FileGrowthMap::iterator it = file_growths.begin();
466 it != file_growths.end(); ++it) {
[email protected]7a90b852013-12-28 17:54:27467 FileIOMap::iterator file_it = files_.find(it->first);
468 if (file_it == files_.end())
469 continue;
470 int64_t trusted_max_written_offset =
471 file_it->second->max_written_offset();
[email protected]540d6af42014-01-28 21:19:03472 if (trusted_max_written_offset > it->second.max_written_offset) {
[email protected]7a90b852013-12-28 17:54:27473 audit_failed = true;
[email protected]540d6af42014-01-28 21:19:03474 it->second.max_written_offset = trusted_max_written_offset;
475 }
476 if (it->second.append_mode_write_amount < 0) {
477 audit_failed = true;
478 it->second.append_mode_write_amount = 0;
[email protected]7a90b852013-12-28 17:54:27479 }
480 }
481 if (audit_failed) {
482 new_msg_ptr->reset(
483 new PpapiHostMsg_ResourceCall(
484 params,
485 PpapiHostMsg_FileSystem_ReserveQuota(
[email protected]540d6af42014-01-28 21:19:03486 amount, file_growths)));
[email protected]7a90b852013-12-28 17:54:27487 }
488 break;
489 }
490 case PpapiHostMsg_ResourceDestroyed::ID: {
491 // Audit resource destroyed messages to release FileSystems.
492 PP_Resource resource;
493 if (!UnpackMessage<PpapiHostMsg_ResourceDestroyed>(
494 nested_msg, &resource))
495 return;
496 FileSystemMap::iterator fs_it = file_systems_.find(resource);
497 if (fs_it != file_systems_.end()) {
498 delete fs_it->second;
499 file_systems_.erase(fs_it);
500 }
[email protected]2d585cbd2014-06-03 02:13:22501 break;
[email protected]7a90b852013-12-28 17:54:27502 }
503 }
504 }
[email protected]c586216c2013-12-18 21:59:17505}
[email protected]6276b492013-11-02 13:38:31506
[email protected]7a90b852013-12-28 17:54:27507NaClMessageScanner::FileIO* NaClMessageScanner::GetFile(
508 PP_Resource file_io) {
509 FileIOMap::iterator it = files_.find(file_io);
510 DCHECK(it != files_.end());
511 return it->second;
512}
513
514void NaClMessageScanner::AuditNestedMessage(PP_Resource resource,
515 const IPC::Message& msg,
516 SerializedHandle* handle) {
517 switch (msg.type()) {
518 case PpapiPluginMsg_FileIO_OpenReply::ID: {
519 // A file that requires quota checking was opened.
520 PP_Resource quota_file_system;
521 int64_t max_written_offset = 0;
522 if (ppapi::UnpackMessage<PpapiPluginMsg_FileIO_OpenReply>(
523 msg, &quota_file_system, &max_written_offset)) {
524 if (quota_file_system) {
525 // Look up the FileSystem by inserting a new one. If it was already
526 // present, get the existing one, otherwise construct it.
527 FileSystem* file_system = NULL;
528 std::pair<FileSystemMap::iterator, bool> insert_result =
529 file_systems_.insert(std::make_pair(quota_file_system,
530 file_system));
531 if (insert_result.second)
532 insert_result.first->second = new FileSystem();
533 file_system = insert_result.first->second;
534 // Create the FileIO.
535 DCHECK(files_.find(resource) == files_.end());
536 files_.insert(std::make_pair(
537 resource,
538 new FileIO(file_system, max_written_offset)));
539 }
540 }
541 break;
542 }
543 case PpapiPluginMsg_FileSystem_ReserveQuotaReply::ID: {
544 // The amount of reserved quota for a FileSystem was refreshed.
545 int64_t amount = 0;
[email protected]540d6af42014-01-28 21:19:03546 FileSizeMap file_sizes;
[email protected]7a90b852013-12-28 17:54:27547 if (ppapi::UnpackMessage<PpapiPluginMsg_FileSystem_ReserveQuotaReply>(
[email protected]540d6af42014-01-28 21:19:03548 msg, &amount, &file_sizes)) {
[email protected]7a90b852013-12-28 17:54:27549 FileSystemMap::iterator it = file_systems_.find(resource);
550 DCHECK(it != file_systems_.end());
551 it->second->UpdateReservedQuota(amount);
552
[email protected]540d6af42014-01-28 21:19:03553 FileSizeMap::const_iterator offset_it = file_sizes.begin();
554 for (; offset_it != file_sizes.end(); ++offset_it) {
[email protected]7a90b852013-12-28 17:54:27555 FileIOMap::iterator fio_it = files_.find(offset_it->first);
556 DCHECK(fio_it != files_.end());
557 if (fio_it != files_.end())
558 fio_it->second->SetMaxWrittenOffset(offset_it->second);
559 }
560 }
561 break;
562 }
563 }
564}
565
[email protected]6276b492013-11-02 13:38:31566} // namespace proxy
567} // namespace ppapi