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.
35 #include "native_client/npapi_plugin/srpc/plugin.h"
36 #include "native_client/npapi_plugin/srpc/ret_array.h"
37 #include "native_client/npapi_plugin/srpc/utility.h"
39 // TODO: this whole module should probably be replaced by
40 // a call to javascript eval to create an array object.
44 // Utility function to force to canonical integer NPIdentifiers.
45 static bool IsIntegerIdentifier(NPIdentifier ident
);
46 static NPIdentifier
ForceToIntegerIdent(NPIdentifier ident
);
48 // Class variable definitions.
49 int RetArray::number_alive
= 0;
51 // RetArray defines no methods.
52 bool RetArray::HasMethod(NPObject
*obj
, NPIdentifier name
) {
53 dprintf(("RetArray::HasMethod(%p, %s)\n", obj
, IdentToString(name
)));
58 bool RetArray::Invoke(NPObject
*obj
,
60 const NPVariant
*args
,
63 dprintf(("RetArray::Invoke(%p, %s, %d)\n",
64 obj
, IdentToString(name
), arg_count
));
69 // RetArray defines a "length" property and one int property for
70 // each valid subscript [0..length-1].
71 bool RetArray::HasProperty(NPObject
*obj
, NPIdentifier name
) {
72 RetArray
* retarray
= reinterpret_cast<RetArray
*>(obj
);
74 dprintf(("RetArray::HasProperty(%p, %s)\n", obj
, IdentToString(name
)));
76 if (Plugin::kLengthIdent
== name
) {
79 if (IsIntegerIdentifier(name
)) {
80 name
= ForceToIntegerIdent(name
);
81 for (int i
= 0; i
< retarray
->property_count_
; ++i
) {
82 if (name
== retarray
->properties_
[i
]) {
90 bool RetArray::GetProperty(NPObject
*obj
,
93 RetArray
* retarray
= reinterpret_cast<RetArray
*>(obj
);
95 dprintf(("RetArray::GetProperty(%p, %s)\n", obj
, IdentToString(name
)));
97 if (Plugin::kLengthIdent
== name
) {
98 INT32_TO_NPVARIANT(retarray
->property_count_
, *variant
);
101 name
= ForceToIntegerIdent(name
);
102 for (int i
= 0; i
< retarray
->property_count_
; ++i
) {
103 if (name
== retarray
->properties_
[i
]) {
104 if (NPVARIANT_IS_STRING(retarray
->values_
[i
])) {
105 NPString value_string
= NPVARIANT_TO_STRING(retarray
->values_
[i
]);
107 reinterpret_cast<char*>(NPN_MemAlloc(value_string
.utf8length
));
108 memcpy(retstring
, value_string
.utf8characters
, value_string
.utf8length
);
109 STRINGN_TO_NPVARIANT(retstring
, value_string
.utf8length
, *variant
);
110 } else if (NPVARIANT_IS_OBJECT(retarray
->values_
[i
])) {
111 NPObject
* prop
= NPVARIANT_TO_OBJECT(retarray
->values_
[i
]);
112 NPN_RetainObject(prop
);
113 *variant
= retarray
->values_
[i
];
115 *variant
= retarray
->values_
[i
];
123 bool RetArray::SetProperty(NPObject
*obj
,
125 const NPVariant
*variant
) {
126 dprintf(("RetArray::SetProperty(%p, %s, %p)\n",
127 obj
, IdentToString(name
), variant
));
132 RetArray
* RetArray::New(Plugin
* plugin
, int property_count
) {
133 dprintf(("RetArray::New(%p, %d)\n", plugin
, property_count
));
135 static NPClass retArrayClass
= {
136 NP_CLASS_STRUCT_VERSION
,
149 reinterpret_cast<RetArray
*>(NPN_CreateObject(plugin
->npp(),
152 retarray
->plugin_
= plugin
;
153 retarray
->property_count_
= property_count
;
154 if (property_count
> 0) {
155 // Allocate a vector of identifiers for integers [0,property_count).
156 retarray
->properties_
= new NPIdentifier
[property_count
];
157 // Allocate a vector for the values mapped to.
158 retarray
->values_
= new NPVariant
[property_count
];
159 for (int i
= 0; i
< property_count
; ++i
) {
160 retarray
->properties_
[i
] = NPN_GetIntIdentifier(i
);
161 // VOID represents JavaScript's undefined.
162 VOID_TO_NPVARIANT(retarray
->values_
[i
]);
165 retarray
->properties_
= NULL
;
166 retarray
->values_
= NULL
;
172 NPObject
*RetArray::Allocate(NPP npp
, NPClass
*theClass
) {
173 dprintf(("RetArray::Allocate(%d)\n", ++number_alive
));
175 return new RetArray(npp
);
178 void RetArray::Deallocate(NPObject
*obj
) {
179 RetArray
* retarray
= reinterpret_cast<RetArray
*>(obj
);
181 dprintf(("RetArray::Deallocate(%p, %d)\n", obj
, --number_alive
));
183 if (retarray
->property_count_
> 0) {
184 for (int i
= 0; i
< retarray
->property_count_
; ++i
) {
185 dprintf(("Deallocate(%p): releasing %d -- \n", retarray
, i
));
186 NPN_ReleaseVariantValue(&retarray
->values_
[i
]);
188 delete retarray
->properties_
;
189 delete retarray
->values_
;
191 delete reinterpret_cast<RetArray
*>(obj
);
194 void RetArray::Invalidate(NPObject
*obj
) {
195 RetArray
* retarray
= reinterpret_cast<RetArray
*>(obj
);
197 dprintf(("RetArray::Invalidate(%p)\n", obj
));
199 // After invalidation, the browser does not respect reference counting,
200 // so we shut down here what we can and prevent attempts to shut down
201 // other linked structures in Deallocate.
203 if (retarray
->property_count_
> 0) {
204 delete retarray
->properties_
;
205 retarray
->properties_
= 0;
206 delete retarray
->values_
;
207 retarray
->values_
= 0;
208 retarray
->property_count_
= 0;
210 retarray
->plugin_
= NULL
;
213 RetArray::RetArray(NPP npp
) : npp_(npp
) {
214 dprintf(("RetArray::RetArray(%p)\n", this));
217 RetArray::~RetArray() {
218 dprintf(("RetArray::~RetArray(%p)\n", this));
221 // Force an identifier to a canonical integer NPIdentifier. This is
222 // needed because Safari likes to index by using character string names.
223 static bool IsIntegerIdentifier(NPIdentifier ident
) {
224 if (NPN_IdentifierIsString(ident
)) {
225 char* string
= NPN_UTF8FromIdentifier(ident
);
226 for (char* p
= string
; '\0' != *p
; ++p
) {
227 if (*p
< '0' || *p
> '9') {
237 static NPIdentifier
ForceToIntegerIdent(NPIdentifier ident
) {
238 if (NPN_IdentifierIsString(ident
)) {
239 const char* str
= NPN_UTF8FromIdentifier(ident
);
240 int index
= atoi(str
);
241 return NPN_GetIntIdentifier(index
);
247 } // namespace nacl_srpc