• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2004, 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 "NP_jsobject.h"
31 
32 #include "PlatformString.h"
33 #include "StringSourceProvider.h"
34 #ifdef ANDROID_NPN_SETEXCEPTION
35 #include "c_runtime.h"
36 #endif  // ANDROID_NPN_SETEXCEPTION
37 #include "c_utility.h"
38 #include "c_instance.h"
39 #include "npruntime_impl.h"
40 #include "npruntime_priv.h"
41 #include "runtime_root.h"
42 #include <runtime/Error.h>
43 #include <runtime/JSGlobalObject.h>
44 #include <runtime/JSLock.h>
45 #include <runtime/PropertyNameArray.h>
46 #include <parser/SourceCode.h>
47 #include <runtime/Completion.h>
48 #include <runtime/Completion.h>
49 
50 using WebCore::String;
51 using WebCore::StringSourceProvider;
52 using namespace JSC;
53 using namespace JSC::Bindings;
54 
getListFromVariantArgs(ExecState * exec,const NPVariant * args,unsigned argCount,RootObject * rootObject,ArgList & aList)55 static void getListFromVariantArgs(ExecState* exec, const NPVariant* args, unsigned argCount, RootObject* rootObject, ArgList& aList)
56 {
57     for (unsigned i = 0; i < argCount; ++i)
58         aList.append(convertNPVariantToValue(exec, &args[i], rootObject));
59 }
60 
jsAllocate(NPP,NPClass *)61 static NPObject* jsAllocate(NPP, NPClass*)
62 {
63     return static_cast<NPObject*>(malloc(sizeof(JavaScriptObject)));
64 }
65 
jsDeallocate(NPObject * npObj)66 static void jsDeallocate(NPObject* npObj)
67 {
68     JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(npObj);
69 
70     if (obj->rootObject && obj->rootObject->isValid())
71         obj->rootObject->gcUnprotect(obj->imp);
72 
73     if (obj->rootObject)
74         obj->rootObject->deref();
75 
76     free(obj);
77 }
78 
79 static NPClass javascriptClass = { 1, jsAllocate, jsDeallocate, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
80 static NPClass noScriptClass = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
81 
82 NPClass* NPScriptObjectClass = &javascriptClass;
83 static NPClass* NPNoScriptObjectClass = &noScriptClass;
84 
_NPN_CreateScriptObject(NPP npp,JSObject * imp,PassRefPtr<RootObject> rootObject)85 NPObject* _NPN_CreateScriptObject(NPP npp, JSObject* imp, PassRefPtr<RootObject> rootObject)
86 {
87     JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(_NPN_CreateObject(npp, NPScriptObjectClass));
88 
89     obj->rootObject = rootObject.releaseRef();
90 
91     if (obj->rootObject)
92         obj->rootObject->gcProtect(imp);
93     obj->imp = imp;
94 
95     return reinterpret_cast<NPObject*>(obj);
96 }
97 
_NPN_CreateNoScriptObject(void)98 NPObject* _NPN_CreateNoScriptObject(void)
99 {
100     return _NPN_CreateObject(0, NPNoScriptObjectClass);
101 }
102 
_NPN_InvokeDefault(NPP,NPObject * o,const NPVariant * args,uint32_t argCount,NPVariant * result)103 bool _NPN_InvokeDefault(NPP, NPObject* o, const NPVariant* args, uint32_t argCount, NPVariant* result)
104 {
105     if (o->_class == NPScriptObjectClass) {
106         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
107 
108         VOID_TO_NPVARIANT(*result);
109 
110         // Lookup the function object.
111         RootObject* rootObject = obj->rootObject;
112         if (!rootObject || !rootObject->isValid())
113             return false;
114 
115         ExecState* exec = rootObject->globalObject()->globalExec();
116         JSLock lock(false);
117 
118         // Call the function object.
119         JSValuePtr function = obj->imp;
120         CallData callData;
121         CallType callType = function.getCallData(callData);
122         if (callType == CallTypeNone)
123             return false;
124 
125         ArgList argList;
126         getListFromVariantArgs(exec, args, argCount, rootObject, argList);
127         ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject();
128         globalObject->startTimeoutCheck();
129         JSValuePtr resultV = call(exec, function, callType, callData, function, argList);
130         globalObject->stopTimeoutCheck();
131 
132         // Convert and return the result of the function call.
133         convertValueToNPVariant(exec, resultV, result);
134         exec->clearException();
135         return true;
136     }
137 
138     if (o->_class->invokeDefault)
139         return o->_class->invokeDefault(o, args, argCount, result);
140     VOID_TO_NPVARIANT(*result);
141     return true;
142 }
143 
_NPN_Invoke(NPP npp,NPObject * o,NPIdentifier methodName,const NPVariant * args,uint32_t argCount,NPVariant * result)144 bool _NPN_Invoke(NPP npp, NPObject* o, NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result)
145 {
146     if (o->_class == NPScriptObjectClass) {
147         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
148 
149         PrivateIdentifier* i = static_cast<PrivateIdentifier*>(methodName);
150         if (!i->isString)
151             return false;
152 
153         // Special case the "eval" method.
154         if (methodName == _NPN_GetStringIdentifier("eval")) {
155             if (argCount != 1)
156                 return false;
157             if (args[0].type != NPVariantType_String)
158                 return false;
159             return _NPN_Evaluate(npp, o, const_cast<NPString*>(&args[0].value.stringValue), result);
160         }
161 
162         // Look up the function object.
163         RootObject* rootObject = obj->rootObject;
164         if (!rootObject || !rootObject->isValid())
165             return false;
166         ExecState* exec = rootObject->globalObject()->globalExec();
167         JSLock lock(false);
168         JSValuePtr function = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
169         CallData callData;
170         CallType callType = function.getCallData(callData);
171         if (callType == CallTypeNone)
172             return false;
173 
174         // Call the function object.
175         ArgList argList;
176         getListFromVariantArgs(exec, args, argCount, rootObject, argList);
177         ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject();
178         globalObject->startTimeoutCheck();
179         JSValuePtr resultV = call(exec, function, callType, callData, obj->imp, argList);
180         globalObject->stopTimeoutCheck();
181 
182         // Convert and return the result of the function call.
183         convertValueToNPVariant(exec, resultV, result);
184         exec->clearException();
185         return true;
186     }
187 
188     if (o->_class->invoke)
189         return o->_class->invoke(o, methodName, args, argCount, result);
190 
191     VOID_TO_NPVARIANT(*result);
192     return true;
193 }
194 
_NPN_Evaluate(NPP,NPObject * o,NPString * s,NPVariant * variant)195 bool _NPN_Evaluate(NPP, NPObject* o, NPString* s, NPVariant* variant)
196 {
197     if (o->_class == NPScriptObjectClass) {
198         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
199 
200         RootObject* rootObject = obj->rootObject;
201         if (!rootObject || !rootObject->isValid())
202             return false;
203 
204         ExecState* exec = rootObject->globalObject()->globalExec();
205         JSLock lock(false);
206         String scriptString = convertNPStringToUTF16(s);
207         ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject();
208         globalObject->startTimeoutCheck();
209         Completion completion = JSC::evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(scriptString));
210         globalObject->stopTimeoutCheck();
211         ComplType type = completion.complType();
212 
213         JSValuePtr result;
214         if (type == Normal) {
215             result = completion.value();
216             if (!result)
217                 result = jsUndefined();
218         } else
219             result = jsUndefined();
220 
221         convertValueToNPVariant(exec, result, variant);
222         exec->clearException();
223         return true;
224     }
225 
226     VOID_TO_NPVARIANT(*variant);
227     return false;
228 }
229 
_NPN_GetProperty(NPP,NPObject * o,NPIdentifier propertyName,NPVariant * variant)230 bool _NPN_GetProperty(NPP, NPObject* o, NPIdentifier propertyName, NPVariant* variant)
231 {
232     if (o->_class == NPScriptObjectClass) {
233         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
234 
235         RootObject* rootObject = obj->rootObject;
236         if (!rootObject || !rootObject->isValid())
237             return false;
238 
239         ExecState* exec = rootObject->globalObject()->globalExec();
240         PrivateIdentifier* i = static_cast<PrivateIdentifier*>(propertyName);
241 
242         JSLock lock(false);
243         JSValuePtr result;
244         if (i->isString)
245             result = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
246         else
247             result = obj->imp->get(exec, i->value.number);
248 
249         convertValueToNPVariant(exec, result, variant);
250         exec->clearException();
251         return true;
252     }
253 
254     if (o->_class->hasProperty && o->_class->getProperty) {
255         if (o->_class->hasProperty(o, propertyName))
256             return o->_class->getProperty(o, propertyName, variant);
257         return false;
258     }
259 
260     VOID_TO_NPVARIANT(*variant);
261     return false;
262 }
263 
_NPN_SetProperty(NPP,NPObject * o,NPIdentifier propertyName,const NPVariant * variant)264 bool _NPN_SetProperty(NPP, NPObject* o, NPIdentifier propertyName, const NPVariant* variant)
265 {
266     if (o->_class == NPScriptObjectClass) {
267         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
268 
269         RootObject* rootObject = obj->rootObject;
270         if (!rootObject || !rootObject->isValid())
271             return false;
272 
273         ExecState* exec = rootObject->globalObject()->globalExec();
274         JSLock lock(false);
275         PrivateIdentifier* i = static_cast<PrivateIdentifier*>(propertyName);
276 
277         if (i->isString) {
278             PutPropertySlot slot;
279             obj->imp->put(exec, identifierFromNPIdentifier(i->value.string), convertNPVariantToValue(exec, variant, rootObject), slot);
280         } else
281             obj->imp->put(exec, i->value.number, convertNPVariantToValue(exec, variant, rootObject));
282         exec->clearException();
283         return true;
284     }
285 
286     if (o->_class->setProperty)
287         return o->_class->setProperty(o, propertyName, variant);
288 
289     return false;
290 }
291 
_NPN_RemoveProperty(NPP,NPObject * o,NPIdentifier propertyName)292 bool _NPN_RemoveProperty(NPP, NPObject* o, NPIdentifier propertyName)
293 {
294     if (o->_class == NPScriptObjectClass) {
295         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
296 
297         RootObject* rootObject = obj->rootObject;
298         if (!rootObject || !rootObject->isValid())
299             return false;
300 
301         ExecState* exec = rootObject->globalObject()->globalExec();
302         PrivateIdentifier* i = static_cast<PrivateIdentifier*>(propertyName);
303         if (i->isString) {
304             if (!obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string))) {
305                 exec->clearException();
306                 return false;
307             }
308         } else {
309             if (!obj->imp->hasProperty(exec, i->value.number)) {
310                 exec->clearException();
311                 return false;
312             }
313         }
314 
315         JSLock lock(false);
316         if (i->isString)
317             obj->imp->deleteProperty(exec, identifierFromNPIdentifier(i->value.string));
318         else
319             obj->imp->deleteProperty(exec, i->value.number);
320 
321         exec->clearException();
322         return true;
323     }
324     return false;
325 }
326 
_NPN_HasProperty(NPP,NPObject * o,NPIdentifier propertyName)327 bool _NPN_HasProperty(NPP, NPObject* o, NPIdentifier propertyName)
328 {
329     if (o->_class == NPScriptObjectClass) {
330         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
331 
332         RootObject* rootObject = obj->rootObject;
333         if (!rootObject || !rootObject->isValid())
334             return false;
335 
336         ExecState* exec = rootObject->globalObject()->globalExec();
337         PrivateIdentifier* i = static_cast<PrivateIdentifier*>(propertyName);
338         JSLock lock(false);
339         if (i->isString) {
340             bool result = obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string));
341             exec->clearException();
342             return result;
343         }
344 
345         bool result = obj->imp->hasProperty(exec, i->value.number);
346         exec->clearException();
347         return result;
348     }
349 
350     if (o->_class->hasProperty)
351         return o->_class->hasProperty(o, propertyName);
352 
353     return false;
354 }
355 
_NPN_HasMethod(NPP,NPObject * o,NPIdentifier methodName)356 bool _NPN_HasMethod(NPP, NPObject* o, NPIdentifier methodName)
357 {
358     if (o->_class == NPScriptObjectClass) {
359         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
360 
361         PrivateIdentifier* i = static_cast<PrivateIdentifier*>(methodName);
362         if (!i->isString)
363             return false;
364 
365         RootObject* rootObject = obj->rootObject;
366         if (!rootObject || !rootObject->isValid())
367             return false;
368 
369         ExecState* exec = rootObject->globalObject()->globalExec();
370         JSLock lock(false);
371         JSValuePtr func = obj->imp->get(exec, identifierFromNPIdentifier(i->value.string));
372         exec->clearException();
373         return !func.isUndefined();
374     }
375 
376     if (o->_class->hasMethod)
377         return o->_class->hasMethod(o, methodName);
378 
379     return false;
380 }
381 
_NPN_SetException(NPObject * o,const NPUTF8 * message)382 void _NPN_SetException(NPObject* o, const NPUTF8* message)
383 {
384 #ifdef ANDROID_NPN_SETEXCEPTION
385     if (o->_class == NPScriptObjectClass) {
386         JSC::Bindings::SetGlobalException(message);
387     }
388 #else
389     // Ignorning the NPObject param is consistent with the Mozilla implementation.
390     UString exception(message);
391     CInstance::setGlobalException(exception);
392 #endif  // ANDROID_NPN_SETEXCEPTION
393 }
394 
_NPN_Enumerate(NPP,NPObject * o,NPIdentifier ** identifier,uint32_t * count)395 bool _NPN_Enumerate(NPP, NPObject* o, NPIdentifier** identifier, uint32_t* count)
396 {
397     if (o->_class == NPScriptObjectClass) {
398         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
399 
400         RootObject* rootObject = obj->rootObject;
401         if (!rootObject || !rootObject->isValid())
402             return false;
403 
404         ExecState* exec = rootObject->globalObject()->globalExec();
405         JSLock lock(false);
406         PropertyNameArray propertyNames(exec);
407 
408         obj->imp->getPropertyNames(exec, propertyNames);
409         unsigned size = static_cast<unsigned>(propertyNames.size());
410         // FIXME: This should really call NPN_MemAlloc but that's in WebKit
411         NPIdentifier* identifiers = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier) * size));
412 
413         for (unsigned i = 0; i < size; ++i)
414             identifiers[i] = _NPN_GetStringIdentifier(propertyNames[i].ustring().UTF8String().c_str());
415 
416         *identifier = identifiers;
417         *count = size;
418 
419         exec->clearException();
420         return true;
421     }
422 
423     if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(o->_class) && o->_class->enumerate)
424         return o->_class->enumerate(o, identifier, count);
425 
426     return false;
427 }
428 
_NPN_Construct(NPP,NPObject * o,const NPVariant * args,uint32_t argCount,NPVariant * result)429 bool _NPN_Construct(NPP, NPObject* o, const NPVariant* args, uint32_t argCount, NPVariant* result)
430 {
431     if (o->_class == NPScriptObjectClass) {
432         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o);
433 
434         VOID_TO_NPVARIANT(*result);
435 
436         // Lookup the constructor object.
437         RootObject* rootObject = obj->rootObject;
438         if (!rootObject || !rootObject->isValid())
439             return false;
440 
441         ExecState* exec = rootObject->globalObject()->globalExec();
442         JSLock lock(false);
443 
444         // Call the constructor object.
445         JSValuePtr constructor = obj->imp;
446         ConstructData constructData;
447         ConstructType constructType = constructor.getConstructData(constructData);
448         if (constructType == ConstructTypeNone)
449             return false;
450 
451         ArgList argList;
452         getListFromVariantArgs(exec, args, argCount, rootObject, argList);
453         ProtectedPtr<JSGlobalObject> globalObject = rootObject->globalObject();
454         globalObject->startTimeoutCheck();
455         JSValuePtr resultV = construct(exec, constructor, constructType, constructData, argList);
456         globalObject->stopTimeoutCheck();
457 
458         // Convert and return the result.
459         convertValueToNPVariant(exec, resultV, result);
460         exec->clearException();
461         return true;
462     }
463 
464     if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(o->_class) && o->_class->construct)
465         return o->_class->construct(o, args, argCount, result);
466 
467     return false;
468 }
469 
470 #endif // ENABLE(NETSCAPE_PLUGIN_API)
471