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