Home | History | Annotate | Download | only in jni
      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