2 * Copyright 2008, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // NaCl-NPAPI Interface
35 #include "native_client/tools/npapi_runtime/npbridge.h"
43 #include "native_client/tools/npapi_runtime/nacl_npapi.h"
44 #include "native_client/tools/npapi_runtime/nacl_util.h"
48 NPBridge::NPBridge(NPP npp
)
51 peer_npvariant_size_(0), // Must be set later
52 channel_(kInvalidHtpHandle
),
56 is_webkit_(false) { // TBD
60 NPBridge::~NPBridge() {
61 while (!stub_map_
.empty()) {
62 std::map
<NPObject
*, NPObjectStub
*>::iterator i
= stub_map_
.begin();
63 NPObjectStub
* stub
= (*i
).second
;
69 // Note proxy objects are deleted by Navigator.
70 for (std::map
<const NPCapability
, NPObjectProxy
*>::iterator i
=
72 i
!= proxy_map_
.end();
74 NPObjectProxy
* proxy
= (*i
).second
;
79 NPObjectStub
* NPBridge::LookupStub(NPObject
* object
) {
81 std::map
<NPObject
*, NPObjectStub
*>::iterator i
;
82 i
= stub_map_
.find(object
);
83 if (i
!= stub_map_
.end()) {
89 NPObjectProxy
* NPBridge::LookupProxy(const NPCapability
& capability
) {
90 if (capability
.object
== NULL
) {
93 if (capability
.pid
== GetPID()) {
96 std::map
<const NPCapability
, NPObjectProxy
*>::iterator i
;
97 i
= proxy_map_
.find(capability
);
98 if (i
!= proxy_map_
.end()) {
104 int NPBridge::CreateStub(NPObject
* object
, NPCapability
* cap
) {
105 NPObjectStub
* stub
= NULL
;
106 if (object
!= NULL
) {
107 if (NPObjectProxy::IsInstance(object
)) { // object can be a proxy
108 NPObjectProxy
* proxy
= static_cast<NPObjectProxy
*>(object
);
109 if (proxy
->capability().pid
== peer_pid()) {
110 *cap
= proxy
->capability();
114 stub
= LookupStub(object
);
117 cap
->object
= object
;
120 stub
= new(std::nothrow
) NPObjectStub(this, object
);
127 stub_map_
[object
] = stub
;
128 cap
->object
= object
;
132 NPObject
* NPBridge::CreateProxy(const NPCapability
& capability
) {
133 if (capability
.object
== NULL
) {
136 if (capability
.pid
== GetPID()) { // capability can be of my process
137 std::map
<NPObject
*, NPObjectStub
*>::iterator i
;
138 i
= stub_map_
.find(capability
.object
);
139 if (i
== stub_map_
.end()) {
142 NPN_RetainObject(capability
.object
);
143 return capability
.object
;
146 std::map
<const NPCapability
, NPObjectProxy
*>::iterator i
;
147 i
= proxy_map_
.find(capability
);
148 if (i
!= proxy_map_
.end()) {
149 NPObjectProxy
* proxy
= (*i
).second
;
150 NPN_RetainObject(proxy
);
153 NPObjectProxy
* proxy
= new(std::nothrow
) NPObjectProxy(this, capability
);
161 void NPBridge::AddProxy(NPObjectProxy
* proxy
) {
162 proxy_map_
[proxy
->capability()] = proxy
;
165 void NPBridge::RemoveProxy(NPObjectProxy
* proxy
) {
166 proxy_map_
.erase(proxy
->capability());
169 NPObjectStub
* NPBridge::GetStub(const NPCapability
& capability
) {
170 if (capability
.pid
!= GetPID()) {
173 std::map
<NPObject
*, NPObjectStub
*>::iterator i
;
174 i
= stub_map_
.find(capability
.object
);
175 if (i
== stub_map_
.end()) {
181 void NPBridge::RemoveStub(NPObjectStub
* stub
) {
182 stub_map_
.erase(stub
->object());
185 RpcHeader
* NPBridge::Request(RpcHeader
* request
, IOVec
* iov
, size_t iov_length
,
187 if (channel_
== kInvalidHtpHandle
) {
190 assert(iov
[0].base
== request
);
191 request
->tag
= ++tag_
;
192 request
->pid
= GetPID();
196 message
.iov_length
= iov_length
;
197 message
.handles
= handles_
;
198 message
.handle_count
= handle_count_
;
199 if (SendDatagram(channel_
, &message
, 0) <
200 static_cast<int>(sizeof(RpcHeader
))) {
201 clear_handle_count();
204 return Wait(request
, length
);
207 RpcHeader
* NPBridge::Wait(const RpcHeader
* request
, int* length
) {
208 RpcHeader
* header
= static_cast<RpcHeader
*>(top());
213 vec
.length
= GetFreeSize();
215 message
.iov_length
= 1;
216 message
.handles
= handles_
;
217 message
.handle_count
= kHandleCountMax
;
218 clear_handle_count();
220 waiting_since_
= time(NULL
);
221 int result
= ReceiveDatagram(channel_
, &message
, 0);
225 channel_
= kInvalidHtpHandle
;
228 if (result
< static_cast<int>(sizeof(RpcHeader
))) {
229 for (size_t i
= 0; i
< message
.handle_count
; ++i
) {
233 channel_
= kInvalidHtpHandle
;
236 handle_count_
= message
.handle_count
;
237 if (request
&& header
->Equals(*request
)) {
238 // Received the response for the request.
244 RpcStack
stack(this);
246 result
= Dispatch(header
, result
);
248 // Send back a truncated header to indicate failure.
249 clear_handle_count();
251 const_cast<RpcHeader
*>(request
),
252 offsetof(RpcHeader
, error_code
)
254 Respond(request
, &iov
, 1);
256 if (header
->type
== RPC_DESTROY
) {
262 int NPBridge::Dispatch(RpcHeader
* request
, int len
) {
263 RpcArg
arg(this, request
, len
);
264 if (len
< static_cast<int>(sizeof(RpcHeader
) + sizeof(NPCapability
))) {
267 arg
.Step(sizeof(RpcHeader
));
268 const NPCapability
* capability
= arg
.GetCapability();
271 switch (request
->type
) {
272 case RPC_SET_EXCEPTION
: {
273 NPObjectStub
* stub
= GetStub(*capability
);
275 return stub
->Dispatch(request
, len
);
277 NPObjectProxy
* proxy
= LookupProxy(*capability
);
279 return proxy
->SetException(request
, len
);
287 case RPC_INVOKE_DEFAULT
:
288 case RPC_HAS_PROPERTY
:
289 case RPC_GET_PROPERTY
:
290 case RPC_SET_PROPERTY
:
291 case RPC_REMOVE_PROPERTY
:
292 case RPC_ENUMERATION
:
293 case RPC_CONSTRUCT
: {
294 NPObjectStub
* stub
= GetStub(*capability
);
296 return stub
->Dispatch(request
, len
);
306 int NPBridge::Respond(const RpcHeader
* reply
, IOVec
* iov
, size_t iov_length
) {
307 assert(1 <= iov_length
);
308 assert(channel_
!= kInvalidHtpHandle
);
309 assert(iov
[0].base
== reply
);
313 message
.iov_length
= iov_length
;
314 message
.handles
= handles_
;
315 message
.handle_count
= handle_count_
;
316 return SendDatagram(channel_
, &message
, 0);