37c3dd836a6c0d4c7dbb03df77fae8175b284773
[WebKit-https.git] / WebCore / bridge / c / c_instance.cpp
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 "npruntime_impl.h"
36 #include "runtime_root.h"
37 #include <runtime/ArgList.h>
38 #include <interpreter/CallFrame.h>
39 #include <runtime/JSLock.h>
40 #include <runtime/JSNumberCell.h>
41 #include <runtime/PropertyNameArray.h>
42 #include <wtf/Assertions.h>
43 #include <wtf/StringExtras.h>
44 #include <wtf/Vector.h>
45
46 namespace JSC {
47 namespace Bindings {
48
49 CInstance::CInstance(NPObject* o, PassRefPtr<RootObject> rootObject)
50     : Instance(rootObject)
51 {
52     _object = _NPN_RetainObject(o);
53     _class = 0;
54 }
55
56 CInstance::~CInstance() 
57 {
58     _NPN_ReleaseObject(_object);
59 }
60
61 Class *CInstance::getClass() const
62 {
63     if (!_class)
64         _class = CClass::classForIsA(_object->_class);
65     return _class;
66 }
67
68 bool CInstance::supportsInvokeDefaultMethod() const
69 {
70     return _object->_class->invokeDefault;
71 }
72
73 JSValuePtr CInstance::invokeMethod(ExecState* exec, const MethodList& methodList, const ArgList& args)
74 {
75     // Overloading methods are not allowed by NPObjects.  Should only be one
76     // name match for a particular method.
77     ASSERT(methodList.size() == 1);
78
79     CMethod* method = static_cast<CMethod*>(methodList[0]);
80
81     NPIdentifier ident = _NPN_GetStringIdentifier(method->name());
82     if (!_object->_class->hasMethod(_object, ident))
83         return jsUndefined();
84
85     unsigned count = args.size();
86     Vector<NPVariant, 8> cArgs(count);
87
88     unsigned i;
89     for (i = 0; i < count; i++)
90         convertValueToNPVariant(exec, args.at(exec, i), &cArgs[i]);
91
92     // Invoke the 'C' method.
93     NPVariant resultVariant;
94     VOID_TO_NPVARIANT(resultVariant);
95
96     {
97         JSLock::DropAllLocks dropAllLocks(false);
98         _object->_class->invoke(_object, ident, cArgs.data(), count, &resultVariant);
99     }
100
101     for (i = 0; i < count; i++)
102         _NPN_ReleaseVariantValue(&cArgs[i]);
103
104     JSValuePtr resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
105     _NPN_ReleaseVariantValue(&resultVariant);
106     return resultValue;
107 }
108
109
110 JSValuePtr CInstance::invokeDefaultMethod(ExecState* exec, const ArgList& args)
111 {
112     if (!_object->_class->invokeDefault)
113         return jsUndefined();
114
115     unsigned count = args.size();
116     Vector<NPVariant, 8> cArgs(count);
117
118     unsigned i;
119     for (i = 0; i < count; i++)
120         convertValueToNPVariant(exec, args.at(exec, i), &cArgs[i]);
121
122     // Invoke the 'C' method.
123     NPVariant resultVariant;
124     VOID_TO_NPVARIANT(resultVariant);
125     {
126         JSLock::DropAllLocks dropAllLocks(false);
127         _object->_class->invokeDefault(_object, cArgs.data(), count, &resultVariant);
128     }
129     
130     for (i = 0; i < count; i++)
131         _NPN_ReleaseVariantValue(&cArgs[i]);
132
133     JSValuePtr resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
134     _NPN_ReleaseVariantValue(&resultVariant);
135     return resultValue;
136 }
137
138 bool CInstance::supportsConstruct() const
139 {
140     return _object->_class->construct;
141 }
142     
143 JSValuePtr CInstance::invokeConstruct(ExecState* exec, const ArgList& args)
144 {
145     if (!_object->_class->construct)
146         return jsUndefined();
147
148     unsigned count = args.size();
149     Vector<NPVariant, 8> cArgs(count);
150
151     unsigned i;
152     for (i = 0; i < count; i++)
153         convertValueToNPVariant(exec, args.at(exec, i), &cArgs[i]);
154
155     // Invoke the 'C' method.
156     NPVariant resultVariant;
157     VOID_TO_NPVARIANT(resultVariant);
158     {
159         JSLock::DropAllLocks dropAllLocks(false);
160         _object->_class->construct(_object, cArgs.data(), count, &resultVariant);
161     }
162     
163     for (i = 0; i < count; i++)
164         _NPN_ReleaseVariantValue(&cArgs[i]);
165
166     JSValuePtr resultValue = convertNPVariantToValue(exec, &resultVariant, _rootObject.get());
167     _NPN_ReleaseVariantValue(&resultVariant);
168     return resultValue;
169 }
170
171 JSValuePtr CInstance::defaultValue(ExecState* exec, PreferredPrimitiveType hint) const
172 {
173     if (hint == PreferString)
174         return stringValue(exec);
175     if (hint == PreferNumber)
176         return numberValue(exec);
177     return valueOf(exec);
178 }
179
180 JSValuePtr CInstance::stringValue(ExecState* exec) const
181 {
182     char buf[1024];
183     snprintf(buf, sizeof(buf), "NPObject %p, NPClass %p", _object, _object->_class);
184     return jsString(exec, buf);
185 }
186
187 JSValuePtr CInstance::numberValue(ExecState* exec) const
188 {
189     // FIXME: Implement something sensible.
190     return jsNumber(exec, 0);
191 }
192
193 JSValuePtr CInstance::booleanValue() const
194 {
195     // FIXME: Implement something sensible.
196     return jsBoolean(false);
197 }
198
199 JSValuePtr CInstance::valueOf(ExecState* exec) const 
200 {
201     return stringValue(exec);
202 }
203
204 void CInstance::getPropertyNames(ExecState* exec, PropertyNameArray& nameArray)
205 {
206     if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(_object->_class) || !_object->_class->enumerate)
207         return;
208
209     uint32_t count;
210     NPIdentifier* identifiers;
211
212     {
213         JSLock::DropAllLocks dropAllLocks(false);
214         if (!_object->_class->enumerate(_object, &identifiers, &count))
215             return;
216     }
217
218     for (uint32_t i = 0; i < count; i++) {
219         PrivateIdentifier* identifier = static_cast<PrivateIdentifier*>(identifiers[i]);
220
221         if (identifier->isString)
222             nameArray.add(identifierFromNPIdentifier(identifier->value.string));
223         else
224             nameArray.add(Identifier::from(exec, identifier->value.number));
225     }
226
227     // FIXME: This should really call NPN_MemFree but that's in WebKit
228     free(identifiers);
229 }
230
231 }
232 }
233
234 #endif // ENABLE(NETSCAPE_PLUGIN_API)