• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
NP_Initialize(NPNetscapeFuncs * browserFuncs,NPPluginFuncs * pluginFuncs,void * java_env)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 
NP_Shutdown(void)146 void NP_Shutdown(void)
147 {
148 
149 }
150 
NP_GetMIMEDescription(void)151 const char *NP_GetMIMEDescription(void)
152 {
153     return "application/x-testbrowserplugin:tst:Test plugin mimetype is application/x-testbrowserplugin";
154 }
155 
NPP_New(NPMIMEType pluginType,NPP instance,uint16_t mode,int16_t argc,char * argn[],char * argv[],NPSavedData * saved)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 
NPP_Destroy(NPP instance,NPSavedData ** save)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 
NPP_SetWindow(NPP instance,NPWindow * window)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 
NPP_NewStream(NPP instance,NPMIMEType type,NPStream * stream,NPBool seekable,uint16_t * stype)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 
NPP_DestroyStream(NPP instance,NPStream * stream,NPReason reason)309 NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason)
310 {
311     return NPERR_NO_ERROR;
312 }
313 
NPP_WriteReady(NPP instance,NPStream * stream)314 int32_t NPP_WriteReady(NPP instance, NPStream* stream)
315 {
316     return 0;
317 }
318 
NPP_Write(NPP instance,NPStream * stream,int32_t offset,int32_t len,void * buffer)319 int32_t NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer)
320 {
321     return 0;
322 }
323 
NPP_StreamAsFile(NPP instance,NPStream * stream,const char * fname)324 void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
325 {
326 }
327 
NPP_Print(NPP instance,NPPrint * platformPrint)328 void NPP_Print(NPP instance, NPPrint* platformPrint)
329 {
330 }
331 
NPP_HandleEvent(NPP instance,void * event)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 
NPP_URLNotify(NPP instance,const char * url,NPReason reason,void * notifyData)407 void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
408 {
409 
410 }
411 
NP_GetValue(NPP instance,NPPVariable variable,void * value)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 
NPP_GetValue(NPP instance,NPPVariable variable,void * value)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 
NPP_SetValue(NPP instance,NPNVariable variable,void * value)464 NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
465 {
466     return NPERR_GENERIC_ERROR;
467 }
468 
469