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