15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*/
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
32e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/V8NPObject.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "V8HTMLAppletElement.h"
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "V8HTMLEmbedElement.h"
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "V8HTMLObjectElement.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/NPV8Object.h"
395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "bindings/v8/UnsafePersistent.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/V8Binding.h"
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/V8NPUtils.h"
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/V8ObjectConstructor.h"
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/npruntime_impl.h"
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "bindings/v8/npruntime_priv.h"
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLPlugInElement.h"
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "wtf/OwnArrayPtr.h"
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore {
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)enum InvokeFunctionType {
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InvokeMethod = 1,
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InvokeConstruct = 2,
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InvokeDefault = 3
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct IdentifierRep {
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int number() const { return m_isString ? 0 : m_value.m_number; }
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const char* string() const { return m_isString ? m_value.m_string : 0; }
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    union {
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const char* m_string;
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int m_number;
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } m_value;
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool m_isString;
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: need comments.
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Params: holder could be HTMLEmbedElement or NPObject
695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& args, InvokeFunctionType functionId)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPObject* npObject;
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
73926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    WrapperWorldType currentWorldType = worldType(args.GetIsolate());
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // These three types are subtypes of HTMLPlugInElement.
75926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (V8HTMLAppletElement::HasInstance(args.Holder(), args.GetIsolate(), currentWorldType) || V8HTMLEmbedElement::HasInstance(args.Holder(), args.GetIsolate(), currentWorldType)
76926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        || V8HTMLObjectElement::HasInstance(args.Holder(), args.GetIsolate(), currentWorldType)) {
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The holder object is a subtype of HTMLPlugInElement.
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        HTMLPlugInElement* element;
79926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        if (V8HTMLAppletElement::HasInstance(args.Holder(), args.GetIsolate(), currentWorldType))
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            element = V8HTMLAppletElement::toNative(args.Holder());
81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        else if (V8HTMLEmbedElement::HasInstance(args.Holder(), args.GetIsolate(), currentWorldType))
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            element = V8HTMLEmbedElement::toNative(args.Holder());
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            element = V8HTMLObjectElement::toNative(args.Holder());
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ScriptInstance scriptInstance = element->getInstance();
8693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (scriptInstance) {
8793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            v8::Isolate* isolate = v8::Isolate::GetCurrent();
8893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            v8::HandleScope handleScope(isolate);
8993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            npObject = v8ObjectToNPObject(scriptInstance->newLocal(isolate));
9093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        } else
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            npObject = 0;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    } else {
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // The holder object is not a subtype of HTMLPlugInElement, it must be an NPObject which has three
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // internal fields.
955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (args.Holder()->InternalFieldCount() != npObjectInternalFieldCount) {
965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            throwError(v8ReferenceError, "NPMethod called on non-NPObject", args.GetIsolate());
975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            return;
985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        }
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        npObject = v8ObjectToNPObject(args.Holder());
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify that our wrapper wasn't using a NPObject which has already been deleted.
1045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (!npObject || !_NPN_IsAlive(npObject)) {
1055267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        throwError(v8ReferenceError, "NPObject deleted", args.GetIsolate());
1065267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return;
1075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Wrap up parameters.
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int numArgs = args.Length();
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    OwnArrayPtr<NPVariant> npArgs = adoptArrayPtr(new NPVariant[numArgs]);
112e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = 0; i < numArgs; i++)
114e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        convertV8ObjectToNPVariant(args[i], npObject, &npArgs[i]);
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPVariant result;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    VOID_TO_NPVARIANT(result);
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool retval = true;
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    switch (functionId) {
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case InvokeMethod:
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (npObject->_class->invoke) {
1235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            v8::Handle<v8::String> functionName = v8::Handle<v8::String>::Cast(args.Data());
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            NPIdentifier identifier = getStringIdentifier(functionName);
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            retval = npObject->_class->invoke(npObject, identifier, npArgs.get(), numArgs, &result);
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case InvokeConstruct:
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (npObject->_class->construct)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            retval = npObject->_class->construct(npObject, npArgs.get(), numArgs, &result);
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    case InvokeDefault:
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (npObject->_class->invokeDefault)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            retval = npObject->_class->invokeDefault(npObject, npArgs.get(), numArgs, &result);
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    default:
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        break;
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!retval)
141926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        throwError(v8GeneralError, "Error calling method on NPObject.", args.GetIsolate());
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = 0; i < numArgs; i++)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        _NPN_ReleaseVariantValue(&npArgs[i]);
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Unwrap return values.
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    v8::Handle<v8::Value> returnValue;
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (_NPN_IsAlive(npObject))
149e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        returnValue = convertNPVariantToV8Object(&result, npObject, args.GetIsolate());
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _NPN_ReleaseVariantValue(&result);
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    v8SetReturnValue(args, returnValue);
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1565267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void npObjectMethodHandler(const v8::FunctionCallbackInfo<v8::Value>& args)
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return npObjectInvokeImpl(args, InvokeMethod);
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1625267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)void npObjectInvokeDefaultHandler(const v8::FunctionCallbackInfo<v8::Value>& args)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1645267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (args.IsConstructCall()) {
1655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        npObjectInvokeImpl(args, InvokeConstruct);
1665267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return;
1675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    npObjectInvokeImpl(args, InvokeDefault);
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
17253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)class V8NPTemplateMap {
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // NPIdentifier is PrivateIdentifier*.
1755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    typedef HashMap<PrivateIdentifier*, UnsafePersistent<v8::FunctionTemplate> > MapType;
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1775267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    UnsafePersistent<v8::FunctionTemplate> get(PrivateIdentifier* key)
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_map.get(key);
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1825267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    void set(PrivateIdentifier* key, v8::Handle<v8::FunctionTemplate> handle)
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(!m_map.contains(key));
1855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        v8::Persistent<v8::FunctionTemplate> wrapper(m_isolate, handle);
186521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        wrapper.MakeWeak(key, &makeWeakCallback);
1875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        m_map.set(key, UnsafePersistent<v8::FunctionTemplate>(wrapper));
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
190926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    static V8NPTemplateMap& sharedInstance(v8::Isolate* isolate)
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
192926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        DEFINE_STATIC_LOCAL(V8NPTemplateMap, map, (isolate));
193926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        ASSERT(isolate == map.m_isolate);
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return map;
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
198926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    explicit V8NPTemplateMap(v8::Isolate* isolate)
199926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        : m_isolate(isolate)
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
201926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    }
202926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    void dispose(PrivateIdentifier* key)
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        MapType::iterator it = m_map.find(key);
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(it != m_map.end());
2075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        it->value.dispose();
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_map.remove(it);
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
21193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    static void makeWeakCallback(v8::Isolate* isolate, v8::Persistent<v8::FunctionTemplate>*, PrivateIdentifier* key)
21293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    {
21393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        V8NPTemplateMap::sharedInstance(isolate).dispose(key);
21493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
21593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    MapType m_map;
217926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    v8::Isolate* m_isolate;
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static v8::Handle<v8::Value> npObjectGetProperty(v8::Local<v8::Object> self, NPIdentifier identifier, v8::Local<v8::Value> key, v8::Isolate* isolate)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPObject* npObject = v8ObjectToNPObject(self);
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify that our wrapper wasn't using a NPObject which
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // has already been deleted.
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!npObject || !_NPN_IsAlive(npObject))
227926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return throwError(v8ReferenceError, "NPObject deleted", isolate);
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
229e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (npObject->_class->hasProperty && npObject->_class->getProperty && npObject->_class->hasProperty(npObject, identifier)) {
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!_NPN_IsAlive(npObject))
232926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return throwError(v8ReferenceError, "NPObject deleted", isolate);
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        NPVariant result;
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        VOID_TO_NPVARIANT(result);
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!npObject->_class->getProperty(npObject, identifier, &result))
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return v8Undefined();
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8::Handle<v8::Value> returnValue;
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (_NPN_IsAlive(npObject))
241e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            returnValue = convertNPVariantToV8Object(&result, npObject, isolate);
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        _NPN_ReleaseVariantValue(&result);
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return returnValue;
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!_NPN_IsAlive(npObject))
248926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        return throwError(v8ReferenceError, "NPObject deleted", isolate);
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (key->IsString() && npObject->_class->hasMethod && npObject->_class->hasMethod(npObject, identifier)) {
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!_NPN_IsAlive(npObject))
252926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return throwError(v8ReferenceError, "NPObject deleted", isolate);
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        PrivateIdentifier* id = static_cast<PrivateIdentifier*>(identifier);
2555267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        UnsafePersistent<v8::FunctionTemplate> functionTemplate = V8NPTemplateMap::sharedInstance(isolate).get(id);
2565267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        // FunctionTemplate caches function for each context.
2575267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        v8::Local<v8::Function> v8Function;
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Cache templates using identifier as the key.
2595267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        if (functionTemplate.isEmpty()) {
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Create a new template.
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            v8::Local<v8::FunctionTemplate> temp = v8::FunctionTemplate::New();
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            temp->SetCallHandler(npObjectMethodHandler, key);
2635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            V8NPTemplateMap::sharedInstance(isolate).set(id, temp);
2645267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            v8Function = temp->GetFunction();
2655267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        } else {
2665267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)            v8Function = functionTemplate.newLocal(isolate)->GetFunction();
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        v8Function->SetName(v8::Handle<v8::String>::Cast(key));
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return v8Function;
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return v8Undefined();
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
275521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectNamedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPIdentifier identifier = getStringIdentifier(name);
278521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    v8SetReturnValue(info, npObjectGetProperty(info.Holder(), identifier, name, info.GetIsolate()));
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
281521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectIndexedPropertyGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPIdentifier identifier = _NPN_GetIntIdentifier(index);
284521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    v8SetReturnValue(info, npObjectGetProperty(info.Holder(), identifier, v8::Number::New(index), info.GetIsolate()));
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
287521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectGetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPIdentifier identifier = getStringIdentifier(name);
290521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    v8SetReturnValue(info, npObjectGetProperty(self, identifier, name, info.GetIsolate()));
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
293521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectGetIndexedProperty(v8::Local<v8::Object> self, uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPIdentifier identifier = _NPN_GetIntIdentifier(index);
296521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    v8SetReturnValue(info, npObjectGetProperty(self, identifier, v8::Number::New(index), info.GetIsolate()));
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
299521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectQueryProperty(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPIdentifier identifier = getStringIdentifier(name);
302521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    if (npObjectGetProperty(info.Holder(), identifier, name, info.GetIsolate()).IsEmpty())
303521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        return;
304521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    v8SetReturnValueInt(info, 0);
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static v8::Handle<v8::Value> npObjectSetProperty(v8::Local<v8::Object> self, NPIdentifier identifier, v8::Local<v8::Value> value, v8::Isolate* isolate)
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPObject* npObject = v8ObjectToNPObject(self);
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify that our wrapper wasn't using a NPObject which has already been deleted.
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!npObject || !_NPN_IsAlive(npObject)) {
313926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        throwError(v8ReferenceError, "NPObject deleted", isolate);
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return value;  // Intercepted, but an exception was thrown.
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (npObject->_class->hasProperty && npObject->_class->setProperty && npObject->_class->hasProperty(npObject, identifier)) {
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!_NPN_IsAlive(npObject))
319926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            return throwError(v8ReferenceError, "NPObject deleted", isolate);
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        NPVariant npValue;
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        VOID_TO_NPVARIANT(npValue);
323e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        convertV8ObjectToNPVariant(value, npObject, &npValue);
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool success = npObject->_class->setProperty(npObject, identifier, &npValue);
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        _NPN_ReleaseVariantValue(&npValue);
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (success)
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return value; // Intercept the call.
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return v8Undefined();
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
333521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectNamedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPIdentifier identifier = getStringIdentifier(name);
336521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    v8SetReturnValue(info, npObjectSetProperty(info.Holder(), identifier, value, info.GetIsolate()));
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
340521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectIndexedPropertySetter(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPIdentifier identifier = _NPN_GetIntIdentifier(index);
343521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    v8SetReturnValue(info, npObjectSetProperty(info.Holder(), identifier, value, info.GetIsolate()));
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
346521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectSetNamedProperty(v8::Local<v8::Object> self, v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPIdentifier identifier = getStringIdentifier(name);
349521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    v8SetReturnValue(info, npObjectSetProperty(self, identifier, value, info.GetIsolate()));
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
352521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectSetIndexedProperty(v8::Local<v8::Object> self, uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPIdentifier identifier = _NPN_GetIntIdentifier(index);
355521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    v8SetReturnValue(info, npObjectSetProperty(self, identifier, value, info.GetIsolate()));
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
358521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info, bool namedProperty)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    NPObject* npObject = v8ObjectToNPObject(info.Holder());
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Verify that our wrapper wasn't using a NPObject which
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // has already been deleted.
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!npObject || !_NPN_IsAlive(npObject))
365926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        throwError(v8ReferenceError, "NPObject deleted", info.GetIsolate());
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate) {
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint32_t count;
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        NPIdentifier* identifiers;
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (npObject->_class->enumerate(npObject, &identifiers, &count)) {
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            v8::Handle<v8::Array> properties = v8::Array::New(count);
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            for (uint32_t i = 0; i < count; ++i) {
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]);
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (namedProperty)
375591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                    properties->Set(v8::Integer::New(i, info.GetIsolate()), v8::String::NewSymbol(identifier->string()));
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else
377591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                    properties->Set(v8::Integer::New(i, info.GetIsolate()), v8::Integer::New(identifier->number(), info.GetIsolate()));
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
380521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            v8SetReturnValue(info, properties);
381521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)            return;
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
386521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectNamedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
388521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    npObjectPropertyEnumerator(info, true);
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
391521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)void npObjectIndexedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
393521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    npObjectPropertyEnumerator(info, false);
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static DOMWrapperMap<NPObject>& staticNPObjectMap()
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
39853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    DEFINE_STATIC_LOCAL(DOMWrapperMap<NPObject>, npObjectMap, (v8::Isolate::GetCurrent()));
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return npObjectMap;
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
40253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)template<>
40393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)inline void DOMWrapperMap<NPObject>::makeWeakCallback(v8::Isolate* isolate, v8::Persistent<v8::Object>* wrapper, DOMWrapperMap<NPObject>*)
4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
40593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    NPObject* npObject = static_cast<NPObject*>(toNative(*wrapper));
4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(npObject);
40893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    ASSERT(staticNPObjectMap().get(npObject) == *wrapper);
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Must remove from our map before calling _NPN_ReleaseObject(). _NPN_ReleaseObject can
4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // call forgetV8ObjectForNPObject, which uses the table as well.
41293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    staticNPObjectMap().removeAndDispose(npObject);
4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (_NPN_IsAlive(npObject))
4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        _NPN_ReleaseObject(npObject);
4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
418e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdochv8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root)
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static v8::Persistent<v8::FunctionTemplate> npObjectDesc;
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(v8::Context::InContext());
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
4255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If this is a v8 object, just return it.
427591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    V8NPObject* v8NPObject = npObjectToV8NPObject(object);
428591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    if (v8NPObject)
4295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return v8::Local<v8::Object>::New(isolate, v8NPObject->v8Object);
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we've already wrapped this object, just return it.
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    v8::Handle<v8::Object> wrapper = staticNPObjectMap().get(object);
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!wrapper.IsEmpty())
4345267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        return v8::Local<v8::Object>::New(isolate, wrapper);
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: we should create a Wrapper type as a subclass of JSObject. It has two internal fields, field 0 is the wrapped
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // pointer, and field 1 is the type. There should be an api function that returns unused type id. The same Wrapper type
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // can be used by DOM bindings.
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (npObjectDesc.IsEmpty()) {
4405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        v8::Handle<v8::FunctionTemplate> templ = v8::FunctionTemplate::New();
4415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        templ->InstanceTemplate()->SetInternalFieldCount(npObjectInternalFieldCount);
4425267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        templ->InstanceTemplate()->SetNamedPropertyHandler(npObjectNamedPropertyGetter, npObjectNamedPropertySetter, npObjectQueryProperty, 0, npObjectNamedPropertyEnumerator);
4435267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        templ->InstanceTemplate()->SetIndexedPropertyHandler(npObjectIndexedPropertyGetter, npObjectIndexedPropertySetter, 0, 0, npObjectIndexedPropertyEnumerator);
4445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        templ->InstanceTemplate()->SetCallAsFunctionHandler(npObjectInvokeDefaultHandler);
4455267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        npObjectDesc.Reset(isolate, templ);
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
448926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // FIXME: Move staticNPObjectMap() to DOMDataStore.
449926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // Use V8DOMWrapper::createWrapper() and
450926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // V8DOMWrapper::associateObjectWithWrapper()
451926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    // to create a wrapper object.
4525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    v8::Handle<v8::Function> v8Function = v8::Local<v8::FunctionTemplate>::New(isolate, npObjectDesc)->GetFunction();
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    v8::Local<v8::Object> value = V8ObjectConstructor::newInstance(v8Function);
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (value.IsEmpty())
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return value;
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
457926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    V8DOMWrapper::setNativeInfo(value, npObjectTypeInfo(), object);
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // KJS retains the object as part of its wrapper (see Bindings::CInstance).
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    _NPN_RetainObject(object);
461e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    _NPN_RegisterObject(object, root);
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
463926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    WrapperConfiguration configuration = buildWrapperConfiguration(object, WrapperConfiguration::Dependent);
464926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    staticNPObjectMap().set(object, value, configuration);
465926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    ASSERT(V8DOMWrapper::maybeDOMWrapper(value));
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return value;
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void forgetV8ObjectForNPObject(NPObject* object)
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
47193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    v8::Isolate* isolate = v8::Isolate::GetCurrent();
47293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    v8::HandleScope scope(isolate);
47393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    v8::Handle<v8::Object> wrapper = staticNPObjectMap().getNewLocal(isolate, object);
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!wrapper.IsEmpty()) {
475926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        V8DOMWrapper::clearNativeInfo(wrapper, npObjectTypeInfo());
47693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        staticNPObjectMap().removeAndDispose(object);
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        _NPN_ReleaseObject(object);
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore
482