Home | History | Annotate | Download | only in plugin
      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 #ifndef PluginTest_h
     27 #define PluginTest_h
     28 
     29 #include <assert.h>
     30 #include <bindings/npfunctions.h>
     31 #include <map>
     32 #include <string>
     33 
     34 // Helper classes for implementing has_member
     35 typedef char (&no_tag)[1];
     36 typedef char (&yes_tag)[2];
     37 
     38 #define DEFINE_HAS_MEMBER_CHECK(member, returnType, argumentTypes) \
     39 template<typename T, returnType (T::*member) argumentTypes> struct pmf_##member##_helper {}; \
     40 template<typename T> no_tag has_member_##member##_helper(...); \
     41 template<typename T> yes_tag has_member_##member##_helper(pmf_##member##_helper<T, &T::member >*); \
     42 template<typename T> struct has_member_##member { \
     43 static const bool value = sizeof(has_member_##member##_helper<T>(0)) == sizeof(yes_tag); \
     44 };
     45 
     46 DEFINE_HAS_MEMBER_CHECK(hasMethod, bool, (NPIdentifier methodName));
     47 DEFINE_HAS_MEMBER_CHECK(invoke, bool, (NPIdentifier methodName, const NPVariant*, uint32_t, NPVariant* result));
     48 DEFINE_HAS_MEMBER_CHECK(invokeDefault, bool, (const NPVariant*, uint32_t, NPVariant* result));
     49 DEFINE_HAS_MEMBER_CHECK(hasProperty, bool, (NPIdentifier propertyName));
     50 DEFINE_HAS_MEMBER_CHECK(getProperty, bool, (NPIdentifier propertyName, NPVariant* result));
     51 DEFINE_HAS_MEMBER_CHECK(removeProperty, bool, (NPIdentifier propertyName));
     52 
     53 class PluginTest {
     54 public:
     55     static PluginTest* create(NPP, const std::string& identifier);
     56     virtual ~PluginTest();
     57 
     58     static void NP_Shutdown();
     59 
     60     // NPP functions.
     61     virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved);
     62     virtual NPError NPP_Destroy(NPSavedData**);
     63     virtual NPError NPP_SetWindow(NPWindow*);
     64     virtual NPError NPP_NewStream(NPMIMEType, NPStream*, NPBool seekable, uint16_t* stype);
     65     virtual NPError NPP_DestroyStream(NPStream*, NPReason);
     66     virtual int32_t NPP_WriteReady(NPStream*);
     67     virtual int32_t NPP_Write(NPStream*, int32_t offset, int32_t len, void* buffer);
     68     virtual int16_t NPP_HandleEvent(void* event);
     69     virtual bool NPP_URLNotify(const char* url, NPReason, void* notifyData);
     70     virtual NPError NPP_GetValue(NPPVariable, void* value);
     71     virtual NPError NPP_SetValue(NPNVariable, void *value);
     72 
     73     // NPN functions.
     74     NPError NPN_GetURL(const char* url, const char* target);
     75     NPError NPN_GetURLNotify(const char* url, const char* target, void* notifyData);
     76     NPError NPN_GetValue(NPNVariable, void* value);
     77     void NPN_InvalidateRect(NPRect* invalidRect);
     78     bool NPN_Invoke(NPObject *, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result);
     79     void* NPN_MemAlloc(uint32_t size);
     80 
     81     // NPRuntime NPN functions.
     82     NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name);
     83     NPIdentifier NPN_GetIntIdentifier(int32_t intid);
     84     bool NPN_IdentifierIsString(NPIdentifier);
     85     NPUTF8* NPN_UTF8FromIdentifier(NPIdentifier);
     86     int32_t NPN_IntFromIdentifier(NPIdentifier);
     87 
     88     NPObject* NPN_CreateObject(NPClass*);
     89     NPObject* NPN_RetainObject(NPObject*);
     90     void NPN_ReleaseObject(NPObject*);
     91     bool NPN_GetProperty(NPObject*, NPIdentifier propertyName, NPVariant* value);
     92     bool NPN_RemoveProperty(NPObject*, NPIdentifier propertyName);
     93     void NPN_ReleaseVariantValue(NPVariant*);
     94 
     95 #ifdef XP_MACOSX
     96     bool NPN_ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double *destX, double *destY, NPCoordinateSpace destSpace);
     97 #endif
     98 
     99     bool executeScript(const NPString*, NPVariant* result);
    100     void executeScript(const char*);
    101     void log(const char* format, ...);
    102 
    103     void registerNPShutdownFunction(void (*)());
    104 
    105     static void indicateTestFailure();
    106 
    107     template<typename TestClassTy> class Register {
    108     public:
    109         Register(const std::string& identifier)
    110         {
    111             registerCreateTestFunction(identifier, Register::create);
    112         }
    113 
    114     private:
    115         static PluginTest* create(NPP npp, const std::string& identifier)
    116         {
    117             return new TestClassTy(npp, identifier);
    118         }
    119     };
    120 
    121 protected:
    122     PluginTest(NPP npp, const std::string& identifier);
    123 
    124     // FIXME: A plug-in test shouldn't need to know about it's NPP. Make this private.
    125     NPP m_npp;
    126 
    127     const std::string& identifier() const { return m_identifier; }
    128 
    129     static NPNetscapeFuncs* netscapeFuncs();
    130 
    131     void waitUntilDone();
    132     void notifyDone();
    133 
    134     // NPObject helper template.
    135     template<typename T> struct Object : NPObject {
    136     public:
    137         static NPObject* create(PluginTest* pluginTest)
    138         {
    139             Object* object = static_cast<Object*>(pluginTest->NPN_CreateObject(npClass()));
    140 
    141             object->m_pluginTest = pluginTest;
    142             return object;
    143         }
    144 
    145         // These should never be called.
    146         bool hasMethod(NPIdentifier methodName)
    147         {
    148             assert(false);
    149             return false;
    150         }
    151 
    152         bool invoke(NPIdentifier methodName, const NPVariant*, uint32_t, NPVariant* result)
    153         {
    154             assert(false);
    155             return false;
    156         }
    157 
    158         bool invokeDefault(const NPVariant*, uint32_t, NPVariant* result)
    159         {
    160             assert(false);
    161             return false;
    162         }
    163 
    164         bool hasProperty(NPIdentifier propertyName)
    165         {
    166             assert(false);
    167             return false;
    168         }
    169 
    170         bool getProperty(NPIdentifier propertyName, NPVariant* result)
    171         {
    172             assert(false);
    173             return false;
    174         }
    175 
    176         bool removeProperty(NPIdentifier propertyName)
    177         {
    178             assert(false);
    179             return false;
    180         }
    181 
    182         // Helper functions.
    183         bool identifierIs(NPIdentifier identifier, const char* value)
    184         {
    185             return pluginTest()->NPN_GetStringIdentifier(value) == identifier;
    186         }
    187 
    188     protected:
    189         Object()
    190             : m_pluginTest(0)
    191         {
    192         }
    193 
    194         virtual ~Object()
    195         {
    196         }
    197 
    198         PluginTest* pluginTest() const { return m_pluginTest; }
    199 
    200     private:
    201         static NPObject* NP_Allocate(NPP npp, NPClass* aClass)
    202         {
    203             return new T;
    204         }
    205 
    206         static void NP_Deallocate(NPObject* npObject)
    207         {
    208             delete static_cast<T*>(npObject);
    209         }
    210 
    211         static bool NP_HasMethod(NPObject* npObject, NPIdentifier methodName)
    212         {
    213             return static_cast<T*>(npObject)->hasMethod(methodName);
    214         }
    215 
    216         static bool NP_Invoke(NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
    217         {
    218             return static_cast<T*>(npObject)->invoke(methodName, arguments, argumentCount, result);
    219         }
    220 
    221         static bool NP_InvokeDefault(NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result)
    222         {
    223             return static_cast<T*>(npObject)->invokeDefault(arguments, argumentCount, result);
    224         }
    225 
    226         static bool NP_HasProperty(NPObject* npObject, NPIdentifier propertyName)
    227         {
    228             return static_cast<T*>(npObject)->hasProperty(propertyName);
    229         }
    230 
    231         static bool NP_GetProperty(NPObject* npObject, NPIdentifier propertyName, NPVariant* result)
    232         {
    233             return static_cast<T*>(npObject)->getProperty(propertyName, result);
    234         }
    235 
    236         static bool NP_RemoveProperty(NPObject* npObject, NPIdentifier propertyName)
    237         {
    238             return static_cast<T*>(npObject)->removeProperty(propertyName);
    239         }
    240 
    241         static NPClass* npClass()
    242         {
    243             static NPClass npClass = {
    244                 NP_CLASS_STRUCT_VERSION,
    245                 NP_Allocate,
    246                 NP_Deallocate,
    247                 0, // NPClass::invalidate
    248                 has_member_hasMethod<T>::value ? NP_HasMethod : 0,
    249                 has_member_invoke<T>::value ? NP_Invoke : 0,
    250                 has_member_invokeDefault<T>::value ? NP_InvokeDefault : 0,
    251                 has_member_hasProperty<T>::value ? NP_HasProperty : 0,
    252                 has_member_getProperty<T>::value ? NP_GetProperty : 0,
    253                 0, // NPClass::setProperty
    254                 has_member_removeProperty<T>::value ? NP_RemoveProperty : 0,
    255                 0, // NPClass::enumerate
    256                 0  // NPClass::construct
    257             };
    258 
    259             return &npClass;
    260         };
    261 
    262         PluginTest* m_pluginTest;
    263     };
    264 
    265 private:
    266     typedef PluginTest* (*CreateTestFunction)(NPP, const std::string&);
    267 
    268     static void registerCreateTestFunction(const std::string&, CreateTestFunction);
    269     static std::map<std::string, CreateTestFunction>& createTestFunctions();
    270 
    271     std::string m_identifier;
    272 };
    273 
    274 #endif // PluginTest_h
    275