nporuntime.h 9.57 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-2012  VLC authors and VideoLAN
Konstantin Pavlov's avatar
Konstantin Pavlov committed
6
 * $Id$
7 8
 *
 * Authors: Damien Fouilleul <damien.fouilleul@laposte.net>
9
 *          JP Dinger <jpd@videolan.org>
10
 *          Hugo Beauzée-Luyssen <hugo@beauzee.fr>
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 *
 * 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
*/

34
//on windows, to avoid including <npapi.h>
35 36 37
//from Microsoft SDK (rather then from Mozilla SDK),
//#include it indirectly via <npfunctions.h>
#include <npfunctions.h>
38
#include <npruntime.h>
39
#include <stdlib.h>
40

41 42
#include <memory>

43 44
#include "utils.hpp"

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

52 53 54
    bool isValid()
    {
        return _instance != NULL;
55
    }
56 57 58 59 60 61 62 63 64 65 66

    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 */
    };

67
    virtual InvokeResult getProperty(int index, npapi::OutVariant &result);
68 69
    virtual InvokeResult setProperty(int index, const NPVariant &value);
    virtual InvokeResult removeProperty(int index);
70 71
    virtual InvokeResult invoke(int index, const NPVariant *args, uint32_t argCount, npapi::OutVariant &result);
    virtual InvokeResult invokeDefault(const NPVariant *args, uint32_t argCount, npapi::OutVariant &result);
72 73 74

    bool returnInvokeResult(InvokeResult result);

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

    void operator delete(void *p)
    {
87 88 89
        NPN_MemFree(p);
    };

90 91 92 93
    RuntimeNPObject(NPP instance, const NPClass *aClass) :
        _instance(instance)
    {
        _class = const_cast<NPClass *>(aClass);
94
        referenceCount = 1;
95
    };
96
    virtual ~RuntimeNPObject() = default;
97

98 99
    bool isPluginRunning()
    {
Jean-Paul Saman's avatar
Jean-Paul Saman committed
100
        return (_instance->pdata != NULL);
101 102 103 104 105 106
    }
    template<class T> T *getPrivate()
    {
        return reinterpret_cast<T *>(_instance->pdata);
    }

107
    NPP _instance;
108 109 110

    template <typename>
    friend class RuntimeNPClass;
111 112
};

113 114
template<class T>
class RuntimeNPClass : public NPClass
115 116
{
public:
117 118 119 120 121 122 123
    static NPClass *getClass()
    {
        static NPClass *singleton = new RuntimeNPClass<T>;
        return singleton;
    }

protected:
124 125 126
    RuntimeNPClass();
    virtual ~RuntimeNPClass();

127 128
    static NPObject *Allocate(NPP instance, NPClass *aClass)
    {
129
        return new T(instance, aClass);
130
    }
131

132 133 134 135 136
    static void Deallocate(NPObject *npobj)
    {
        RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
        delete vObj;
    }
137

138 139 140 141 142
    static void Invalidate(NPObject *npobj)
    {
        RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
        vObj->_instance = NULL;
    }
143

144 145 146 147 148
    static bool HasMethod(NPObject *npobj, NPIdentifier name)
    {
        const RuntimeNPClass* vClass = static_cast<RuntimeNPClass*>(npobj->_class);
        return vClass->indexOfMethod(name) != -1;
    }
149

150 151 152 153 154
    static bool HasProperty(NPObject *npobj, NPIdentifier name)
    {
        const RuntimeNPClass* vClass = static_cast<RuntimeNPClass*>(npobj->_class);
        return vClass->indexOfProperty(name) != -1;
    }
155

156
    static bool GetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
157
    {
158 159
        RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
        if( vObj->isValid() )
160
        {
161 162 163 164
            const RuntimeNPClass* vClass = static_cast<RuntimeNPClass*>(npobj->_class);
            int index = vClass->indexOfProperty(name);
            if( index != -1 )
            {
165 166
                npapi::OutVariant res{ result };
                return vObj->returnInvokeResult(vObj->getProperty(index, res));
167
            }
168
        }
169
        return false;
170 171
    }

172
    static bool SetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value)
173
    {
174 175
        RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
        if( vObj->isValid() )
176
        {
177 178 179 180 181 182
            const RuntimeNPClass* vClass = static_cast<RuntimeNPClass*>(npobj->_class);
            int index = vClass->indexOfProperty(name);
            if( index != -1 )
            {
                return vObj->returnInvokeResult(vObj->setProperty(index, *value));
            }
183
        }
184
        return false;
185 186
    }

187
    static bool RemoveProperty(NPObject *npobj, NPIdentifier name)
188
    {
189 190
        RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
        if( vObj->isValid() )
191
        {
192 193 194 195 196 197
            const RuntimeNPClass* vClass = static_cast<RuntimeNPClass*>(npobj->_class);
            int index = vClass->indexOfProperty(name);
            if( index != -1 )
            {
                return vObj->returnInvokeResult(vObj->removeProperty(index));
            }
198
        }
199
        return false;
200 201
    }

202 203 204
    static bool ClassInvoke(NPObject *npobj, NPIdentifier name,
                                        const NPVariant *args, uint32_t argCount,
                                        NPVariant *result)
205
    {
206 207
        RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
        if( vObj->isValid() )
208
        {
209 210 211 212
            const RuntimeNPClass* vClass = static_cast<RuntimeNPClass*>(npobj->_class);
            int index = vClass->indexOfMethod(name);
            if( index != -1 )
            {
213 214
                npapi::OutVariant res{ result };
                return vObj->returnInvokeResult(vObj->invoke(index, args, argCount, res));
215
            }
216
        }
217
        return false;
218 219
    }

220 221 222 223
    static bool InvokeDefault(NPObject *npobj,
                                               const NPVariant *args,
                                               uint32_t argCount,
                                               NPVariant *result)
224
    {
225 226 227
        RuntimeNPObject *vObj = static_cast<RuntimeNPObject *>(npobj);
        if( vObj->isValid() )
        {
228 229
            npapi::OutVariant res{ result };
            return vObj->returnInvokeResult(vObj->invokeDefault(args, argCount, res ));
230 231
        }
        return false;
232
    }
233 234 235 236 237

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

private:
238 239
    std::unique_ptr<NPIdentifier[]> propertyIdentifiers;
    std::unique_ptr<NPIdentifier[]> methodIdentifiers;
240 241 242 243 244 245 246
};

template<class T>
inline void RuntimeNPObject::InstantObj( NPObject *&obj )
{
    if( !obj )
        obj = NPN_CreateObject(_instance, RuntimeNPClass<T>::getClass());
247 248 249 250 251 252 253 254
}

template<class T>
RuntimeNPClass<T>::RuntimeNPClass()
{
    // retreive property identifiers from names
    if( T::propertyCount > 0 )
    {
255 256 257
        propertyIdentifiers.reset( new NPIdentifier[T::propertyCount] );
        NPN_GetStringIdentifiers(const_cast<const NPUTF8**>(T::propertyNames),
            T::propertyCount, propertyIdentifiers.get() );
258 259 260 261 262
    }

    // retreive method identifiers from names
    if( T::methodCount > 0 )
    {
263 264 265
        methodIdentifiers.reset( new NPIdentifier[T::methodCount] );
        NPN_GetStringIdentifiers(const_cast<const NPUTF8**>(T::methodNames),
            T::methodCount, methodIdentifiers.get() );
266 267 268 269
    }

    // fill in NPClass structure
    structVersion  = NP_CLASS_STRUCT_VERSION;
270 271 272 273 274 275 276 277 278 279
    allocate       = &Allocate;
    deallocate     = &Deallocate;
    invalidate     = &Invalidate;
    hasMethod      = &HasMethod;
    invoke         = &ClassInvoke;
    invokeDefault  = &InvokeDefault;
    hasProperty    = &HasProperty;
    getProperty    = &GetProperty;
    setProperty    = &SetProperty;
    removeProperty = &RemoveProperty;
280 281
    enumerate      = 0;
    construct      = 0;
282 283 284 285 286 287 288 289 290 291 292 293
}

template<class T>
RuntimeNPClass<T>::~RuntimeNPClass()
{
}

template<class T>
int RuntimeNPClass<T>::indexOfMethod(NPIdentifier name) const
{
    if( methodIdentifiers )
    {
294
        for(int c = 0; c< T::methodCount; ++c )
295 296 297 298 299 300 301 302 303 304 305 306 307
        {
            if( name == methodIdentifiers[c] )
                return c;
        }
    }
    return -1;
}

template<class T>
int RuntimeNPClass<T>::indexOfProperty(NPIdentifier name) const
{
    if( propertyIdentifiers )
    {
308
        for(int c = 0; c< T::propertyCount; ++c )
309 310 311 312 313 314 315 316 317
        {
            if( name == propertyIdentifiers[c] )
                return c;
        }
    }
    return -1;
}

#endif