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/nacl_util.h"
37 #include "native_client/tools/npapi_runtime/npbridge.h"
41 NPObjectStub::NPObjectStub(NPBridge
* bridge
, NPObject
* object
)
44 NPN_RetainObject(object_
);
47 NPObjectStub::~NPObjectStub() {
48 NPN_ReleaseObject(object_
);
49 bridge_
->RemoveStub(this);
52 int NPObjectStub::Dispatch(RpcHeader
* request
, int len
) {
54 bool return_variant
= false;
56 RpcArg
arg(bridge_
, request
, len
);
57 arg
.Step(sizeof(RpcHeader
));
58 arg
.Step(sizeof(NPCapability
));
60 switch (request
->type
) {
62 request
->error_code
= true;
65 request
->error_code
= Invalidate(&arg
);
68 request
->error_code
= HasMethod(&arg
);
71 return_variant
= true;
72 request
->error_code
= Invoke(request
->error_code
, &arg
, &variant
);
74 case RPC_INVOKE_DEFAULT
:
75 return_variant
= true;
76 request
->error_code
= InvokeDefault(request
->error_code
, &arg
, &variant
);
78 case RPC_HAS_PROPERTY
:
79 request
->error_code
= HasProperty(&arg
);
81 case RPC_GET_PROPERTY
:
82 return_variant
= true;
83 request
->error_code
= GetProperty(&arg
, &variant
);
85 case RPC_SET_PROPERTY
:
86 request
->error_code
= SetProperty(&arg
);
88 case RPC_REMOVE_PROPERTY
:
89 request
->error_code
= RemoveProperty(&arg
);
92 request
->error_code
= Enumeration(&arg
);
95 return_variant
= true;
96 request
->error_code
= Construct(request
->error_code
, &arg
, &variant
);
103 vecp
->base
= request
;
104 vecp
->length
= sizeof(RpcHeader
);
107 arg
.CloseUnusedHandles();
109 RpcStack
stack(bridge_
);
110 char converted_variant
[kNPVariantSizeMax
];
111 if (request
->error_code
!= false && return_variant
) {
112 if (bridge_
->peer_npvariant_size() == sizeof(NPVariant
)) {
113 vecp
->base
= &variant
;
114 vecp
->length
= sizeof(variant
);
116 ConvertNPVariants(&variant
, converted_variant
,
117 bridge_
->peer_npvariant_size(),
119 vecp
->base
= converted_variant
;
120 vecp
->length
= bridge_
->peer_npvariant_size();
123 stack
.Push(variant
, false);
124 vecp
= stack
.SetIOVec(vecp
);
126 int length
= bridge_
->Respond(request
, vecv
, vecp
- vecv
);
127 if (request
->error_code
!= false && return_variant
&&
128 NPVARIANT_IS_STRING(variant
)) {
129 // We cannot call NPN_ReleaseVariantValue() before bridge_->Respond()
130 // completes since NPN_ReleaseVariantValue() changes the variant type to
131 // NPVariantType_Void.
132 NPN_ReleaseVariantValue(&variant
);
134 if (request
->type
== RPC_DEALLOCATE
) {
140 bool NPObjectStub::Invalidate(RpcArg
* arg
) {
141 if (object_
->_class
&& object_
->_class
->invalidate
) {
142 object_
->_class
->invalidate(object_
);
143 object_
->referenceCount
= 1;
148 bool NPObjectStub::HasMethod(RpcArg
* arg
) {
149 arg
->StepOption(sizeof(NPIdentifier
));
150 NPIdentifier name
= arg
->GetIdentifier();
151 return NPN_HasMethod(bridge_
->npp(), object_
, name
);
154 bool NPObjectStub::Invoke(uint32_t arg_count
, RpcArg
* arg
,
155 NPVariant
* variant
) {
156 arg
->StepOption(sizeof(NPIdentifier
) + arg_count
* sizeof(NPVariant
));
157 NPIdentifier name
= arg
->GetIdentifier();
158 const NPVariant
* args
= NULL
;
160 args
= arg
->GetVariant(true);
161 for (uint32_t i
= 1; i
< arg_count
; ++i
) {
162 arg
->GetVariant(true);
165 bool return_value
= NPN_Invoke(bridge_
->npp(), object_
, name
,
166 args
, arg_count
, variant
);
167 for (uint32_t i
= 0; i
< arg_count
; ++i
) {
168 if (NPVARIANT_IS_OBJECT(args
[i
])) {
169 NPObject
* object
= NPVARIANT_TO_OBJECT(args
[i
]);
170 NPN_ReleaseObject(object
);
176 bool NPObjectStub::InvokeDefault(uint32_t arg_count
, RpcArg
* arg
,
177 NPVariant
* variant
) {
178 arg
->StepOption(arg_count
* sizeof(NPVariant
));
179 const NPVariant
* args
= NULL
;
181 args
= arg
->GetVariant(true);
182 for (uint32_t i
= 1; i
< arg_count
; ++i
) {
183 arg
->GetVariant(true);
186 bool return_value
= NPN_InvokeDefault(bridge_
->npp(), object_
,
187 args
, arg_count
, variant
);
188 for (uint32_t i
= 0; i
< arg_count
; ++i
) {
189 if (NPVARIANT_IS_OBJECT(args
[i
])) {
190 NPObject
* object
= NPVARIANT_TO_OBJECT(args
[i
]);
191 NPN_ReleaseObject(object
);
197 bool NPObjectStub::HasProperty(RpcArg
* arg
) {
198 arg
->StepOption(sizeof(NPIdentifier
));
199 NPIdentifier name
= arg
->GetIdentifier();
200 return NPN_HasProperty(bridge_
->npp(), object_
, name
);
203 bool NPObjectStub::GetProperty(RpcArg
* arg
, NPVariant
* variant
) {
204 arg
->StepOption(sizeof(NPIdentifier
));
205 NPIdentifier name
= arg
->GetIdentifier();
206 return NPN_GetProperty(bridge_
->npp(), object_
, name
, variant
);
209 bool NPObjectStub::SetProperty(RpcArg
* arg
) {
210 arg
->StepOption(sizeof(NPIdentifier
) + sizeof(NPVariant
));
211 NPIdentifier name
= arg
->GetIdentifier();
212 const NPVariant
* variant
= arg
->GetVariant(true);
213 bool return_value
= NPN_SetProperty(bridge_
->npp(), object_
, name
, variant
);
214 if (NPVARIANT_IS_OBJECT(*variant
)) {
215 NPObject
* object
= NPVARIANT_TO_OBJECT(*variant
);
216 NPN_ReleaseObject(object
);
221 bool NPObjectStub::RemoveProperty(RpcArg
* arg
) {
222 arg
->StepOption(sizeof(NPIdentifier
));
223 NPIdentifier name
= arg
->GetIdentifier();
224 return NPN_RemoveProperty(bridge_
->npp(), object_
, name
);
227 bool NPObjectStub::Enumeration(RpcArg
* arg
) {
231 bool NPObjectStub::Construct(uint32_t arg_count
, RpcArg
* arg
,
232 NPVariant
* variant
) {
236 void NPObjectStub::SetException(const NPUTF8
* message
) {
238 request
.type
= RPC_SET_EXCEPTION
;
241 vecp
->base
= &request
;
242 vecp
->length
= sizeof request
;
244 NPCapability capability
= { GetPID(), object_
};
245 vecp
->base
= &capability
;
246 vecp
->length
= sizeof capability
;
248 vecp
->base
= const_cast<NPUTF8
*>(message
);
249 vecp
->length
= strlen(message
) + 1;
251 bridge_
->Request(&request
, vecv
, vecp
- vecv
, NULL
);