Foo::s_info should be Foo::info(), so that you can change how the s_info is actually...
[WebKit-https.git] / Source / WebKit2 / WebProcess / Plugins / Netscape / NPJSObject.cpp
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 #if ENABLE(NETSCAPE_PLUGIN_API)
30
31 #include "JSNPObject.h"
32 #include "NPRuntimeObjectMap.h"
33 #include "NPRuntimeUtilities.h"
34 #include <JavaScriptCore/JSCJSValueInlines.h>
35 #include <JavaScriptCore/JSCellInlines.h>
36 #include <JavaScriptCore/JSLock.h>
37 #include <JavaScriptCore/JSObject.h>
38 #include <JavaScriptCore/StrongInlines.h>
39 #include <JavaScriptCore/StructureInlines.h>
40 #include <WebCore/Frame.h>
41 #include <WebCore/IdentifierRep.h>
42 #include <wtf/text/WTFString.h>
43
44 using namespace JSC;
45 using namespace WebCore;
46
47 namespace WebKit {
48
49 NPJSObject* NPJSObject::create(VM& vm, NPRuntimeObjectMap* objectMap, JSObject* jsObject)
50 {
51     // We should never have a JSNPObject inside an NPJSObject.
52     ASSERT(!jsObject->inherits(JSNPObject::info()));
53
54     NPJSObject* npJSObject = toNPJSObject(createNPObject(0, npClass()));
55     npJSObject->initialize(vm, objectMap, jsObject);
56
57     return npJSObject;
58 }
59
60 NPJSObject::NPJSObject()
61     : m_objectMap(0)
62 {
63 }
64
65 NPJSObject::~NPJSObject()
66 {
67     m_objectMap->npJSObjectDestroyed(this);
68 }
69
70 bool NPJSObject::isNPJSObject(NPObject* npObject)
71 {
72     return npObject->_class == npClass();
73 }
74
75 void NPJSObject::initialize(VM& vm, NPRuntimeObjectMap* objectMap, JSObject* jsObject)
76 {
77     ASSERT(!m_objectMap);
78     ASSERT(!m_jsObject);
79
80     m_objectMap = objectMap;
81     m_jsObject.set(vm, jsObject);
82 }
83
84 static Identifier identifierFromIdentifierRep(ExecState* exec, IdentifierRep* identifierRep)
85 {
86     ASSERT(identifierRep->isString());
87
88     const char* string = identifierRep->string();
89     int length = strlen(string);
90
91     return Identifier(exec, String::fromUTF8WithLatin1Fallback(string, length).impl());
92 }
93
94 bool NPJSObject::hasMethod(NPIdentifier methodName)
95 {
96     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(methodName);
97
98     if (!identifierRep->isString())
99         return false;
100
101     ExecState* exec = m_objectMap->globalExec();
102     if (!exec)
103         return false;
104
105     JSLockHolder lock(exec);
106
107     JSValue value = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep));    
108     exec->clearException();
109
110     CallData callData;
111     return getCallData(value, callData) != CallTypeNone;
112 }
113
114 bool NPJSObject::invoke(NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
115 {
116     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(methodName);
117     
118     if (!identifierRep->isString())
119         return false;
120     
121     ExecState* exec = m_objectMap->globalExec();
122     if (!exec)
123         return false;
124     
125     JSLockHolder lock(exec);
126
127     JSValue function = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep));
128     return invoke(exec, m_objectMap->globalObject(), function, arguments, argumentCount, result);
129 }
130
131 bool NPJSObject::invokeDefault(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
132 {
133     ExecState* exec = m_objectMap->globalExec();
134     if (!exec)
135         return false;
136
137     JSLockHolder lock(exec);
138
139     JSValue function = m_jsObject.get();
140     return invoke(exec, m_objectMap->globalObject(), function, arguments, argumentCount, result);
141 }
142
143 bool NPJSObject::hasProperty(NPIdentifier identifier)
144 {
145     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(identifier);
146     
147     ExecState* exec = m_objectMap->globalExec();
148     if (!exec)
149         return false;
150     
151     JSLockHolder lock(exec);
152
153     bool result;
154     if (identifierRep->isString())
155         result = m_jsObject->hasProperty(exec, identifierFromIdentifierRep(exec, identifierRep));
156     else
157         result = m_jsObject->hasProperty(exec, identifierRep->number());
158
159     exec->clearException();
160     return result;
161 }
162
163 bool NPJSObject::getProperty(NPIdentifier propertyName, NPVariant* result)
164 {
165     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName);
166     
167     ExecState* exec = m_objectMap->globalExec();
168     if (!exec)
169         return false;
170
171     JSLockHolder lock(exec);
172     JSValue jsResult;
173     if (identifierRep->isString())
174         jsResult = m_jsObject->get(exec, identifierFromIdentifierRep(exec, identifierRep));
175     else
176         jsResult = m_jsObject->get(exec, identifierRep->number());
177     
178     m_objectMap->convertJSValueToNPVariant(exec, jsResult, *result);
179     exec->clearException();
180     return true;
181 }
182
183 bool NPJSObject::setProperty(NPIdentifier propertyName, const NPVariant* value)
184 {
185     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName);
186     
187     ExecState* exec = m_objectMap->globalExec();
188     if (!exec)
189         return false;
190     
191     JSLockHolder lock(exec);
192
193     JSValue jsValue = m_objectMap->convertNPVariantToJSValue(exec, m_objectMap->globalObject(), *value);
194     if (identifierRep->isString()) {
195         PutPropertySlot slot;
196         m_jsObject->methodTable()->put(m_jsObject.get(), exec, identifierFromIdentifierRep(exec, identifierRep), jsValue, slot);
197     } else
198         m_jsObject->methodTable()->putByIndex(m_jsObject.get(), exec, identifierRep->number(), jsValue, false);
199     exec->clearException();
200     
201     return true;
202 }
203
204 bool NPJSObject::removeProperty(NPIdentifier propertyName)
205 {
206     IdentifierRep* identifierRep = static_cast<IdentifierRep*>(propertyName);
207     
208     ExecState* exec = m_objectMap->globalExec();
209     if (!exec)
210         return false;
211
212     JSLockHolder lock(exec);
213     if (identifierRep->isString()) {
214         Identifier identifier = identifierFromIdentifierRep(exec, identifierRep);
215         
216         if (!m_jsObject->hasProperty(exec, identifier)) {
217             exec->clearException();
218             return false;
219         }
220         
221         m_jsObject->methodTable()->deleteProperty(m_jsObject.get(), exec, identifier);
222     } else {
223         if (!m_jsObject->hasProperty(exec, identifierRep->number())) {
224             exec->clearException();
225             return false;
226         }
227
228         m_jsObject->methodTable()->deletePropertyByIndex(m_jsObject.get(), exec, identifierRep->number());
229     }
230
231     exec->clearException();
232     return true;
233 }
234
235 bool NPJSObject::enumerate(NPIdentifier** identifiers, uint32_t* identifierCount)
236 {
237     ExecState* exec = m_objectMap->globalExec();
238     if (!exec)
239         return false;
240     
241     JSLockHolder lock(exec);
242
243     PropertyNameArray propertyNames(exec);
244     m_jsObject->methodTable()->getPropertyNames(m_jsObject.get(), exec, propertyNames, ExcludeDontEnumProperties);
245
246     NPIdentifier* nameIdentifiers = npnMemNewArray<NPIdentifier>(propertyNames.size());
247
248     for (size_t i = 0; i < propertyNames.size(); ++i)
249         nameIdentifiers[i] = static_cast<NPIdentifier>(IdentifierRep::get(propertyNames[i].string().utf8().data()));
250
251     *identifiers = nameIdentifiers;
252     *identifierCount = propertyNames.size();
253
254     return true;
255 }
256
257 bool NPJSObject::construct(const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
258 {
259     ExecState* exec = m_objectMap->globalExec();
260     if (!exec)
261         return false;
262
263     JSLockHolder lock(exec);
264
265     ConstructData constructData;
266     ConstructType constructType = getConstructData(m_jsObject.get(), constructData);
267     if (constructType == ConstructTypeNone)
268         return false;
269
270     // Convert the passed in arguments.
271     MarkedArgumentBuffer argumentList;
272     for (uint32_t i = 0; i < argumentCount; ++i)
273         argumentList.append(m_objectMap->convertNPVariantToJSValue(exec, m_objectMap->globalObject(), arguments[i]));
274
275     JSValue value = JSC::construct(exec, m_jsObject.get(), constructType, constructData, argumentList);
276     
277     // Convert and return the new object.
278     m_objectMap->convertJSValueToNPVariant(exec, value, *result);
279     exec->clearException();
280
281     return true;
282 }
283
284 bool NPJSObject::invoke(ExecState* exec, JSGlobalObject* globalObject, JSValue function, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
285 {
286     CallData callData;
287     CallType callType = getCallData(function, callData);
288     if (callType == CallTypeNone)
289         return false;
290
291     // Convert the passed in arguments.
292     MarkedArgumentBuffer argumentList;
293     for (uint32_t i = 0; i < argumentCount; ++i)
294         argumentList.append(m_objectMap->convertNPVariantToJSValue(exec, globalObject, arguments[i]));
295
296     JSValue value = JSC::call(exec, function, callType, callData, m_jsObject.get(), argumentList);
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
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     
326 NPObject* NPJSObject::NP_Allocate(NPP npp, NPClass*)
327 {
328     ASSERT_UNUSED(npp, !npp);
329
330     return new NPJSObject;
331 }
332
333 void NPJSObject::NP_Deallocate(NPObject* npObject)
334 {
335     NPJSObject* npJSObject = toNPJSObject(npObject);
336     delete npJSObject;
337 }
338
339 bool NPJSObject::NP_HasMethod(NPObject* npObject, NPIdentifier methodName)
340 {
341     return toNPJSObject(npObject)->hasMethod(methodName);
342 }
343     
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     
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     
354 bool NPJSObject::NP_HasProperty(NPObject* npObject, NPIdentifier propertyName)
355 {
356     return toNPJSObject(npObject)->hasProperty(propertyName);
357 }
358
359 bool NPJSObject::NP_GetProperty(NPObject* npObject, NPIdentifier propertyName, NPVariant* result)
360 {
361     return toNPJSObject(npObject)->getProperty(propertyName, result);
362 }
363
364 bool NPJSObject::NP_SetProperty(NPObject* npObject, NPIdentifier propertyName, const NPVariant* value)
365 {
366     return toNPJSObject(npObject)->setProperty(propertyName, value);
367 }
368
369 bool NPJSObject::NP_RemoveProperty(NPObject* npObject, NPIdentifier propertyName)
370 {
371     return toNPJSObject(npObject)->removeProperty(propertyName);
372 }
373
374 bool NPJSObject::NP_Enumerate(NPObject* npObject, NPIdentifier** identifiers, uint32_t* identifierCount)
375 {
376     return toNPJSObject(npObject)->enumerate(identifiers, identifierCount);
377 }
378
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
386 #endif // ENABLE(NETSCAPE_PLUGIN_API)