• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ppb_buffer_proxy.h"
6 
7 #include <vector>
8 
9 #include "base/logging.h"
10 #include "build/build_config.h"
11 #include "ppapi/c/pp_completion_callback.h"
12 #include "ppapi/c/pp_errors.h"
13 #include "ppapi/c/pp_resource.h"
14 #include "ppapi/c/dev/ppb_buffer_dev.h"
15 #include "ppapi/proxy/host_dispatcher.h"
16 #include "ppapi/proxy/plugin_dispatcher.h"
17 #include "ppapi/proxy/ppapi_messages.h"
18 #include "ppapi/thunk/enter.h"
19 #include "ppapi/thunk/resource_creation_api.h"
20 #include "ppapi/thunk/thunk.h"
21 
22 namespace ppapi {
23 namespace proxy {
24 
Buffer(const HostResource & resource,const base::SharedMemoryHandle & shm_handle,uint32_t size)25 Buffer::Buffer(const HostResource& resource,
26                const base::SharedMemoryHandle& shm_handle,
27                uint32_t size)
28     : Resource(OBJECT_IS_PROXY, resource),
29       shm_(shm_handle, false),
30       size_(size),
31       map_count_(0) {
32 }
33 
~Buffer()34 Buffer::~Buffer() {
35   Unmap();
36 }
37 
AsPPB_Buffer_API()38 thunk::PPB_Buffer_API* Buffer::AsPPB_Buffer_API() {
39   return this;
40 }
41 
Describe(uint32_t * size_in_bytes)42 PP_Bool Buffer::Describe(uint32_t* size_in_bytes) {
43   *size_in_bytes = size_;
44   return PP_TRUE;
45 }
46 
IsMapped()47 PP_Bool Buffer::IsMapped() {
48   return PP_FromBool(map_count_ > 0);
49 }
50 
Map()51 void* Buffer::Map() {
52   if (map_count_++ == 0)
53     shm_.Map(size_);
54   return shm_.memory();
55 }
56 
Unmap()57 void Buffer::Unmap() {
58   if (--map_count_ == 0)
59     shm_.Unmap();
60 }
61 
GetSharedMemory(int * out_handle)62 int32_t Buffer::GetSharedMemory(int* out_handle) {
63   NOTREACHED();
64   return PP_ERROR_NOTSUPPORTED;
65 }
66 
PPB_Buffer_Proxy(Dispatcher * dispatcher)67 PPB_Buffer_Proxy::PPB_Buffer_Proxy(Dispatcher* dispatcher)
68     : InterfaceProxy(dispatcher) {
69 }
70 
~PPB_Buffer_Proxy()71 PPB_Buffer_Proxy::~PPB_Buffer_Proxy() {
72 }
73 
74 // static
CreateProxyResource(PP_Instance instance,uint32_t size)75 PP_Resource PPB_Buffer_Proxy::CreateProxyResource(PP_Instance instance,
76                                                   uint32_t size) {
77   PluginDispatcher* dispatcher = PluginDispatcher::GetForInstance(instance);
78   if (!dispatcher)
79     return 0;
80 
81   HostResource result;
82   ppapi::proxy::SerializedHandle shm_handle;
83   dispatcher->Send(new PpapiHostMsg_PPBBuffer_Create(
84       API_ID_PPB_BUFFER, instance, size, &result, &shm_handle));
85   if (result.is_null() || !shm_handle.IsHandleValid() ||
86       !shm_handle.is_shmem())
87     return 0;
88 
89   return AddProxyResource(result, shm_handle.shmem(), size);
90 }
91 
92 // static
AddProxyResource(const HostResource & resource,base::SharedMemoryHandle shm_handle,uint32_t size)93 PP_Resource PPB_Buffer_Proxy::AddProxyResource(
94     const HostResource& resource,
95     base::SharedMemoryHandle shm_handle,
96     uint32_t size) {
97   return (new Buffer(resource, shm_handle, size))->GetReference();
98 }
99 
OnMessageReceived(const IPC::Message & msg)100 bool PPB_Buffer_Proxy::OnMessageReceived(const IPC::Message& msg) {
101   bool handled = true;
102   IPC_BEGIN_MESSAGE_MAP(PPB_Buffer_Proxy, msg)
103     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBBuffer_Create, OnMsgCreate)
104     IPC_MESSAGE_UNHANDLED(handled = false)
105   IPC_END_MESSAGE_MAP()
106   // TODO(brettw) handle bad messages!
107   return handled;
108 }
109 
OnMsgCreate(PP_Instance instance,uint32_t size,HostResource * result_resource,ppapi::proxy::SerializedHandle * result_shm_handle)110 void PPB_Buffer_Proxy::OnMsgCreate(
111     PP_Instance instance,
112     uint32_t size,
113     HostResource* result_resource,
114     ppapi::proxy::SerializedHandle* result_shm_handle) {
115   // Overwritten below on success.
116   result_shm_handle->set_null_shmem();
117   HostDispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
118   if (!dispatcher)
119     return;
120   if (!dispatcher->permissions().HasPermission(ppapi::PERMISSION_DEV))
121     return;
122 
123   thunk::EnterResourceCreation enter(instance);
124   if (enter.failed())
125     return;
126   PP_Resource local_buffer_resource = enter.functions()->CreateBuffer(instance,
127                                                                       size);
128   if (local_buffer_resource == 0)
129     return;
130 
131   thunk::EnterResourceNoLock<thunk::PPB_Buffer_API> trusted_buffer(
132       local_buffer_resource, false);
133   if (trusted_buffer.failed())
134     return;
135   int local_fd;
136   if (trusted_buffer.object()->GetSharedMemory(&local_fd) != PP_OK)
137     return;
138 
139   result_resource->SetHostResource(instance, local_buffer_resource);
140 
141   // TODO(piman/brettw): Change trusted interface to return a PP_FileHandle,
142   // those casts are ugly.
143   base::PlatformFile platform_file =
144 #if defined(OS_WIN)
145       reinterpret_cast<HANDLE>(static_cast<intptr_t>(local_fd));
146 #elif defined(OS_POSIX)
147       local_fd;
148 #else
149   #error Not implemented.
150 #endif
151   result_shm_handle->set_shmem(
152       dispatcher->ShareHandleWithRemote(platform_file, false), size);
153 }
154 
155 }  // namespace proxy
156 }  // namespace ppapi
157