Home | History | Annotate | Download | only in Netscape
      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 
     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 
     56 NPJSObject::NPJSObject()
     57     : m_objectMap(0)
     58 {
     59 }
     60 
     61 NPJSObject::~NPJSObject()
     62 {
     63     m_objectMap->npJSObjectDestroyed(this);
     64 }
     65 
     66 bool NPJSObject::isNPJSObject(NPObject* npObject)
     67 {
     68     return npObject->_class == npClass();
     69 }
     70 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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