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