nporuntime.h 12.6 KB
Newer Older
1
/*****************************************************************************
2 3
 * runtime.cpp: support for NPRuntime API for Netscape Script-able plugins
 *              FYI: http://www.mozilla.org/projects/plugins/npruntime.html
4 5
 *****************************************************************************
 * Copyright (C) 2002-2005 the VideoLAN team
Konstantin Pavlov's avatar
Konstantin Pavlov committed
6
 * $Id$
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *
 * Authors: Damien Fouilleul <damien.fouilleul@laposte.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef __NPORUNTIME_H__
#define __NPORUNTIME_H__

/*
** support framework for runtime script objects
*/

32 33 34 35 36
//on windows, to avoid including <npapi.h> 
//from Microsoft SDK (rather then from Mozilla SDK),
//#include it indirectly via <npfunctions.h>
#include <npfunctions.h>

37 38
#include <npruntime.h>

39 40 41 42 43 44 45
static void RuntimeNPClassDeallocate(NPObject *npobj);
static void RuntimeNPClassInvalidate(NPObject *npobj);
static bool RuntimeNPClassInvokeDefault(NPObject *npobj,
                                        const NPVariant *args,
                                        uint32_t argCount,
                                        NPVariant *result);

46 47 48
class RuntimeNPObject : public NPObject
{
public:
49 50 51
    // Lazy child object cration helper. Doing this avoids
    // ownership problems with firefox.
    template<class T> void InstantObj( NPObject *&obj );
52 53 54 55 56

    /*
    ** utility functions
    */

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
    static bool isNumberValue(const NPVariant &v)
    {
        return NPVARIANT_IS_INT32(v)
            || NPVARIANT_IS_DOUBLE(v);
    };

    static int numberValue(const NPVariant &v)
    {
        switch( v.type ) {
            case NPVariantType_Int32:
                return NPVARIANT_TO_INT32(v);
            case NPVariantType_Double:
                return(int)NPVARIANT_TO_DOUBLE(v);
            default:
                return 0;
        }
    };

Damien Fouilleul's avatar
Damien Fouilleul committed
75 76 77
    static char* stringValue(const NPString &v);
    static char* stringValue(const NPVariant &v);

78
protected:
79 80
    void *operator new(size_t n)
    {
81 82 83 84
        /*
        ** Assume that browser has a smarter memory allocator
        ** than plain old malloc() and use it instead.
        */
85 86 87 88 89
        return NPN_MemAlloc(n);
    };

    void operator delete(void *p)
    {
90 91 92 93 94 95
        NPN_MemFree(p);
    };

    bool isValid()
    {
        return _instance != NULL;
96
    };
97

98 99 100 101
    RuntimeNPObject(NPP instance, const NPClass *aClass) :
        _instance(instance)
    {
        _class = const_cast<NPClass *>(aClass);
102
        referenceCount = 1;
103 104 105 106 107 108 109 110 111 112 113 114 115
    };
    virtual ~RuntimeNPObject() {};

    enum InvokeResult
    {
        INVOKERESULT_NO_ERROR       = 0,    /* returns no error */
        INVOKERESULT_GENERIC_ERROR  = 1,    /* returns error */
        INVOKERESULT_NO_SUCH_METHOD = 2,    /* throws method does not exist */
        INVOKERESULT_INVALID_ARGS   = 3,    /* throws invalid arguments */
        INVOKERESULT_INVALID_VALUE  = 4,    /* throws invalid value in assignment */
        INVOKERESULT_OUT_OF_MEMORY  = 5,    /* throws out of memory */
    };

116 117
    friend void RuntimeNPClassDeallocate(NPObject *npobj);
    friend void RuntimeNPClassInvalidate(NPObject *npobj);
118 119 120 121 122 123
    template <class RuntimeNPObject> friend bool RuntimeNPClassGetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result);
    template <class RuntimeNPObject> friend bool RuntimeNPClassSetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value);
    template <class RuntimeNPObject> friend bool RuntimeNPClassRemoveProperty(NPObject *npobj, NPIdentifier name);
    template <class RuntimeNPObject> friend bool RuntimeNPClassInvoke(NPObject *npobj, NPIdentifier name,
                                                    const NPVariant *args, uint32_t argCount,
                                                    NPVariant *result);
124 125 126 127
    friend bool RuntimeNPClassInvokeDefault(NPObject *npobj,
                                            const NPVariant *args,
                                            uint32_t argCount,
                                            NPVariant *result);
128

Damien Fouilleul's avatar
Damien Fouilleul committed
129 130
    virtual InvokeResult getProperty(int index, NPVariant &result);
    virtual InvokeResult setProperty(int index, const NPVariant &value);
131
    virtual InvokeResult removeProperty(int index);
Damien Fouilleul's avatar
Damien Fouilleul committed
132 133
    virtual InvokeResult invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant &result);
    virtual InvokeResult invokeDefault(const NPVariant *args, uint32_t argCount, NPVariant &result);
134 135 136

    bool returnInvokeResult(InvokeResult result);

137 138
    static InvokeResult invokeResultString(const char *,NPVariant &);

139 140
    bool isPluginRunning()
    {
Jean-Paul Saman's avatar
Jean-Paul Saman committed
141
        return (_instance->pdata != NULL);
142 143 144 145 146 147
    }
    template<class T> T *getPrivate()
    {
        return reinterpret_cast<T *>(_instance->pdata);
    }

148 149 150 151 152 153
    NPP _instance;
};

template<class T> class RuntimeNPClass : public NPClass
{
public:
154 155 156 157 158 159 160
    static NPClass *getClass()
    {
        static NPClass *singleton = new RuntimeNPClass<T>;
        return singleton;
    }

protected:
161 162 163
    RuntimeNPClass();
    virtual ~RuntimeNPClass();

164
    template <class RuntimeNPObject> friend NPObject *RuntimeNPClassAllocate(NPP instance, NPClass *aClass);
165
    template <class RuntimeNPObject> friend bool RuntimeNPClassHasMethod(NPObject *npobj, NPIdentifier name);
166 167 168 169 170 171 172
    template <class RuntimeNPObject> friend bool RuntimeNPClassHasProperty(NPObject *npobj, NPIdentifier name);
    template <class RuntimeNPObject> friend bool RuntimeNPClassGetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result);
    template <class RuntimeNPObject> friend bool RuntimeNPClassSetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value);
    template <class RuntimeNPObject> friend bool RuntimeNPClassRemoveProperty(NPObject *npobj, NPIdentifier name);
    template <class RuntimeNPObject> friend bool RuntimeNPClassInvoke(NPObject *npobj, NPIdentifier name,
                                                                      const NPVariant *args, uint32_t argCount,
                                                                      NPVariant *result);
173 174 175 176 177 178 179 180 181 182 183

    RuntimeNPObject *create(NPP instance) const;

    int indexOfMethod(NPIdentifier name) const;
    int indexOfProperty(NPIdentifier name) const;

private:
    NPIdentifier *propertyIdentifiers;
    NPIdentifier *methodIdentifiers;
};

184 185 186 187 188 189 190
template<class T>
inline void RuntimeNPObject::InstantObj( NPObject *&obj )
{
    if( !obj )
        obj = NPN_CreateObject(_instance, RuntimeNPClass<T>::getClass());
}

191 192 193 194
template<class T>
static NPObject *RuntimeNPClassAllocate(NPP instance, NPClass *aClass)
{
    const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(aClass);
195
    return vClass->create(instance);
196 197 198 199 200
}

static void RuntimeNPClassDeallocate(NPObject *npobj)
{
    RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
201
    vObj->_class = NULL;
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
    delete vObj;
}

static void RuntimeNPClassInvalidate(NPObject *npobj)
{
    RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
    vObj->_instance = NULL;
}

template<class T>
static bool RuntimeNPClassHasMethod(NPObject *npobj, NPIdentifier name)
{
    const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
    return vClass->indexOfMethod(name) != -1;
}

template<class T>
static bool RuntimeNPClassHasProperty(NPObject *npobj, NPIdentifier name)
{
    const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
    return vClass->indexOfProperty(name) != -1;
}

template<class T>
static bool RuntimeNPClassGetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
{
228
    RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
229
    if( vObj->isValid() )
230
    {
231 232 233 234 235 236
        const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
        int index = vClass->indexOfProperty(name);
        if( index != -1 )
        {
            return vObj->returnInvokeResult(vObj->getProperty(index, *result));
        }
237 238 239 240 241 242 243
    }
    return false;
}

template<class T>
static bool RuntimeNPClassSetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
{
244
    RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
245
    if( vObj->isValid() )
246
    {
247 248 249 250 251 252
        const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
        int index = vClass->indexOfProperty(name);
        if( index != -1 )
        {
            return vObj->returnInvokeResult(vObj->setProperty(index, *value));
        }
253 254 255 256 257 258 259
    }
    return false;
}

template<class T>
static bool RuntimeNPClassRemoveProperty(NPObject *npobj, NPIdentifier name)
{
260
    RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
261
    if( vObj->isValid() )
262
    {
263 264 265 266 267 268
        const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
        int index = vClass->indexOfProperty(name);
        if( index != -1 )
        {
            return vObj->returnInvokeResult(vObj->removeProperty(index));
        }
269 270 271 272 273 274 275 276 277
    }
    return false;
}

template<class T>
static bool RuntimeNPClassInvoke(NPObject *npobj, NPIdentifier name,
                                    const NPVariant *args, uint32_t argCount,
                                    NPVariant *result)
{
278
    RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
279
    if( vObj->isValid() )
280
    {
281 282 283 284 285
        const RuntimeNPClass<T> *vClass = static_cast<RuntimeNPClass<T> *>(npobj->_class);
        int index = vClass->indexOfMethod(name);
        if( index != -1 )
        {
            return vObj->returnInvokeResult(vObj->invoke(index, args, argCount, *result));
286

287
        }
288 289 290 291 292 293 294 295 296 297
    }
    return false;
}

static bool RuntimeNPClassInvokeDefault(NPObject *npobj,
                                           const NPVariant *args,
                                           uint32_t argCount,
                                           NPVariant *result)
{
    RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
298
    if( vObj->isValid() )
299 300 301 302
    {
        return vObj->returnInvokeResult(vObj->invokeDefault(args, argCount, *result));
    }
    return false;
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
}

template<class T>
RuntimeNPClass<T>::RuntimeNPClass()
{
    // retreive property identifiers from names
    if( T::propertyCount > 0 )
    {
        propertyIdentifiers = new NPIdentifier[T::propertyCount];
        if( propertyIdentifiers )
            NPN_GetStringIdentifiers(const_cast<const NPUTF8**>(T::propertyNames),
                T::propertyCount, propertyIdentifiers);
    }

    // retreive method identifiers from names
    if( T::methodCount > 0 )
    {
        methodIdentifiers = new NPIdentifier[T::methodCount];
        if( methodIdentifiers )
            NPN_GetStringIdentifiers(const_cast<const NPUTF8**>(T::methodNames),
                T::methodCount, methodIdentifiers);
    }

    // fill in NPClass structure
    structVersion  = NP_CLASS_STRUCT_VERSION;
328 329 330 331 332 333 334 335 336 337
    allocate       = &RuntimeNPClassAllocate<T>;
    deallocate     = &RuntimeNPClassDeallocate;
    invalidate     = &RuntimeNPClassInvalidate;
    hasMethod      = &RuntimeNPClassHasMethod<T>;
    invoke         = &RuntimeNPClassInvoke<T>;
    invokeDefault  = &RuntimeNPClassInvokeDefault;
    hasProperty    = &RuntimeNPClassHasProperty<T>;
    getProperty    = &RuntimeNPClassGetProperty<T>;
    setProperty    = &RuntimeNPClassSetProperty<T>;
    removeProperty = &RuntimeNPClassRemoveProperty<T>;
338 339
    enumerate      = 0;
    construct      = 0;
340 341 342 343 344
}

template<class T>
RuntimeNPClass<T>::~RuntimeNPClass()
{
345 346
    delete[] propertyIdentifiers;
    delete[] methodIdentifiers;
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
}

template<class T>
RuntimeNPObject *RuntimeNPClass<T>::create(NPP instance) const
{
    return new T(instance, this);
}

template<class T>
int RuntimeNPClass<T>::indexOfMethod(NPIdentifier name) const
{
    if( methodIdentifiers )
    {
        for(int c=0; c< T::methodCount; ++c )
        {
            if( name == methodIdentifiers[c] )
                return c;
        }
    }
    return -1;
}

template<class T>
int RuntimeNPClass<T>::indexOfProperty(NPIdentifier name) const
{
    if( propertyIdentifiers )
    {
        for(int c=0; c< T::propertyCount; ++c )
        {
            if( name == propertyIdentifiers[c] )
                return c;
        }
    }
    return -1;
}

#endif