• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Apple 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 INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "NPJSObject.h"
28 
29 #include "JSNPObject.h"
30 #include "NPRuntimeObjectMap.h"
31 #include "NPRuntimeUtilities.h"
32 #include "PluginView.h"
33 #include <JavaScriptCore/JSLock.h>
34 #include <JavaScriptCore/JSObject.h>
35 #include <WebCore/Frame.h>
36 #include <WebCore/IdentifierRep.h>
37 #include <WebCore/NotImplemented.h>
38 #include <wtf/text/WTFString.h>
39 
40 using namespace JSC;
41 using namespace WebCore;
42 
43 namespace WebKit {
44 
create(JSGlobalData & globalData,NPRuntimeObjectMap * objectMap,JSObject * jsObject)45 NPJSObject* NPJSObject::create(JSGlobalData& globalData, NPRuntimeObjectMap* objectMap, JSObject* jsObject)
46 {
47     // We should never have a JSNPObject inside an NPJSObject.
48     ASSERT(!jsObject->inherits(&JSNPObject::s_info));
49 
50     NPJSObject* npJSObject = toNPJSObject(createNPObject(0, npClass()));
51     npJSObject->initialize(globalData, objectMap, jsObject);
52 
53     return npJSObject;
54 }
55 
NPJSObject()56 NPJSObject::NPJSObject()
57     : m_objectMap(0)
58 {
59 }
60 
~NPJSObject()61 NPJSObject::~NPJSObject()
62 {
63     m_objectMap->npJSObjectDestroyed(this);
64 }
65 
isNPJSObject(NPObject * npObject)66 bool NPJSObject::isNPJSObject(NPObject* npObject)
67 {
68     return npObject->_class == npClass();
69 }
70 
initialize(JSGlobalData & globalData,NPRuntimeObjectMap * objectMap,JSObject * jsObject)71 void NPJSObject::initialize(JSGlobalData& globalData, NPRuntimeObjectMap* objectMap, JSObject* jsObject)
72 {
73     ASSERT(!m_objectMap);
74     ASSERT(!m_jsObject);
75 
76     m_objectMap = objectMap;
77     m_jsObject.set(globalData, jsObject);
78 }
79 
identifierFromIdentifierRep(ExecState * exec,IdentifierRep * identifierRep)80 static Identifier identifierFromIdentifierRep(ExecState* exec, IdentifierRep* identifierRep)
81 {
82     ASSERT(identifierRep->isString());
83 
84     const char* string = identifierRep->string();
85     int length = strlen(string);
86 
87     return Identifier(exec, String::fromUTF8WithLatin1Fallback(string, length).impl());
88 }
89 
hasMethod(NPIdentifier methodName)90 bool NPJSObject::hasMethod(NPIdentifier methodName)
91 {
92     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(methodName);
93 
94     if (!identifierRep->isString())
95         return false;
96 
97     ExecState* exec = m_objectMap->globalExec();
98     if (!exec)
99         return false;
100 
101     JSLock lock(SilenceAssertionsOnly);
102 
103     JSValue value = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep));
104     exec->clearException();
105 
106     CallData callData;
107     return getCallData(value, callData) != CallTypeNone;
108 }
109 
invoke(NPIdentifier methodName,const NPVariant * arguments,uint32_t argumentCount,NPVariant * result)110 bool NPJSObject::invoke(NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
111 {
112     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(methodName);
113 
114     if (!identifierRep->isString())
115         return false;
116 
117     ExecState* exec = m_objectMap->globalExec();
118     if (!exec)
119         return false;
120 
121     JSLock lock(SilenceAssertionsOnly);
122 
123     JSValue function = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep));
124     return invoke(exec, m_objectMap->globalObject(), function, arguments, argumentCount, result);
125 }
126 
invokeDefault(const NPVariant * arguments,uint32_t argumentCount,NPVariant * result)127 bool NPJSObject::invokeDefault(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
128 {
129     ExecState* exec = m_objectMap->globalExec();
130     if (!exec)
131         return false;
132 
133     JSLock lock(SilenceAssertionsOnly);
134 
135     JSValue function = m_jsObject.get();
136     return invoke(exec, m_objectMap->globalObject(), function, arguments, argumentCount, result);
137 }
138 
hasProperty(NPIdentifier identifier)139 bool NPJSObject::hasProperty(NPIdentifier identifier)
140 {
141     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(identifier);
142 
143     ExecState* exec = m_objectMap->globalExec();
144     if (!exec)
145         return false;
146 
147     JSLock lock(SilenceAssertionsOnly);
148 
149     bool result;
150     if (identifierRep->isString())
151         result = m_jsObject->hasProperty(exec, identifierFromIdentifierRep(exec, identifierRep));
152     else
153         result = m_jsObject->hasProperty(exec, identifierRep->number());
154 
155     exec->clearException();
156     return result;
157 }
158 
getProperty(NPIdentifier propertyName,NPVariant * result)159 bool NPJSObject::getProperty(NPIdentifier propertyName, NPVariant* result)
160 {
161     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName);
162 
163     ExecState* exec = m_objectMap->globalExec();
164     if (!exec)
165         return false;
166 
167     JSLock lock(SilenceAssertionsOnly);
168     JSValue jsResult;
169     if (identifierRep->isString())
170         jsResult = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep));
171     else
172         jsResult = m_jsObject->get(exec, identifierRep->number());
173 
174     m_objectMap->convertJSValueToNPVariant(exec, jsResult, *result);
175     exec->clearException();
176     return true;
177 }
178 
setProperty(NPIdentifier propertyName,const NPVariant * value)179 bool NPJSObject::setProperty(NPIdentifier propertyName, const NPVariant* value)
180 {
181     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName);
182 
183     ExecState* exec = m_objectMap->globalExec();
184     if (!exec)
185         return false;
186 
187     JSLock lock(SilenceAssertionsOnly);
188 
189     JSValue jsValue = m_objectMap->convertNPVariantToJSValue(exec, m_objectMap->globalObject(), *value);
190     if (identifierRep->isString()) {
191         PutPropertySlot slot;
192         m_jsObject->put(exec, identifierFromIdentifierRep(exec, identifierRep), jsValue, slot);
193     } else
194         m_jsObject->put(exec, identifierRep->number(), jsValue);
195     exec->clearException();
196 
197     return true;
198 }
199 
removeProperty(NPIdentifier propertyName)200 bool NPJSObject::removeProperty(NPIdentifier propertyName)
201 {
202     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName);
203 
204     ExecState* exec = m_objectMap->globalExec();
205     if (!exec)
206         return false;
207 
208     JSLock lock(SilenceAssertionsOnly);
209     if (identifierRep->isString()) {
210         Identifier identifier = identifierFromIdentifierRep(exec, identifierRep);
211 
212         if (!m_jsObject->hasProperty(exec, identifier)) {
213             exec->clearException();
214             return false;
215         }
216 
217         m_jsObject->deleteProperty(exec, identifier);
218     } else {
219         if (!m_jsObject->hasProperty(exec, identifierRep->number())) {
220             exec->clearException();
221             return false;
222         }
223 
224         m_jsObject->deleteProperty(exec, identifierRep->number());
225     }
226 
227     exec->clearException();
228     return true;
229 }
230 
enumerate(NPIdentifier ** identifiers,uint32_t * identifierCount)231 bool NPJSObject::enumerate(NPIdentifier** identifiers, uint32_t* identifierCount)
232 {
233     ExecState* exec = m_objectMap->globalExec();
234     if (!exec)
235         return false;
236 
237     JSLock lock(SilenceAssertionsOnly);
238 
239     PropertyNameArray propertyNames(exec);
240     m_jsObject->getPropertyNames(exec, propertyNames);
241 
242     NPIdentifier* nameIdentifiers = npnMemNewArray<NPIdentifier>(propertyNames.size());
243 
244     for (size_t i = 0; i < propertyNames.size(); ++i)
245         nameIdentifiers[i] = static_cast<NPIdentifier>(IdentifierRep::get(propertyNames[i].ustring().utf8().data()));
246 
247     *identifiers = nameIdentifiers;
248     *identifierCount = propertyNames.size();
249 
250     return true;
251 }
252 
construct(const NPVariant * arguments,uint32_t argumentCount,NPVariant * result)253 bool NPJSObject::construct(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
254 {
255     ExecState* exec = m_objectMap->globalExec();
256     if (!exec)
257         return false;
258 
259     JSLock lock(SilenceAssertionsOnly);
260 
261     ConstructData constructData;
262     ConstructType constructType = getConstructData(m_jsObject.get(), constructData);
263     if (constructType == ConstructTypeNone)
264         return false;
265 
266     // Convert the passed in arguments.
267     MarkedArgumentBuffer argumentList;
268     for (uint32_t i = 0; i < argumentCount; ++i)
269         argumentList.append(m_objectMap->convertNPVariantToJSValue(exec, m_objectMap->globalObject(), arguments[i]));
270 
271     exec->globalData().timeoutChecker.start();
272     JSValue value = JSC::construct(exec, m_jsObject.get(), constructType, constructData, argumentList);
273     exec->globalData().timeoutChecker.stop();
274 
275     // Convert and return the new object.
276     m_objectMap->convertJSValueToNPVariant(exec, value, *result);
277     exec->clearException();
278 
279     return true;
280 }
281 
invoke(ExecState * exec,JSGlobalObject * globalObject,JSValue function,const NPVariant * arguments,uint32_t argumentCount,NPVariant * result)282 bool NPJSObject::invoke(ExecState* exec, JSGlobalObject* globalObject, JSValue function, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
283 {
284     CallData callData;
285     CallType callType = getCallData(function, callData);
286     if (callType == CallTypeNone)
287         return false;
288 
289     // Convert the passed in arguments.
290     MarkedArgumentBuffer argumentList;
291     for (uint32_t i = 0; i < argumentCount; ++i)
292         argumentList.append(m_objectMap->convertNPVariantToJSValue(exec, globalObject, arguments[i]));
293 
294     exec->globalData().timeoutChecker.start();
295     JSValue value = JSC::call(exec, function, callType, callData, m_jsObject.get(), argumentList);
296     exec->globalData().timeoutChecker.stop();
297 
298     // Convert and return the result of the function call.
299     m_objectMap->convertJSValueToNPVariant(exec, value, *result);
300     exec->clearException();
301 
302     return true;
303 }
304 
npClass()305 NPClass* NPJSObject::npClass()
306 {
307     static NPClass npClass = {
308         NP_CLASS_STRUCT_VERSION,
309         NP_Allocate,
310         NP_Deallocate,
311         0,
312         NP_HasMethod,
313         NP_Invoke,
314         NP_InvokeDefault,
315         NP_HasProperty,
316         NP_GetProperty,
317         NP_SetProperty,
318         NP_RemoveProperty,
319         NP_Enumerate,
320         NP_Construct
321     };
322 
323     return &npClass;
324 }
325 
NP_Allocate(NPP npp,NPClass *)326 NPObject* NPJSObject::NP_Allocate(NPP npp, NPClass*)
327 {
328     ASSERT_UNUSED(npp, !npp);
329 
330     return new NPJSObject;
331 }
332 
NP_Deallocate(NPObject * npObject)333 void NPJSObject::NP_Deallocate(NPObject* npObject)
334 {
335     NPJSObject* npJSObject = toNPJSObject(npObject);
336     delete npJSObject;
337 }
338 
NP_HasMethod(NPObject * npObject,NPIdentifier methodName)339 bool NPJSObject::NP_HasMethod(NPObject* npObject, NPIdentifier methodName)
340 {
341     return toNPJSObject(npObject)->hasMethod(methodName);
342 }
343 
NP_Invoke(NPObject * npObject,NPIdentifier methodName,const NPVariant * arguments,uint32_t argumentCount,NPVariant * result)344 bool NPJSObject::NP_Invoke(NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
345 {
346     return toNPJSObject(npObject)->invoke(methodName, arguments, argumentCount, result);
347 }
348 
NP_InvokeDefault(NPObject * npObject,const NPVariant * arguments,uint32_t argumentCount,NPVariant * result)349 bool NPJSObject::NP_InvokeDefault(NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
350 {
351     return toNPJSObject(npObject)->invokeDefault(arguments, argumentCount, result);
352 }
353 
NP_HasProperty(NPObject * npObject,NPIdentifier propertyName)354 bool NPJSObject::NP_HasProperty(NPObject* npObject, NPIdentifier propertyName)
355 {
356     return toNPJSObject(npObject)->hasProperty(propertyName);
357 }
358 
NP_GetProperty(NPObject * npObject,NPIdentifier propertyName,NPVariant * result)359 bool NPJSObject::NP_GetProperty(NPObject* npObject, NPIdentifier propertyName, NPVariant* result)
360 {
361     return toNPJSObject(npObject)->getProperty(propertyName, result);
362 }
363 
NP_SetProperty(NPObject * npObject,NPIdentifier propertyName,const NPVariant * value)364 bool NPJSObject::NP_SetProperty(NPObject* npObject, NPIdentifier propertyName, const NPVariant* value)
365 {
366     return toNPJSObject(npObject)->setProperty(propertyName, value);
367 }
368 
NP_RemoveProperty(NPObject * npObject,NPIdentifier propertyName)369 bool NPJSObject::NP_RemoveProperty(NPObject* npObject, NPIdentifier propertyName)
370 {
371     return toNPJSObject(npObject)->removeProperty(propertyName);
372 }
373 
NP_Enumerate(NPObject * npObject,NPIdentifier ** identifiers,uint32_t * identifierCount)374 bool NPJSObject::NP_Enumerate(NPObject* npObject, NPIdentifier** identifiers, uint32_t* identifierCount)
375 {
376     return toNPJSObject(npObject)->enumerate(identifiers, identifierCount);
377 }
378 
NP_Construct(NPObject * npObject,const NPVariant * arguments,uint32_t argumentCount,NPVariant * result)379 bool NPJSObject::NP_Construct(NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
380 {
381     return toNPJSObject(npObject)->construct(arguments, argumentCount, result);
382 }
383 
384 } // namespace WebKit
385