Debugging: Add code to print backtrace for guest on SIGSEGV
[nativeclient.git] / npapi_plugin / srpc / ret_array.cc
blob90c7b7688663fb6e651f70a20dae2fd5dd855236
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 #include <new>
34 #include <stdlib.h>
35 #include <string.h>
36 #include "native_client/npapi_plugin/srpc/npapi_native.h"
37 #include "native_client/npapi_plugin/srpc/plugin.h"
38 #include "native_client/npapi_plugin/srpc/ret_array.h"
39 #include "native_client/npapi_plugin/srpc/utility.h"
41 // TODO: this whole module should probably be replaced by
42 // a call to javascript eval to create an array object.
44 namespace nacl_srpc {
46 // Utility function to force to canonical integer NPIdentifiers.
47 static bool IsIntegerIdentifier(NPIdentifier ident);
48 static NPIdentifier ForceToIntegerIdent(NPIdentifier ident);
50 // Class variable definitions.
51 int RetArray::number_alive = 0;
53 // RetArray defines no methods.
54 bool RetArray::HasMethod(NPObject *obj, NPIdentifier name) {
55 dprintf(("RetArray::HasMethod(%p, %s)\n", obj, IdentToString(name)));
57 return false;
60 bool RetArray::Invoke(NPObject *obj,
61 NPIdentifier name,
62 const NPVariant *args,
63 uint32_t arg_count,
64 NPVariant *result) {
65 dprintf(("RetArray::Invoke(%p, %s, %d)\n",
66 obj, IdentToString(name), arg_count));
68 VOID_TO_NPVARIANT(*result);
69 return false;
72 // RetArray defines a "length" property and one int property for
73 // each valid subscript [0..length-1].
74 bool RetArray::HasProperty(NPObject *obj, NPIdentifier name) {
75 RetArray* retarray = reinterpret_cast<RetArray*>(obj);
77 dprintf(("RetArray::HasProperty(%p, %s)\n", obj, IdentToString(name)));
79 if (Plugin::kLengthIdent == name) {
80 return true;
82 if (IsIntegerIdentifier(name)) {
83 name = ForceToIntegerIdent(name);
84 for (int i = 0; i < retarray->property_count_; ++i) {
85 if (name == retarray->properties_[i]) {
86 return true;
90 return false;
93 bool RetArray::GetProperty(NPObject *obj,
94 NPIdentifier name,
95 NPVariant *variant) {
96 RetArray* retarray = reinterpret_cast<RetArray*>(obj);
98 dprintf(("RetArray::GetProperty(%p, %s)\n", obj, IdentToString(name)));
100 VOID_TO_NPVARIANT(*variant);
101 if (Plugin::kLengthIdent == name) {
102 ScalarToNPVariant(retarray->property_count_, variant);
103 return true;
105 name = ForceToIntegerIdent(name);
106 for (int i = 0; i < retarray->property_count_; ++i) {
107 if (name == retarray->properties_[i]) {
108 char* ret_string;
109 NPObject* ret_property;
110 if (NPVariantToScalar(&retarray->values_[i], &ret_string)) {
111 ScalarToNPVariant(ret_string, variant);
112 // Free the temporary string used to copy the object.
113 free(ret_string);
114 } else if (NPVariantToScalar(&retarray->values_[i], &ret_property)) {
115 NPN_RetainObject(ret_property);
116 *variant = retarray->values_[i];
117 } else {
118 *variant = retarray->values_[i];
120 return true;
123 return false;
126 bool RetArray::SetProperty(NPObject *obj,
127 NPIdentifier name,
128 const NPVariant *variant) {
129 dprintf(("RetArray::SetProperty(%p, %s, %p)\n",
130 obj, IdentToString(name), variant));
132 return false;
135 RetArray* RetArray::New(Plugin* plugin, int property_count) {
136 dprintf(("RetArray::New(%p, %d)\n", plugin, property_count));
138 static NPClass retArrayClass = {
139 NP_CLASS_STRUCT_VERSION,
140 Allocate,
141 Deallocate,
142 Invalidate,
143 HasMethod,
144 Invoke,
146 HasProperty,
147 GetProperty,
148 SetProperty,
151 RetArray* retarray =
152 reinterpret_cast<RetArray*>(NPN_CreateObject(plugin->npp(),
153 &retArrayClass));
154 if (NULL == retarray) {
155 return NULL;
158 retarray->plugin_ = plugin;
159 retarray->property_count_ = property_count;
160 if (property_count > 0) {
161 // Allocate a vector of identifiers for integers [0,property_count).
162 retarray->properties_ = new(std::nothrow) NPIdentifier[property_count];
163 if (NULL == retarray->properties_) {
164 NPN_ReleaseObject(retarray);
165 return NULL;
167 // Allocate a vector for the values mapped to.
168 retarray->values_ = new(std::nothrow) NPVariant[property_count];
169 if (NULL == retarray->values_) {
170 delete[] retarray->properties_;
171 NPN_ReleaseObject(retarray);
172 return NULL;
174 for (int i = 0; i < property_count; ++i) {
175 retarray->properties_[i] = NPN_GetIntIdentifier(i);
176 // VOID represents JavaScript's undefined.
177 VOID_TO_NPVARIANT(retarray->values_[i]);
179 } else {
180 retarray->properties_ = NULL;
181 retarray->values_ = NULL;
184 return retarray;
187 NPObject *RetArray::Allocate(NPP npp, NPClass *theClass) {
188 dprintf(("RetArray::Allocate(%d)\n", ++number_alive));
190 return new(std::nothrow) RetArray(npp);
193 void RetArray::Deallocate(NPObject *obj) {
194 RetArray* retarray = reinterpret_cast<RetArray*>(obj);
196 dprintf(("RetArray::Deallocate(%p, %d)\n", obj, --number_alive));
198 if (retarray->property_count_ > 0) {
199 for (int i = 0; i < retarray->property_count_; ++i) {
200 dprintf(("Deallocate(%p): releasing %d -- \n", retarray, i));
201 NPN_ReleaseVariantValue(&retarray->values_[i]);
203 delete retarray->properties_;
204 delete retarray->values_;
206 delete reinterpret_cast<RetArray*>(obj);
209 void RetArray::Invalidate(NPObject *obj) {
210 RetArray* retarray = reinterpret_cast<RetArray*>(obj);
212 dprintf(("RetArray::Invalidate(%p)\n", obj));
214 // After invalidation, the browser does not respect reference counting,
215 // so we shut down here what we can and prevent attempts to shut down
216 // other linked structures in Deallocate.
218 if (retarray->property_count_ > 0) {
219 delete retarray->properties_;
220 retarray->properties_ = 0;
221 delete retarray->values_;
222 retarray->values_ = 0;
223 retarray->property_count_ = 0;
225 retarray->plugin_ = NULL;
228 RetArray::RetArray(NPP npp) : npp_(npp) {
229 dprintf(("RetArray::RetArray(%p)\n", this));
232 RetArray::~RetArray() {
233 dprintf(("RetArray::~RetArray(%p)\n", this));
236 // Force an identifier to a canonical integer NPIdentifier. This is
237 // needed because Safari likes to index by using character string names.
238 static bool IsIntegerIdentifier(NPIdentifier ident) {
239 if (NPN_IdentifierIsString(ident)) {
240 char* string = NPN_UTF8FromIdentifier(ident);
241 for (char* p = string; '\0' != *p; ++p) {
242 if (*p < '0' || *p > '9') {
243 return false;
246 return true;
247 } else {
248 return true;
252 static NPIdentifier ForceToIntegerIdent(NPIdentifier ident) {
253 if (NPN_IdentifierIsString(ident)) {
254 const char* str = NPN_UTF8FromIdentifier(ident);
255 int index = atoi(str);
256 return NPN_GetIntIdentifier(index);
257 } else {
258 return ident;
262 } // namespace nacl_srpc