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 bool retval = true;
125 NPVariant resultVariant;
126 VOID_TO_NPVARIANT(resultVariant);
127
128 {
129 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
130 ASSERT(globalExceptionString().isNull());
131 retval = _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant);
132 moveGlobalExceptionToExecState(exec);
133 }
134
135 if (!retval)
136 throwError(exec, GeneralError, "Error calling method on NPObject!");
137
138 for (i = 0; i < count; i++)
139 _NPN_ReleaseVariantValue(&cArgs[i]);
140
141 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
142 _NPN_ReleaseVariantValue(&resultVariant);
143 return resultValue;
144 }
145
146
invokeDefaultMethod(ExecState * exec,const ArgList & args)147 JSValue CInstance::invokeDefaultMethod(ExecState* exec, const ArgList& args)
148 {
149 if (!_object->_class->invokeDefault)
150 return jsUndefined();
151
152 unsigned count = args.size();
153 Vector<NPVariant, 8> cArgs(count);
154
155 unsigned i;
156 for (i = 0; i < count; i++)
157 convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
158
159 // Invoke the 'C' method.
160 bool retval = true;
161 NPVariant resultVariant;
162 VOID_TO_NPVARIANT(resultVariant);
163 {
164 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
165 ASSERT(globalExceptionString().isNull());
166 retval = _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant);
167 moveGlobalExceptionToExecState(exec);
168 }
169
170 if (!retval)
171 throwError(exec, GeneralError, "Error calling method on NPObject!");
172
173 for (i = 0; i < count; i++)
174 _NPN_ReleaseVariantValue(&cArgs[i]);
175
176 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_rootObject.get());
177 _NPN_ReleaseVariantValue(&resultVariant);
178 return resultValue;
179 }
180
supportsConstruct() const181 bool CInstance::supportsConstruct() const
182 {
183 return _object->_class->construct;
184 }
185
invokeConstruct(ExecState * exec,const ArgList & args)186 JSValue CInstance::invokeConstruct(ExecState* exec, const ArgList& args)
187 {
188 if (!_object->_class->construct)
189 return jsUndefined();
190
191 unsigned count = args.size();
192 Vector<NPVariant, 8> cArgs(count);
193
194 unsigned i;
195 for (i = 0; i < count; i++)
196 convertValueToNPVariant(exec, args.at(i), &cArgs[i]);
197
198 // Invoke the 'C' method.
199 bool retval = true;
200 NPVariant resultVariant;
201 VOID_TO_NPVARIANT(resultVariant);
202 {
203 JSLock::DropAllLocks dropAllLocks(SilenceAssertionsOnly);
204 ASSERT(globalExceptionString().isNull());
205 retval = _object->_class->construct(_object, cArgs.data(), count, &resultVariant);
206 moveGlobalExceptionToExecState(exec);
207 }
208
209 if (!retval)
210 throwError(exec, GeneralError, "Error calling method on NPObject!");
211
212 for (i = 0; i < count; i++)
213 _NPN_ReleaseVariantValue(&cArgs[i]);
214
215 JSValue resultValue = convertNPVariantToValue(exec, &resultVariant, m_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