Merge branch 'upstream'
[nativeclient.git] / tools / npapi_runtime / npobject_stub.cc
blobab5d529a589c23ccb1bd4877e8149ff35b343a56
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
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
14 * distribution.
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"
39 namespace nacl {
41 NPObjectStub::NPObjectStub(NPBridge* bridge, NPObject* object)
42 : bridge_(bridge),
43 object_(object) {
44 NPN_RetainObject(object_);
47 NPObjectStub::~NPObjectStub() {
48 NPN_ReleaseObject(object_);
49 bridge_->RemoveStub(this);
52 int NPObjectStub::Dispatch(RpcHeader* request, int len) {
53 NPVariant variant;
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) {
61 case RPC_DEALLOCATE:
62 request->error_code = true;
63 break;
64 case RPC_INVALIDATE:
65 request->error_code = Invalidate(&arg);
66 break;
67 case RPC_HAS_METHOD:
68 request->error_code = HasMethod(&arg);
69 break;
70 case RPC_INVOKE:
71 return_variant = true;
72 request->error_code = Invoke(request->error_code, &arg, &variant);
73 break;
74 case RPC_INVOKE_DEFAULT:
75 return_variant = true;
76 request->error_code = InvokeDefault(request->error_code, &arg, &variant);
77 break;
78 case RPC_HAS_PROPERTY:
79 request->error_code = HasProperty(&arg);
80 break;
81 case RPC_GET_PROPERTY:
82 return_variant = true;
83 request->error_code = GetProperty(&arg, &variant);
84 break;
85 case RPC_SET_PROPERTY:
86 request->error_code = SetProperty(&arg);
87 break;
88 case RPC_REMOVE_PROPERTY:
89 request->error_code = RemoveProperty(&arg);
90 break;
91 case RPC_ENUMERATION:
92 request->error_code = Enumeration(&arg);
93 break;
94 case RPC_CONSTRUCT:
95 return_variant = true;
96 request->error_code = Construct(request->error_code, &arg, &variant);
97 break;
98 default:
99 return -1;
101 IOVec vecv[3];
102 IOVec* vecp = vecv;
103 vecp->base = request;
104 vecp->length = sizeof(RpcHeader);
105 ++vecp;
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);
115 } else {
116 ConvertNPVariants(&variant, converted_variant,
117 bridge_->peer_npvariant_size(),
119 vecp->base = converted_variant;
120 vecp->length = bridge_->peer_npvariant_size();
122 ++vecp;
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) {
135 delete this;
137 return length;
140 bool NPObjectStub::Invalidate(RpcArg* arg) {
141 if (object_->_class && object_->_class->invalidate) {
142 object_->_class->invalidate(object_);
143 object_->referenceCount = 1;
145 return true;
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;
159 if (0 < arg_count) {
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);
173 return return_value;
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;
180 if (0 < arg_count) {
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);
194 return return_value;
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);
218 return return_value;
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) {
228 return false;
231 bool NPObjectStub::Construct(uint32_t arg_count, RpcArg* arg,
232 NPVariant* variant) {
233 return false;
236 void NPObjectStub::SetException(const NPUTF8* message) {
237 RpcHeader request;
238 request.type = RPC_SET_EXCEPTION;
239 IOVec vecv[3];
240 IOVec* vecp = vecv;
241 vecp->base = &request;
242 vecp->length = sizeof request;
243 ++vecp;
244 NPCapability capability = { GetPID(), object_ };
245 vecp->base = &capability;
246 vecp->length = sizeof capability;
247 ++vecp;
248 vecp->base = const_cast<NPUTF8*>(message);
249 vecp->length = strlen(message) + 1;
250 ++vecp;
251 bridge_->Request(&request, vecv, vecp - vecv, NULL);
254 } // namespace nacl