1 /*
2 * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "config.h"
27
28 #if ENABLE(NETSCAPE_PLUGIN_API)
29
30 #include "c_instance.h"
31
32 #include "c_class.h"
33 #include "c_runtime.h"
34 #include "c_utility.h"
35 #include "IdentifierRep.h"
36 #include "npruntime_impl.h"
37 #include "runtime_root.h"
38 #include <runtime/ArgList.h>
39 #include <runtime/Error.h>
40 #include <interpreter/CallFrame.h>
41 #include <runtime/JSLock.h>
42 #include <runtime/JSNumberCell.h>
43 #include <runtime/PropertyNameArray.h>
44 #include <wtf/Assertions.h>
45 #include <wtf/StdLibExtras.h>
46 #include <wtf/StringExtras.h>
47 #include <wtf/Vector.h>
48
49 using namespace WebCore;
50
51 namespace JSC {
52 namespace Bindings {
53
54 using JSC::UString;
55
globalExceptionString()56 static JSC::UString& globalExceptionString()
57 {
58 DEFINE_STATIC_LOCAL(JSC::UString, exceptionStr, ());
59 return exceptionStr;
60 }
61
setGlobalException(UString exception)62 void CInstance::setGlobalException(UString exception)
63 {
64 globalExceptionString() = exception;
65 }
66
moveGlobalExceptionToExecState(ExecState * exec)67 void CInstance::moveGlobalExceptionToExecState(ExecState* exec)
68 {
69 if (globalExceptionString().isNull())
70 return;
71
72 {
73 JSLock lock(SilenceAssertionsOnly);
74 throwError(exec, GeneralError, globalExceptionString());
75 }
76
77 globalExceptionString() = UString();
78 }
79
CInstance(NPObject * o,PassRefPtr<RootObject> rootObject)80 CInstance::CInstance(NPObject* o, PassRefPtr<RootObject> rootObject)
81 : Instance(rootObject)
82 {
83 _object = _NPN_RetainObject(o);
84 _class = 0;
85 }
86
~CInstance()87 CInstance::~CInstance()
88 {
89 _NPN_ReleaseObject(_object);
90 }
91
getClass() const92 Class *CInstance::getClass() const
93 {
94 if (!_class)
95 _class = CClass::classForIsA(_object->_class);
96 return _class;
97 }
98
supportsInvokeDefaultMethod() const99 bool CInstance::supportsInvokeDefaultMethod() const
100 {
101 return _object->_class->invokeDefault;
102 }
103
invokeMethod(ExecState * exec,const MethodList & methodList,const ArgList & args)104 JSValue CInstance::invokeMethod(ExecState* exec, const MethodList& methodList, const ArgList& args)
105 {
106 // Overloading methods are not allowed by NPObjects. Should only be one
107 // name match for a particular method.
108 ASSERT(methodList.size() == 1);
109
110 CMethod* method = static_cast<CMethod*>(methodList[0]);
111
112 NPIdentifier ident = method->identifier();
113 if (!_object->_class->hasMethod(_object, ident))
114 return jsUndefined();
115
116 unsigned count = args.size();
117 Vector<NPVariant, 8> cArgs(count);
118
119 unsigned i;
120 for (i = 0; i < count; i++)
121 convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
122
123 // Invoke the 'C' method.
124 #ifdef ANDROID_NPN_SETEXCEPTION
125 SetGlobalException(0);
126 #endif
127 NPVariant resultVariant;
128 VOID_TO_NPVARIANT(resultVariant);
129
130 {
131 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
132 ASSERT(globalExceptionString().isNull());
133 _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant);
134 moveGlobalExceptionToExecState(exec);
135 }
136
137 for (i = 0; i < count; i++)
138 _NPN_ReleaseVariantValue(&cArgs[i]);
139
140 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
141 _NPN_ReleaseVariantValue(&resultVariant);
142 #ifdef ANDROID_NPN_SETEXCEPTION
143 MoveGlobalExceptionToExecState(exec);
144 #endif
145 return resultValue;
146 }
147
148
invokeDefaultMethod(ExecState * exec,const ArgList & args)149 JSValue CInstance::invokeDefaultMethod(ExecState* exec, const ArgList& args)
150 {
151 if (!_object->_class->invokeDefault)
152 return jsUndefined();
153
154 unsigned count = args.size();
155 Vector<NPVariant, 8> cArgs(count);
156
157 unsigned i;
158 for (i = 0; i < count; i++)
159 convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
160
161 // Invoke the 'C' method.
162 #ifdef ANDROID_NPN_SETEXCEPTION
163 SetGlobalException(0);
164 #endif
165 NPVariant resultVariant;
166 VOID_TO_NPVARIANT(resultVariant);
167 {
168 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
169 ASSERT(globalExceptionString().isNull());
170 _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant);
171 moveGlobalExceptionToExecState(exec);
172 }
173
174 for (i = 0; i < count; i++)
175 _NPN_ReleaseVariantValue(&cArgs[i]);
176
177 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
178 _NPN_ReleaseVariantValue(&resultVariant);
179 #ifdef ANDROID_NPN_SETEXCEPTION
180 MoveGlobalExceptionToExecState(exec);
181 #endif
182 return resultValue;
183 }
184
supportsConstruct() const185 bool CInstance::supportsConstruct() const
186 {
187 return _object->_class->construct;
188 }
189
invokeConstruct(ExecState * exec,const ArgList & args)190 JSValue CInstance::invokeConstruct(ExecState* exec, const ArgList& args)
191 {
192 if (!_object->_class->construct)
193 return jsUndefined();
194
195 unsigned count = args.size();
196 Vector<NPVariant, 8> cArgs(count);
197
198 unsigned i;
199 for (i = 0; i < count; i++)
200 convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
201
202 // Invoke the 'C' method.
203 NPVariant resultVariant;
204 VOID_TO_NPVARIANT(resultVariant);
205 {
206 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
207 ASSERT(globalExceptionString().isNull());
208 _object->_class->construct(_object, cArgs.data(), count, &resultVariant);
209 moveGlobalExceptionToExecState(exec);
210 }
211
212 for (i = 0; i < count; i++)
213 _NPN_ReleaseVariantValue(&cArgs[i]);
214
215 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
216 _NPN_ReleaseVariantValue(&resultVariant);
217 return resultValue;
218 }
219
defaultValue(ExecState * exec,PreferredPrimitiveType hint) const220 JSValue CInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
221 {
222 if (hint == PreferString)
223 return stringValue(exec);
224 if (hint == PreferNumber)
225 return numberValue(exec);
226 return valueOf(exec);
227 }
228
stringValue(ExecState * exec) const229 JSValue CInstance::stringValue(ExecState* exec) const
230 {
231 char buf[1024];
232 snprintf(buf, sizeof(buf), "NPObject %p, NPClass %p", _object, _object->_class);
233 return jsString(exec, buf);
234 }
235
numberValue(ExecState * exec) const236 JSValue CInstance::numberValue(ExecState* exec) const
237 {
238 // FIXME: Implement something sensible.
239 return jsNumber(exec, 0);
240 }
241
booleanValue() const242 JSValue CInstance::booleanValue() const
243 {
244 // FIXME: Implement something sensible.
245 return jsBoolean(false);
246 }
247
valueOf(ExecState * exec) const248 JSValue CInstance::valueOf(ExecState* exec) const
249 {
250 return stringValue(exec);
251 }
252
getPropertyNames(ExecState * exec,PropertyNameArray & nameArray)253 void CInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray)
254 {
255 if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) || !_object->_class->enumerate)
256 return;
257
258 uint32_t count;
259 NPIdentifier* identifiers;
260
261 {
262 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
263 ASSERT(globalExceptionString().isNull());
264 bool ok = _object->_class->enumerate(_object, &identifiers, &count);
265 moveGlobalExceptionToExecState(exec);
266 if (!ok)
267 return;
268 }
269
270 for (uint32_t i = 0; i < count; i++) {
271 IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]);
272
273 if (identifier->isString())
274 nameArray.add(identifierFromNPIdentifier(identifier->string()));
275 else
276 nameArray.add(Identifier::from(exec, identifier->number()));
277 }
278
279 // FIXME: This should really call NPN_MemFree but that's in WebKit
280 free(identifiers);
281 }
282
283 }
284 }
285
286 #endif // ENABLE(NETSCAPE_PLUGIN_API)
287