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/plugin_array_buffer_var.h"
6
7 #include <stdlib.h>
8
9 #include <limits>
10
11 #include "base/memory/shared_memory.h"
12 #include "ppapi/c/dev/ppb_buffer_dev.h"
13 #include "ppapi/proxy/plugin_dispatcher.h"
14 #include "ppapi/proxy/plugin_globals.h"
15 #include "ppapi/proxy/ppapi_messages.h"
16 #include "ppapi/proxy/serialized_structs.h"
17 #include "ppapi/shared_impl/host_resource.h"
18 #include "ppapi/shared_impl/resource.h"
19 #include "ppapi/thunk/enter.h"
20 #include "ppapi/thunk/ppb_buffer_api.h"
21
22 using base::SharedMemory;
23 using base::SharedMemoryHandle;
24 using ppapi::proxy::PluginGlobals;
25 using ppapi::proxy::PluginResourceTracker;
26
27 namespace ppapi {
28
PluginArrayBufferVar(uint32 size_in_bytes)29 PluginArrayBufferVar::PluginArrayBufferVar(uint32 size_in_bytes)
30 : buffer_(size_in_bytes),
31 plugin_handle_(base::SharedMemory::NULLHandle()),
32 size_in_bytes_(size_in_bytes) {
33 }
34
PluginArrayBufferVar(uint32 size_in_bytes,SharedMemoryHandle plugin_handle)35 PluginArrayBufferVar::PluginArrayBufferVar(uint32 size_in_bytes,
36 SharedMemoryHandle plugin_handle)
37 : plugin_handle_(plugin_handle),
38 size_in_bytes_(size_in_bytes) {
39 }
40
~PluginArrayBufferVar()41 PluginArrayBufferVar::~PluginArrayBufferVar() {
42 Unmap();
43
44 if (shmem_.get() == NULL) {
45 // The SharedMemory destuctor can't close the handle for us.
46 if (SharedMemory::IsHandleValid(plugin_handle_))
47 SharedMemory::CloseHandle(plugin_handle_);
48 } else {
49 // Delete SharedMemory, if we have one.
50 shmem_.reset();
51 }
52 }
53
Map()54 void* PluginArrayBufferVar::Map() {
55 if (shmem_.get())
56 return shmem_->memory();
57 if (SharedMemory::IsHandleValid(plugin_handle_)) {
58 shmem_.reset(new SharedMemory(plugin_handle_, false));
59 if (!shmem_->Map(size_in_bytes_)) {
60 shmem_.reset();
61 return NULL;
62 }
63 return shmem_->memory();
64 }
65 if (buffer_.empty())
66 return NULL;
67 return &(buffer_[0]);
68 }
69
Unmap()70 void PluginArrayBufferVar::Unmap() {
71 if (shmem_.get())
72 shmem_->Unmap();
73 }
74
ByteLength()75 uint32 PluginArrayBufferVar::ByteLength() {
76 return size_in_bytes_;
77 }
78
CopyToNewShmem(PP_Instance instance,int * host_handle_id,SharedMemoryHandle * plugin_out_handle)79 bool PluginArrayBufferVar::CopyToNewShmem(
80 PP_Instance instance,
81 int* host_handle_id,
82 SharedMemoryHandle* plugin_out_handle) {
83 ppapi::proxy::PluginDispatcher* dispatcher =
84 ppapi::proxy::PluginDispatcher::GetForInstance(instance);
85 if (!dispatcher)
86 return false;
87
88 ppapi::proxy::SerializedHandle plugin_handle;
89 dispatcher->Send(new PpapiHostMsg_SharedMemory_CreateSharedMemory(
90 instance, ByteLength(), host_handle_id, &plugin_handle));
91 if (!plugin_handle.IsHandleValid() || !plugin_handle.is_shmem() ||
92 *host_handle_id == -1)
93 return false;
94
95 base::SharedMemoryHandle tmp_handle = plugin_handle.shmem();
96 SharedMemory s(tmp_handle, false);
97 if (!s.Map(ByteLength()))
98 return false;
99 memcpy(s.memory(), Map(), ByteLength());
100 s.Unmap();
101
102 // We don't need to keep the shared memory around on the plugin side;
103 // we've already copied all our data into it. We'll make it invalid
104 // just to be safe.
105 *plugin_out_handle = base::SharedMemory::NULLHandle();
106
107 return true;
108 }
109
110 } // namespace ppapi
111