1/*
2 * Copyright (C) 2009 Google 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 are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "WebBindings.h"
33
34#include "npruntime_impl.h"
35#include "npruntime_priv.h"
36
37#if USE(V8)
38#include "NPV8Object.h"  // for PrivateIdentifier
39#include "Range.h"
40#include "V8BindingState.h"
41#include "V8DOMWrapper.h"
42#include "V8Element.h"
43#include "V8NPUtils.h"
44#include "V8Node.h"
45#include "V8Proxy.h"
46#include "V8Range.h"
47#elif USE(JSC)
48#include "bridge/c/c_utility.h"
49#endif
50#include "WebElement.h"
51#include "WebRange.h"
52
53#if USE(JAVASCRIPTCORE_BINDINGS)
54using JSC::Bindings::PrivateIdentifier;
55#endif
56
57using namespace WebCore;
58
59namespace WebKit {
60
61bool WebBindings::construct(NPP npp, NPObject* object, const NPVariant* args, uint32_t argCount, NPVariant* result)
62{
63    return _NPN_Construct(npp, object, args, argCount, result);
64}
65
66NPObject* WebBindings::createObject(NPP npp, NPClass* npClass)
67{
68    return _NPN_CreateObject(npp, npClass);
69}
70
71bool WebBindings::enumerate(NPP npp, NPObject* object, NPIdentifier** identifier, uint32_t* identifierCount)
72{
73    return _NPN_Enumerate(npp, object, identifier, identifierCount);
74}
75
76bool WebBindings::evaluate(NPP npp, NPObject* object, NPString* script, NPVariant* result)
77{
78    return _NPN_Evaluate(npp, object, script, result);
79}
80
81bool WebBindings::evaluateHelper(NPP npp, bool popupsAllowed, NPObject* object, NPString* script, NPVariant* result)
82{
83    return _NPN_EvaluateHelper(npp, popupsAllowed, object, script, result);
84}
85
86NPIdentifier WebBindings::getIntIdentifier(int32_t number)
87{
88    return _NPN_GetIntIdentifier(number);
89}
90
91bool WebBindings::getProperty(NPP npp, NPObject* object, NPIdentifier property, NPVariant* result)
92{
93    return _NPN_GetProperty(npp, object, property, result);
94}
95
96NPIdentifier WebBindings::getStringIdentifier(const NPUTF8* string)
97{
98    return _NPN_GetStringIdentifier(string);
99}
100
101void WebBindings::getStringIdentifiers(const NPUTF8** names, int32_t nameCount, NPIdentifier* identifiers)
102{
103    _NPN_GetStringIdentifiers(names, nameCount, identifiers);
104}
105
106bool WebBindings::hasMethod(NPP npp, NPObject* object, NPIdentifier method)
107{
108    return _NPN_HasMethod(npp, object, method);
109}
110
111bool WebBindings::hasProperty(NPP npp, NPObject* object, NPIdentifier property)
112{
113    return _NPN_HasProperty(npp, object, property);
114}
115
116bool WebBindings::identifierIsString(NPIdentifier identifier)
117{
118    return _NPN_IdentifierIsString(identifier);
119}
120
121int32_t WebBindings::intFromIdentifier(NPIdentifier identifier)
122{
123    return _NPN_IntFromIdentifier(identifier);
124}
125
126void WebBindings::initializeVariantWithStringCopy(NPVariant* variant, const NPString* value)
127{
128#if USE(V8)
129    _NPN_InitializeVariantWithStringCopy(variant, value);
130#else
131    NPN_InitializeVariantWithStringCopy(variant, value);
132#endif
133}
134
135bool WebBindings::invoke(NPP npp, NPObject* object, NPIdentifier method, const NPVariant* args, uint32_t argCount, NPVariant* result)
136{
137    return _NPN_Invoke(npp, object, method, args, argCount, result);
138}
139
140bool WebBindings::invokeDefault(NPP npp, NPObject* object, const NPVariant* args, uint32_t argCount, NPVariant* result)
141{
142    return _NPN_InvokeDefault(npp, object, args, argCount, result);
143}
144
145void WebBindings::releaseObject(NPObject* object)
146{
147    return _NPN_ReleaseObject(object);
148}
149
150void WebBindings::releaseVariantValue(NPVariant* variant)
151{
152    _NPN_ReleaseVariantValue(variant);
153}
154
155bool WebBindings::removeProperty(NPP npp, NPObject* object, NPIdentifier identifier)
156{
157    return _NPN_RemoveProperty(npp, object, identifier);
158}
159
160NPObject* WebBindings::retainObject(NPObject* object)
161{
162    return _NPN_RetainObject(object);
163}
164
165void WebBindings::setException(NPObject* object, const NPUTF8* message)
166{
167    _NPN_SetException(object, message);
168}
169
170bool WebBindings::setProperty(NPP npp, NPObject* object, NPIdentifier identifier, const NPVariant* value)
171{
172    return _NPN_SetProperty(npp, object, identifier, value);
173}
174
175void WebBindings::unregisterObject(NPObject* object)
176{
177#if USE(V8)
178    _NPN_UnregisterObject(object);
179#endif
180}
181
182NPUTF8* WebBindings::utf8FromIdentifier(NPIdentifier identifier)
183{
184    return _NPN_UTF8FromIdentifier(identifier);
185}
186
187void WebBindings::extractIdentifierData(const NPIdentifier& identifier, const NPUTF8*& string, int32_t& number, bool& isString)
188{
189    PrivateIdentifier* data = static_cast<PrivateIdentifier*>(identifier);
190    if (!data) {
191        isString = false;
192        number = 0;
193        return;
194    }
195
196    isString = data->isString;
197    if (isString)
198        string = data->value.string;
199    else
200        number = data->value.number;
201}
202
203#if USE(V8)
204
205static bool getRangeImpl(NPObject* object, WebRange* webRange)
206{
207    if (!object || (object->_class != npScriptObjectClass))
208        return false;
209
210    V8NPObject* v8NPObject = reinterpret_cast<V8NPObject*>(object);
211    v8::Handle<v8::Object> v8Object(v8NPObject->v8Object);
212    if (!V8Range::info.equals(V8DOMWrapper::domWrapperType(v8Object)))
213        return false;
214
215    Range* native = V8Range::toNative(v8Object);
216    if (!native)
217        return false;
218
219    *webRange = WebRange(native);
220    return true;
221}
222
223static bool getElementImpl(NPObject* object, WebElement* webElement)
224{
225    if (!object || (object->_class != npScriptObjectClass))
226        return false;
227
228    V8NPObject* v8NPObject = reinterpret_cast<V8NPObject*>(object);
229    v8::Handle<v8::Object> v8Object(v8NPObject->v8Object);
230    Element* native = V8Element::toNative(v8Object);
231    if (!native)
232        return false;
233
234    *webElement = WebElement(native);
235    return true;
236}
237
238static NPObject* makeIntArrayImpl(const WebVector<int>& data)
239{
240    v8::HandleScope handleScope;
241    v8::Handle<v8::Array> result = v8::Array::New(data.size());
242    for (size_t i = 0; i < data.size(); ++i)
243        result->Set(i, v8::Number::New(data[i]));
244
245    WebCore::DOMWindow* window = WebCore::V8Proxy::retrieveWindow(WebCore::V8Proxy::currentContext());
246    return npCreateV8ScriptObject(0, result, window);
247}
248
249static NPObject* makeStringArrayImpl(const WebVector<WebString>& data)
250{
251    v8::HandleScope handleScope;
252    v8::Handle<v8::Array> result = v8::Array::New(data.size());
253    for (size_t i = 0; i < data.size(); ++i)
254        result->Set(i, data[i].data() ? v8::String::New(reinterpret_cast<const uint16_t*>((data[i].data())), data[i].length()) : v8::String::New(""));
255
256    WebCore::DOMWindow* window = WebCore::V8Proxy::retrieveWindow(WebCore::V8Proxy::currentContext());
257    return npCreateV8ScriptObject(0, result, window);
258}
259
260static NPObject* makeNodeImpl(WebNode data)
261{
262    v8::HandleScope handleScope;
263    if (data.isNull())
264        return 0;
265    v8::Handle<v8::Object> result = V8Node::wrap(data.unwrap<Node>());
266    WebCore::DOMWindow* window = WebCore::V8Proxy::retrieveWindow(WebCore::V8Proxy::currentContext());
267    return npCreateV8ScriptObject(0, result, window);
268}
269
270#endif
271
272bool WebBindings::getRange(NPObject* range, WebRange* webRange)
273{
274#if USE(V8)
275    return getRangeImpl(range, webRange);
276#else
277    // Not supported on other ports (JSC, etc).
278    return false;
279#endif
280}
281
282bool WebBindings::getElement(NPObject* element, WebElement* webElement)
283{
284#if USE(V8)
285    return getElementImpl(element, webElement);
286#else
287    // Not supported on other ports (JSC, etc.).
288    return false;
289#endif
290}
291
292NPObject* WebBindings::makeIntArray(const WebVector<int>& data)
293{
294#if USE(V8)
295    return makeIntArrayImpl(data);
296#else
297    // Not supported on other ports (JSC, etc.).
298    return 0;
299#endif
300}
301
302NPObject* WebBindings::makeStringArray(const WebVector<WebString>& data)
303{
304#if USE(V8)
305    return makeStringArrayImpl(data);
306#else
307    // Not supported on other ports (JSC, etc.).
308    return 0;
309#endif
310}
311
312NPObject* WebBindings::makeNode(const WebNode& data)
313{
314#if USE(V8)
315    return makeNodeImpl(data);
316#else
317    // Not supported on other ports (JSC, etc.).
318    return 0;
319#endif
320}
321
322void WebBindings::pushExceptionHandler(ExceptionHandler handler, void* data)
323{
324    WebCore::pushExceptionHandler(handler, data);
325}
326
327void WebBindings::popExceptionHandler()
328{
329    WebCore::popExceptionHandler();
330}
331
332} // namespace WebKit
333