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