Debugging: Add code to print backtrace for guest on SIGSEGV
[nativeclient.git] / tools / npapi_runtime / npobject_proxy.cc
blob6f8803f98a3682a3ae494c4fda02ca4f96247115
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/npbridge.h"
37 namespace {
39 NPObject* Alloc(NPP npp, NPClass* aClass) {
40 return nacl::NPObjectProxy::GetLastAllocated();
43 void Deallocate(NPObject* object) {
44 delete static_cast<nacl::NPObjectProxy*>(object);
47 // Invalidate is called after NPP_Destroy...
48 void Invalidate(NPObject* object) {
49 return static_cast<nacl::NPObjectProxy*>(object)->Invalidate();
52 bool HasMethod(NPObject* object, NPIdentifier name) {
53 return static_cast<nacl::NPObjectProxy*>(object)->HasMethod(name);
56 bool Invoke(NPObject* object, NPIdentifier name,
57 const NPVariant* args, uint32_t arg_count,
58 NPVariant* result) {
59 return static_cast<nacl::NPObjectProxy*>(object)->Invoke(
60 name, args, arg_count, result);
63 bool InvokeDefault(NPObject* object, const NPVariant* args, uint32_t arg_count,
64 NPVariant* result) {
65 return static_cast<nacl::NPObjectProxy*>(object)->InvokeDefault(
66 args, arg_count, result);
69 bool HasProperty(NPObject* object, NPIdentifier name) {
70 return static_cast<nacl::NPObjectProxy*>(object)->HasProperty(name);
73 bool GetProperty(NPObject* object, NPIdentifier name, NPVariant* result) {
74 return static_cast<nacl::NPObjectProxy*>(object)->GetProperty(name, result);
77 bool SetProperty(NPObject* object, NPIdentifier name, const NPVariant* value) {
78 return static_cast<nacl::NPObjectProxy*>(object)->SetProperty(name, value);
81 bool RemoveProperty(NPObject* object, NPIdentifier name) {
82 return static_cast<nacl::NPObjectProxy*>(object)->RemoveProperty(name);
85 bool Enumeration(NPObject* object, NPIdentifier* *value, uint32_t* count) {
86 return static_cast<nacl::NPObjectProxy*>(object)->Enumeration(value, count);
89 bool Construct(NPObject* object, const NPVariant* args, uint32_t arg_count,
90 NPVariant* result) {
91 return static_cast<nacl::NPObjectProxy*>(object)->Construct(args, arg_count,
92 result);
95 } // namespace
97 namespace nacl {
99 #if 1 <= NP_VERSION_MAJOR || 19 <= NP_VERSION_MINOR
101 NPClass NPObjectProxy::np_class = {
102 NP_CLASS_STRUCT_VERSION_CTOR,
103 ::Alloc,
104 ::Deallocate,
105 ::Invalidate,
106 ::HasMethod,
107 ::Invoke,
108 ::InvokeDefault,
109 ::HasProperty,
110 ::GetProperty,
111 ::SetProperty,
112 ::RemoveProperty,
113 ::Enumeration,
114 ::Construct
117 #else // 1 <= NP_VERSION_MAJOR || 19 <= NP_VERSION_MINOR
119 NPClass NPObjectProxy::np_class = {
120 NP_CLASS_STRUCT_VERSION,
121 ::Alloc,
122 ::Deallocate,
123 ::Invalidate,
124 ::HasMethod,
125 ::Invoke,
126 ::InvokeDefault,
127 ::HasProperty,
128 ::GetProperty,
129 ::SetProperty,
130 ::RemoveProperty
133 #endif // 1 <= NP_VERSION_MAJOR || 19 <= NP_VERSION_MINOR
135 NPObject* NPObjectProxy::last_allocated;
137 NPObjectProxy::NPObjectProxy(NPBridge* bridge, const NPCapability& capability)
138 : bridge_(bridge) {
139 capability_.CopyFrom(capability);
140 last_allocated = this;
141 NPN_CreateObject(bridge->npp(), &np_class);
144 NPObjectProxy::~NPObjectProxy() {
145 if (bridge_ == NULL) {
146 return;
148 RpcHeader request;
149 request.type = RPC_DEALLOCATE;
150 IOVec vecv[2];
151 IOVec* vecp = vecv;
152 vecp->base = &request;
153 vecp->length = sizeof request;
154 ++vecp;
155 vecp->base = &capability_;
156 vecp->length = sizeof capability_;
157 ++vecp;
158 int length;
159 bridge_->Request(&request, vecv, vecp - vecv, &length);
160 bridge_->RemoveProxy(this);
163 void NPObjectProxy::Invalidate() {
164 // Note Invalidate() can be called after NPP_Destroy() is called.
165 if (bridge_ == NULL) {
166 return;
168 RpcHeader request;
169 request.type = RPC_INVALIDATE;
170 IOVec vecv[2];
171 IOVec* vecp = vecv;
172 vecp->base = &request;
173 vecp->length = sizeof request;
174 ++vecp;
175 vecp->base = &capability_;
176 vecp->length = sizeof capability_;
177 ++vecp;
178 int length;
179 bridge_->Request(&request, vecv, vecp - vecv, &length);
182 bool NPObjectProxy::HasMethod(NPIdentifier name) {
183 RpcStack stack(bridge_);
184 if (stack.Push(name) == NULL) {
185 return false;
187 RpcHeader request;
188 request.type = RPC_HAS_METHOD;
189 IOVec vecv[4];
190 IOVec* vecp = vecv;
191 vecp->base = &request;
192 vecp->length = sizeof request;
193 ++vecp;
194 vecp->base = &capability_;
195 vecp->length = sizeof capability_;
196 ++vecp;
197 vecp->base = &name;
198 vecp->length = sizeof name;
199 ++vecp;
200 vecp = stack.SetIOVec(vecp);
201 int length;
202 RpcHeader* reply = bridge_->Request(&request, vecv, vecp - vecv, &length);
203 if (reply == NULL) {
204 return false;
206 return reply->error_code ? true : false;
209 bool NPObjectProxy::Invoke(NPIdentifier name,
210 const NPVariant* args, uint32_t arg_count,
211 NPVariant* variant) {
212 RpcStack stack(bridge_);
213 char converted_args[kNPVariantSizeMax * kParamMax];
214 // Avoid stack overflow if too many parameters are passed.
215 if (kParamMax < arg_count) {
216 return false;
218 if (bridge_->peer_npvariant_size() != sizeof(NPVariant)) {
219 ConvertNPVariants(args, converted_args,
220 bridge_->peer_npvariant_size(),
221 arg_count);
223 if (stack.Push(name) == NULL) {
224 return false;
226 for (uint32_t i = 0; i < arg_count; ++i) {
227 if (stack.Push(args[i], true) == NULL) {
228 return false;
231 RpcHeader request;
232 request.type = RPC_INVOKE;
233 request.error_code = arg_count;
234 IOVec vecv[5];
235 IOVec* vecp = vecv;
236 vecp->base = &request;
237 vecp->length = sizeof request;
238 ++vecp;
239 vecp->base = &capability_;
240 vecp->length = sizeof capability_;
241 ++vecp;
242 vecp->base = &name;
243 vecp->length = sizeof name;
244 ++vecp;
245 if (0 < arg_count) {
246 if (bridge_->peer_npvariant_size() == sizeof(NPVariant)) {
247 vecp->base = const_cast<NPVariant*>(args);
248 vecp->length = arg_count * sizeof(NPVariant);
249 } else {
250 vecp->base = converted_args;
251 vecp->length = arg_count * bridge_->peer_npvariant_size();
253 ++vecp;
255 vecp = stack.SetIOVec(vecp);
256 int length;
257 RpcHeader* reply = bridge_->Request(&request, vecv, vecp - vecv, &length);
258 if (reply == NULL) {
259 return false;
261 RpcArg result(bridge_, reply, length);
262 result.Step(sizeof(RpcHeader));
263 if (reply->error_code != false) {
264 result.StepOption(sizeof(NPVariant));
265 *variant = *result.GetVariant(false);
266 return true;
268 return false;
271 bool NPObjectProxy::InvokeDefault(const NPVariant* args, uint32_t arg_count,
272 NPVariant* variant) {
273 RpcStack stack(bridge_);
274 char converted_args[kNPVariantSizeMax * kParamMax];
275 // Avoid stack overflow if too many parameters are passed.
276 if (kParamMax < arg_count) {
277 return false;
279 if (bridge_->peer_npvariant_size() != sizeof(NPVariant)) {
280 ConvertNPVariants(args, converted_args,
281 bridge_->peer_npvariant_size(),
282 arg_count);
284 for (uint32_t i = 0; i < arg_count; ++i) {
285 if (stack.Push(args[i], true) == NULL) {
286 return false;
289 RpcHeader request;
290 request.type = RPC_INVOKE_DEFAULT;
291 request.error_code = arg_count;
292 IOVec vecv[4];
293 IOVec* vecp = vecv;
294 vecp->base = &request;
295 vecp->length = sizeof request;
296 ++vecp;
297 vecp->base = &capability_;
298 vecp->length = sizeof capability_;
299 ++vecp;
300 if (0 < arg_count) {
301 if (bridge_->peer_npvariant_size() == sizeof(NPVariant)) {
302 vecp->base = const_cast<NPVariant*>(args);
303 vecp->length = arg_count * sizeof(NPVariant);
304 } else {
305 vecp->base = converted_args;
306 vecp->length = arg_count * bridge_->peer_npvariant_size();
308 ++vecp;
310 vecp = stack.SetIOVec(vecp);
311 int length;
312 RpcHeader* reply = bridge_->Request(&request, vecv, vecp - vecv, &length);
313 if (reply == NULL) {
314 return false;
316 RpcArg result(bridge_, reply, length);
317 result.Step(sizeof(RpcHeader));
318 if (reply->error_code != false) {
319 result.StepOption(sizeof(NPVariant));
320 *variant = *result.GetVariant(false);
321 return true;
323 return false;
326 bool NPObjectProxy::HasProperty(NPIdentifier name) {
327 RpcStack stack(bridge_);
328 if (stack.Push(name) == NULL) {
329 return false;
331 RpcHeader request;
332 request.type = RPC_HAS_PROPERTY;
333 IOVec vecv[4];
334 IOVec* vecp = vecv;
335 vecp->base = &request;
336 vecp->length = sizeof request;
337 ++vecp;
338 vecp->base = &capability_;
339 vecp->length = sizeof capability_;
340 ++vecp;
341 vecp->base = &name;
342 vecp->length = sizeof name;
343 ++vecp;
344 vecp = stack.SetIOVec(vecp);
345 int length;
346 RpcHeader* reply = bridge_->Request(&request, vecv, vecp - vecv, &length);
347 if (reply == NULL) {
348 return false;
350 return reply->error_code ? true : false;
353 bool NPObjectProxy::GetProperty(NPIdentifier name, NPVariant* variant) {
354 RpcStack stack(bridge_);
355 if (stack.Push(name) == NULL) {
356 return false;
358 RpcHeader request;
359 request.type = RPC_GET_PROPERTY;
360 IOVec vecv[4];
361 IOVec* vecp = vecv;
362 vecp->base = &request;
363 vecp->length = sizeof request;
364 ++vecp;
365 vecp->base = &capability_;
366 vecp->length = sizeof capability_;
367 ++vecp;
368 vecp->base = &name;
369 vecp->length = sizeof name;
370 ++vecp;
371 vecp = stack.SetIOVec(vecp);
372 int length;
373 RpcHeader* reply = bridge_->Request(&request, vecv, vecp - vecv, &length);
374 if (reply == NULL) {
375 return false;
377 RpcArg result(bridge_, reply, length);
378 result.Step(sizeof(RpcHeader));
379 if (reply->error_code != false) {
380 result.StepOption(sizeof(NPVariant));
381 *variant = *result.GetVariant(false);
382 return true;
384 return false;
387 bool NPObjectProxy::SetProperty(NPIdentifier name, const NPVariant* value) {
388 RpcStack stack(bridge_);
389 char converted_value[kNPVariantSizeMax];
390 if (bridge_->peer_npvariant_size() != sizeof(NPVariant)) {
391 ConvertNPVariants(value, converted_value,
392 bridge_->peer_npvariant_size(),
395 if (stack.Push(name) == NULL) {
396 return false;
398 if (stack.Push(*value, true) == NULL) {
399 return false;
401 RpcHeader request;
402 request.type = RPC_SET_PROPERTY;
403 IOVec vecv[5];
404 IOVec* vecp = vecv;
405 vecp->base = &request;
406 vecp->length = sizeof request;
407 ++vecp;
408 vecp->base = &capability_;
409 vecp->length = sizeof capability_;
410 ++vecp;
411 vecp->base = &name;
412 vecp->length = sizeof name;
413 ++vecp;
414 if (bridge_->peer_npvariant_size() == sizeof(NPVariant)) {
415 vecp->base = const_cast<NPVariant*>(value);
416 vecp->length = sizeof(NPVariant);
417 } else {
418 vecp->base = converted_value;
419 vecp->length = bridge_->peer_npvariant_size();
421 ++vecp;
422 vecp = stack.SetIOVec(vecp);
423 int length;
424 RpcHeader* reply = bridge_->Request(&request, vecv, vecp - vecv, &length);
425 if (reply == NULL) {
426 return false;
428 return reply->error_code ? true : false;
431 bool NPObjectProxy::RemoveProperty(NPIdentifier name) {
432 RpcStack stack(bridge_);
433 if (stack.Push(name) == NULL) {
434 return false;
436 RpcHeader request;
437 request.type = RPC_REMOVE_PROPERTY;
438 IOVec vecv[4];
439 IOVec* vecp = vecv;
440 vecp->base = &request;
441 vecp->length = sizeof request;
442 ++vecp;
443 vecp->base = &capability_;
444 vecp->length = sizeof capability_;
445 ++vecp;
446 vecp->base = &name;
447 vecp->length = sizeof name;
448 ++vecp;
449 vecp = stack.SetIOVec(vecp);
450 int length;
451 RpcHeader* reply = bridge_->Request(&request, vecv, vecp - vecv, &length);
452 if (reply == NULL) {
453 return false;
455 return reply->error_code ? true : false;
458 bool NPObjectProxy::Enumeration(NPIdentifier* *value, uint32_t* count) {
459 return false;
462 bool NPObjectProxy::Construct(const NPVariant* args, uint32_t arg_count,
463 NPVariant* result) {
464 return false;
467 void NPObjectProxy::SetException(const NPUTF8* message) {
468 RpcHeader request;
469 request.type = RPC_SET_EXCEPTION;
470 IOVec vecv[3];
471 IOVec* vecp = vecv;
472 vecp->base = &request;
473 vecp->length = sizeof request;
474 ++vecp;
475 vecp->base = &capability_;
476 vecp->length = sizeof capability_;
477 ++vecp;
478 vecp->base = const_cast<NPUTF8*>(message);
479 vecp->length = strlen(message) + 1;
480 ++vecp;
481 bridge_->Request(&request, vecv, vecp - vecv, NULL);
484 int NPObjectProxy::SetException(RpcHeader* request, int len) {
485 RpcArg arg(bridge_, request, len);
486 arg.Step(sizeof(RpcHeader));
487 arg.Step(sizeof(NPCapability));
488 const NPUTF8* message = arg.GetString();
489 NPN_SetException(this, message ? message : "");
490 IOVec vecv[1];
491 IOVec* vecp = vecv;
492 vecp->base = request;
493 vecp->length = sizeof(RpcHeader);
494 ++vecp;
495 return bridge_->Respond(request, vecv, vecp - vecv);
498 } // namespace nacl