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.
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.
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
)));
60 bool RetArray::Invoke(NPObject
*obj
,
62 const NPVariant
*args
,
65 dprintf(("RetArray::Invoke(%p, %s, %d)\n",
66 obj
, IdentToString(name
), arg_count
));
68 VOID_TO_NPVARIANT(*result
);
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
) {
82 if (IsIntegerIdentifier(name
)) {
83 name
= ForceToIntegerIdent(name
);
84 for (int i
= 0; i
< retarray
->property_count_
; ++i
) {
85 if (name
== retarray
->properties_
[i
]) {
93 bool RetArray::GetProperty(NPObject
*obj
,
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
);
105 name
= ForceToIntegerIdent(name
);
106 for (int i
= 0; i
< retarray
->property_count_
; ++i
) {
107 if (name
== retarray
->properties_
[i
]) {
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.
114 } else if (NPVariantToScalar(&retarray
->values_
[i
], &ret_property
)) {
115 NPN_RetainObject(ret_property
);
116 *variant
= retarray
->values_
[i
];
118 *variant
= retarray
->values_
[i
];
126 bool RetArray::SetProperty(NPObject
*obj
,
128 const NPVariant
*variant
) {
129 dprintf(("RetArray::SetProperty(%p, %s, %p)\n",
130 obj
, IdentToString(name
), variant
));
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
,
152 reinterpret_cast<RetArray
*>(NPN_CreateObject(plugin
->npp(),
154 if (NULL
== retarray
) {
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
);
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
);
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
]);
180 retarray
->properties_
= NULL
;
181 retarray
->values_
= NULL
;
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') {
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
);
262 } // namespace nacl_srpc