1 /* 2 * Copyright 2008, The Android Open Source Project 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 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * 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 THE COPYRIGHT HOLDERS ``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 <stdlib.h> 27 #include <string.h> 28 #include <stdio.h> 29 #include "main.h" 30 #include "PluginObject.h" 31 #include "AnimationPlugin.h" 32 #include "AudioPlugin.h" 33 #include "BackgroundPlugin.h" 34 #include "FormPlugin.h" 35 #include "NavigationPlugin.h" 36 #include "PaintPlugin.h" 37 #include "VideoPlugin.h" 38 39 NPNetscapeFuncs* browser; 40 JavaVM* gVM; 41 42 #define EXPORT __attribute__((visibility("default"))) 43 44 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, 45 char* argn[], char* argv[], NPSavedData* saved); 46 NPError NPP_Destroy(NPP instance, NPSavedData** save); 47 NPError NPP_SetWindow(NPP instance, NPWindow* window); 48 NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, 49 NPBool seekable, uint16* stype); 50 NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason); 51 int32 NPP_WriteReady(NPP instance, NPStream* stream); 52 int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, 53 void* buffer); 54 void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname); 55 void NPP_Print(NPP instance, NPPrint* platformPrint); 56 int16 NPP_HandleEvent(NPP instance, void* event); 57 void NPP_URLNotify(NPP instance, const char* URL, NPReason reason, 58 void* notifyData); 59 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value); 60 NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value); 61 62 extern "C" { 63 EXPORT NPError NP_Initialize(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs, void *java_env); 64 EXPORT NPError NP_GetValue(NPP instance, NPPVariable variable, void *value); 65 EXPORT const char* NP_GetMIMEDescription(void); 66 EXPORT void NP_Shutdown(void); 67 }; 68 69 ANPAudioTrackInterfaceV0 gSoundI; 70 ANPBitmapInterfaceV0 gBitmapI; 71 ANPCanvasInterfaceV0 gCanvasI; 72 ANPEventInterfaceV0 gEventI; 73 ANPLogInterfaceV0 gLogI; 74 ANPPaintInterfaceV0 gPaintI; 75 ANPPathInterfaceV0 gPathI; 76 ANPSurfaceInterfaceV0 gSurfaceI; 77 ANPSystemInterfaceV0 gSystemI; 78 ANPTypefaceInterfaceV0 gTypefaceI; 79 ANPWindowInterfaceV0 gWindowI; 80 81 #define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0])) 82 #define DEBUG_PLUGIN_EVENTS 0 83 84 NPError NP_Initialize(NPNetscapeFuncs* browserFuncs, NPPluginFuncs* pluginFuncs, void *java_env) 85 { 86 // Make sure we have a function table equal or larger than we are built against. 87 if (browserFuncs->size < sizeof(NPNetscapeFuncs)) { 88 return NPERR_GENERIC_ERROR; 89 } 90 91 // Copy the function table (structure) 92 browser = (NPNetscapeFuncs*) malloc(sizeof(NPNetscapeFuncs)); 93 memcpy(browser, browserFuncs, sizeof(NPNetscapeFuncs)); 94 95 // Build the plugin function table 96 pluginFuncs->version = 11; 97 pluginFuncs->size = sizeof(pluginFuncs); 98 pluginFuncs->newp = NPP_New; 99 pluginFuncs->destroy = NPP_Destroy; 100 pluginFuncs->setwindow = NPP_SetWindow; 101 pluginFuncs->newstream = NPP_NewStream; 102 pluginFuncs->destroystream = NPP_DestroyStream; 103 pluginFuncs->asfile = NPP_StreamAsFile; 104 pluginFuncs->writeready = NPP_WriteReady; 105 pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write; 106 pluginFuncs->print = NPP_Print; 107 pluginFuncs->event = NPP_HandleEvent; 108 pluginFuncs->urlnotify = NPP_URLNotify; 109 pluginFuncs->getvalue = NPP_GetValue; 110 pluginFuncs->setvalue = NPP_SetValue; 111 112 static const struct { 113 NPNVariable v; 114 uint32_t size; 115 ANPInterface* i; 116 } gPairs[] = { 117 { kAudioTrackInterfaceV0_ANPGetValue, sizeof(gSoundI), &gSoundI }, 118 { kBitmapInterfaceV0_ANPGetValue, sizeof(gBitmapI), &gBitmapI }, 119 { kCanvasInterfaceV0_ANPGetValue, sizeof(gCanvasI), &gCanvasI }, 120 { kEventInterfaceV0_ANPGetValue, sizeof(gEventI), &gEventI }, 121 { kLogInterfaceV0_ANPGetValue, sizeof(gLogI), &gLogI }, 122 { kPaintInterfaceV0_ANPGetValue, sizeof(gPaintI), &gPaintI }, 123 { kPathInterfaceV0_ANPGetValue, sizeof(gPathI), &gPathI }, 124 { kSurfaceInterfaceV0_ANPGetValue, sizeof(gSurfaceI), &gSurfaceI }, 125 { kSystemInterfaceV0_ANPGetValue, sizeof(gSystemI), &gSystemI }, 126 { kTypefaceInterfaceV0_ANPGetValue, sizeof(gTypefaceI), &gTypefaceI }, 127 { kWindowInterfaceV0_ANPGetValue, sizeof(gWindowI), &gWindowI }, 128 }; 129 for (size_t i = 0; i < ARRAY_COUNT(gPairs); i++) { 130 gPairs[i].i->inSize = gPairs[i].size; 131 NPError err = browser->getvalue(NULL, gPairs[i].v, gPairs[i].i); 132 if (err) { 133 return err; 134 } 135 } 136 137 // store the JavaVM for the plugin 138 JNIEnv* env = (JNIEnv*)java_env; 139 env->GetJavaVM(&gVM); 140 141 return NPERR_NO_ERROR; 142 } 143 144 void NP_Shutdown(void) 145 { 146 147 } 148 149 const char *NP_GetMIMEDescription(void) 150 { 151 return "application/x-testbrowserplugin:tst:Test plugin mimetype is application/x-testbrowserplugin"; 152 } 153 154 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, 155 char* argn[], char* argv[], NPSavedData* saved) 156 { 157 158 /* BEGIN: STANDARD PLUGIN FRAMEWORK */ 159 PluginObject *obj = NULL; 160 161 // Scripting functions appeared in NPAPI version 14 162 if (browser->version >= 14) { 163 instance->pdata = browser->createobject (instance, getPluginClass()); 164 obj = static_cast<PluginObject*>(instance->pdata); 165 } 166 /* END: STANDARD PLUGIN FRAMEWORK */ 167 168 // select the drawing model based on user input 169 ANPDrawingModel model = kBitmap_ANPDrawingModel; 170 171 for (int i = 0; i < argc; i++) { 172 if (!strcmp(argn[i], "DrawingModel")) { 173 if (!strcmp(argv[i], "Bitmap")) { 174 model = kBitmap_ANPDrawingModel; 175 } 176 else if (!strcmp(argv[i], "Surface")) { 177 model = kSurface_ANPDrawingModel; 178 } 179 gLogI.log(kDebug_ANPLogType, "------ %p DrawingModel is %d", instance, model); 180 break; 181 } 182 } 183 184 // notify the plugin API of the drawing model we wish to use. This must be 185 // done prior to creating certain subPlugin objects (e.g. surfaceViews) 186 NPError err = browser->setvalue(instance, kRequestDrawingModel_ANPSetValue, 187 reinterpret_cast<void*>(model)); 188 if (err) { 189 gLogI.log(kError_ANPLogType, "request model %d err %d", model, err); 190 return err; 191 } 192 193 const char* path = gSystemI.getApplicationDataDirectory(); 194 if (path) { 195 gLogI.log(kDebug_ANPLogType, "Application data dir is %s", path); 196 } else { 197 gLogI.log(kError_ANPLogType, "Can't find Application data dir"); 198 } 199 200 // select the pluginType 201 for (int i = 0; i < argc; i++) { 202 if (!strcmp(argn[i], "PluginType")) { 203 if (!strcmp(argv[i], "Animation")) { 204 obj->pluginType = kAnimation_PluginType; 205 obj->activePlugin = new BallAnimation(instance); 206 } 207 else if (!strcmp(argv[i], "Audio")) { 208 obj->pluginType = kAudio_PluginType; 209 obj->activePlugin = new AudioPlugin(instance); 210 } 211 else if (!strcmp(argv[i], "Background")) { 212 obj->pluginType = kBackground_PluginType; 213 obj->activePlugin = new BackgroundPlugin(instance); 214 } 215 else if (!strcmp(argv[i], "Form")) { 216 obj->pluginType = kForm_PluginType; 217 obj->activePlugin = new FormPlugin(instance); 218 } 219 else if (!strcmp(argv[i], "Navigation")) { 220 obj->pluginType = kNavigation_PluginType; 221 obj->activePlugin = new NavigationPlugin(instance); 222 } 223 else if (!strcmp(argv[i], "Paint")) { 224 obj->pluginType = kPaint_PluginType; 225 obj->activePlugin = new PaintPlugin(instance); 226 } 227 else if (!strcmp(argv[i], "Video")) { 228 obj->pluginType = kVideo_PluginType; 229 obj->activePlugin = new VideoPlugin(instance); 230 } 231 gLogI.log(kDebug_ANPLogType, "------ %p PluginType is %d", instance, obj->pluginType); 232 break; 233 } 234 } 235 236 // if no pluginType is specified then default to Animation 237 if (!obj->pluginType) { 238 gLogI.log(kError_ANPLogType, "------ %p No PluginType attribute was found", instance); 239 obj->pluginType = kAnimation_PluginType; 240 obj->activePlugin = new BallAnimation(instance); 241 } 242 243 // check to ensure the pluginType supports the model 244 if (!obj->activePlugin->supportsDrawingModel(model)) { 245 gLogI.log(kError_ANPLogType, "------ %p Unsupported DrawingModel (%d)", instance, model); 246 return NPERR_GENERIC_ERROR; 247 } 248 249 // if the plugin uses the surface drawing model then set the java context 250 if (model == kSurface_ANPDrawingModel) { 251 SurfaceSubPlugin* surfacePlugin = static_cast<SurfaceSubPlugin*>(obj->activePlugin); 252 253 jobject context; 254 NPError err = browser->getvalue(instance, kJavaContext_ANPGetValue, 255 static_cast<void*>(&context)); 256 if (err) { 257 gLogI.log(kError_ANPLogType, "request context err: %d", err); 258 return err; 259 } 260 261 surfacePlugin->setContext(context); 262 } 263 264 265 return NPERR_NO_ERROR; 266 } 267 268 NPError NPP_Destroy(NPP instance, NPSavedData** save) 269 { 270 PluginObject *obj = (PluginObject*) instance->pdata; 271 if (obj) { 272 delete obj->activePlugin; 273 browser->releaseobject(&obj->header); 274 } 275 276 return NPERR_NO_ERROR; 277 } 278 279 NPError NPP_SetWindow(NPP instance, NPWindow* window) 280 { 281 PluginObject *obj = (PluginObject*) instance->pdata; 282 283 // Do nothing if browser didn't support NPN_CreateObject which would have created the PluginObject. 284 if (obj != NULL) { 285 obj->window = window; 286 } 287 288 browser->invalidaterect(instance, NULL); 289 290 return NPERR_NO_ERROR; 291 } 292 293 NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) 294 { 295 *stype = NP_ASFILEONLY; 296 return NPERR_NO_ERROR; 297 } 298 299 NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) 300 { 301 return NPERR_NO_ERROR; 302 } 303 304 int32 NPP_WriteReady(NPP instance, NPStream* stream) 305 { 306 return 0; 307 } 308 309 int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer) 310 { 311 return 0; 312 } 313 314 void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) 315 { 316 } 317 318 void NPP_Print(NPP instance, NPPrint* platformPrint) 319 { 320 } 321 322 int16 NPP_HandleEvent(NPP instance, void* event) 323 { 324 PluginObject *obj = reinterpret_cast<PluginObject*>(instance->pdata); 325 const ANPEvent* evt = reinterpret_cast<const ANPEvent*>(event); 326 327 #if DEBUG_PLUGIN_EVENTS 328 switch (evt->eventType) { 329 case kDraw_ANPEventType: 330 331 if (evt->data.draw.model == kBitmap_ANPDrawingModel) { 332 333 static ANPBitmapFormat currentFormat = -1; 334 if (evt->data.draw.data.bitmap.format != currentFormat) { 335 currentFormat = evt->data.draw.data.bitmap.format; 336 gLogI.log(kDebug_ANPLogType, "---- %p Draw (bitmap)" 337 " clip=%d,%d,%d,%d format=%d", instance, 338 evt->data.draw.clip.left, 339 evt->data.draw.clip.top, 340 evt->data.draw.clip.right, 341 evt->data.draw.clip.bottom, 342 evt->data.draw.data.bitmap.format); 343 } 344 } 345 break; 346 347 case kKey_ANPEventType: 348 gLogI.log(kDebug_ANPLogType, "---- %p Key action=%d" 349 " code=%d vcode=%d unichar=%d repeat=%d mods=%x", instance, 350 evt->data.key.action, 351 evt->data.key.nativeCode, 352 evt->data.key.virtualCode, 353 evt->data.key.unichar, 354 evt->data.key.repeatCount, 355 evt->data.key.modifiers); 356 break; 357 358 case kLifecycle_ANPEventType: 359 gLogI.log(kDebug_ANPLogType, "---- %p Lifecycle action=%d", 360 instance, evt->data.lifecycle.action); 361 break; 362 363 case kTouch_ANPEventType: 364 gLogI.log(kDebug_ANPLogType, "---- %p Touch action=%d [%d %d]", 365 instance, evt->data.touch.action, evt->data.touch.x, 366 evt->data.touch.y); 367 break; 368 369 case kMouse_ANPEventType: 370 gLogI.log(kDebug_ANPLogType, "---- %p Mouse action=%d [%d %d]", 371 instance, evt->data.mouse.action, evt->data.mouse.x, 372 evt->data.mouse.y); 373 break; 374 375 case kVisibleRect_ANPEventType: 376 gLogI.log(kDebug_ANPLogType, "---- %p VisibleRect [%d %d %d %d]", 377 instance, evt->data.visibleRect.rect.left, evt->data.visibleRect.rect.top, 378 evt->data.visibleRect.rect.right, evt->data.visibleRect.rect.bottom); 379 break; 380 381 default: 382 gLogI.log(kError_ANPLogType, "---- %p Unknown Event [%d]", 383 instance, evt->eventType); 384 break; 385 } 386 #endif 387 388 if(!obj->activePlugin) { 389 gLogI.log(kError_ANPLogType, "the active plugin is null."); 390 return 0; // unknown or unhandled event 391 } 392 else { 393 return obj->activePlugin->handleEvent(evt); 394 } 395 } 396 397 void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) 398 { 399 400 } 401 402 EXPORT NPError NP_GetValue(NPP instance, NPPVariable variable, void *value) { 403 404 if (variable == NPPVpluginNameString) { 405 const char **str = (const char **)value; 406 *str = "Test Plugin"; 407 return NPERR_NO_ERROR; 408 } 409 410 if (variable == NPPVpluginDescriptionString) { 411 const char **str = (const char **)value; 412 *str = "Description of Test Plugin"; 413 return NPERR_NO_ERROR; 414 } 415 416 return NPERR_GENERIC_ERROR; 417 } 418 419 NPError NPP_GetValue(NPP instance, NPPVariable variable, void* value) 420 { 421 if (variable == NPPVpluginScriptableNPObject) { 422 void **v = (void **)value; 423 PluginObject *obj = (PluginObject*) instance->pdata; 424 425 if (obj) 426 browser->retainobject(&obj->header); 427 428 *v = &(obj->header); 429 return NPERR_NO_ERROR; 430 } 431 432 if (variable == kJavaSurface_ANPGetValue) { 433 //get the surface sub-plugin 434 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 435 if (obj && obj->activePlugin) { 436 437 if(obj->activePlugin->supportsDrawingModel(kSurface_ANPDrawingModel)) { 438 SurfaceSubPlugin* plugin = static_cast<SurfaceSubPlugin*>(obj->activePlugin); 439 jobject* surface = static_cast<jobject*>(value); 440 *surface = plugin->getSurface(); 441 return NPERR_NO_ERROR; 442 } else { 443 gLogI.log(kError_ANPLogType, 444 "-- %p Tried to retrieve surface for non-surface plugin", 445 instance); 446 } 447 } 448 } 449 450 return NPERR_GENERIC_ERROR; 451 } 452 453 NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) 454 { 455 return NPERR_GENERIC_ERROR; 456 } 457 458