• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007 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. ``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 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 "PluginObject.h"
27 
28 #include "PluginTest.h"
29 #include <cstdlib>
30 #include <string>
31 
32 #ifdef XP_UNIX
33 #include <X11/Xlib.h>
34 #endif
35 
36 #if !defined(NP_NO_CARBON) && defined(QD_HEADERS_ARE_PRIVATE) && QD_HEADERS_ARE_PRIVATE
37 extern "C" void GlobalToLocal(Point*);
38 #endif
39 
40 using namespace std;
41 
42 #define CRASH() do { \
43     *(int *)(uintptr_t)0xbbadbeef = 0; \
44     ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
45 } while(false)
46 
47 static bool getEntryPointsWasCalled;
48 static bool initializeWasCalled;
49 
50 #if defined(XP_WIN)
51 #define STDCALL __stdcall
52 
strcasecmp(const char * s1,const char * s2)53 static inline int strcasecmp(const char* s1, const char* s2)
54 {
55     return _stricmp(s1, s2);
56 }
57 
58 #else
59 #define STDCALL
60 #endif
61 
62 extern "C" {
63 NPError STDCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs);
64 }
65 
66 // Entry points
67 extern "C"
NP_Initialize(NPNetscapeFuncs * browserFuncs,NPPluginFuncs * pluginFuncs)68 NPError STDCALL NP_Initialize(NPNetscapeFuncs *browserFuncs
69 #ifdef XP_UNIX
70                               , NPPluginFuncs *pluginFuncs
71 #endif
72                               )
73 {
74     initializeWasCalled = true;
75 
76 #if defined(XP_WIN)
77     // Simulate Flash and QuickTime's behavior of crashing when NP_Initialize is called before NP_GetEntryPoints.
78     if (!getEntryPointsWasCalled)
79         CRASH();
80 #endif
81 
82     browser = browserFuncs;
83 
84 #ifdef XP_UNIX
85     return NP_GetEntryPoints(pluginFuncs);
86 #else
87     return NPERR_NO_ERROR;
88 #endif
89 }
90 
91 extern "C"
NP_GetEntryPoints(NPPluginFuncs * pluginFuncs)92 NPError STDCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs)
93 {
94     getEntryPointsWasCalled = true;
95 
96 #ifdef XP_MACOSX
97     // Simulate Silverlight's behavior of crashing when NP_GetEntryPoints is called before NP_Initialize.
98     if (!initializeWasCalled)
99         CRASH();
100 #endif
101 
102     pluginFunctions = pluginFuncs;
103 
104     pluginFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
105     pluginFuncs->size = sizeof(pluginFuncs);
106     pluginFuncs->newp = NPP_New;
107     pluginFuncs->destroy = NPP_Destroy;
108     pluginFuncs->setwindow = NPP_SetWindow;
109     pluginFuncs->newstream = NPP_NewStream;
110     pluginFuncs->destroystream = NPP_DestroyStream;
111     pluginFuncs->asfile = NPP_StreamAsFile;
112     pluginFuncs->writeready = NPP_WriteReady;
113     pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write;
114     pluginFuncs->print = NPP_Print;
115     pluginFuncs->event = NPP_HandleEvent;
116     pluginFuncs->urlnotify = NPP_URLNotify;
117     pluginFuncs->getvalue = NPP_GetValue;
118     pluginFuncs->setvalue = NPP_SetValue;
119 
120     return NPERR_NO_ERROR;
121 }
122 
123 extern "C"
NP_Shutdown(void)124 void STDCALL NP_Shutdown(void)
125 {
126     PluginTest::NP_Shutdown();
127 }
128 
129 static void executeScript(const PluginObject* obj, const char* script);
130 
NPP_New(NPMIMEType pluginType,NPP instance,uint16_t mode,int16_t argc,char * argn[],char * argv[],NPSavedData * saved)131 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved)
132 {
133     bool forceCarbon = false;
134 
135 #ifdef XP_MACOSX
136     NPEventModel eventModel;
137 
138     // Always turn on the CG model
139     NPBool supportsCoreGraphics;
140     if (browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) != NPERR_NO_ERROR)
141         supportsCoreGraphics = false;
142 
143     if (!supportsCoreGraphics)
144         return NPERR_INCOMPATIBLE_VERSION_ERROR;
145 
146     NPDrawingModel drawingModelToUse = NPDrawingModelCoreGraphics;
147 
148     NPBool supportsCoreAnimation;
149     if (browser->getvalue(instance, NPNVsupportsCoreAnimationBool, &supportsCoreAnimation) != NPERR_NO_ERROR)
150         supportsCoreAnimation = false;
151 
152 #ifndef NP_NO_CARBON
153     NPBool supportsCarbon = false;
154 #endif
155     NPBool supportsCocoa = false;
156 
157 #ifndef NP_NO_CARBON
158     // A browser that doesn't know about NPNVsupportsCarbonBool is one that only supports Carbon event model.
159     if (browser->getvalue(instance, NPNVsupportsCarbonBool, &supportsCarbon) != NPERR_NO_ERROR)
160         supportsCarbon = true;
161 #endif
162 
163     if (browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoa) != NPERR_NO_ERROR)
164         supportsCocoa = false;
165 
166     if (supportsCocoa && !forceCarbon) {
167         eventModel = NPEventModelCocoa;
168 #ifndef NP_NO_CARBON
169     } else if (supportsCarbon) {
170         eventModel = NPEventModelCarbon;
171 #endif
172     } else {
173         return NPERR_INCOMPATIBLE_VERSION_ERROR;
174     }
175 
176      browser->setvalue(instance, NPPVpluginEventModel, (void *)eventModel);
177 #endif // XP_MACOSX
178 
179     PluginObject* obj = (PluginObject*)browser->createobject(instance, getPluginClass());
180     instance->pdata = obj;
181 
182 #ifdef XP_MACOSX
183     obj->eventModel = eventModel;
184 #if !defined(BUILDING_ON_TIGER)
185     obj->coreAnimationLayer = 0;
186 #endif
187 #endif // XP_MACOSX
188 
189     string testIdentifier;
190     const char* onNewScript = 0;
191 
192     for (int i = 0; i < argc; i++) {
193         if (strcasecmp(argn[i], "test") == 0)
194             testIdentifier = argv[i];
195         if (strcasecmp(argn[i], "onstreamload") == 0 && !obj->onStreamLoad)
196             obj->onStreamLoad = strdup(argv[i]);
197         else if (strcasecmp(argn[i], "onStreamDestroy") == 0 && !obj->onStreamDestroy)
198             obj->onStreamDestroy = strdup(argv[i]);
199         else if (strcasecmp(argn[i], "onURLNotify") == 0 && !obj->onURLNotify)
200             obj->onURLNotify = strdup(argv[i]);
201         else if (strcasecmp(argn[i], "src") == 0 &&
202                  strcasecmp(argv[i], "data:application/x-webkit-test-netscape,returnerrorfromnewstream") == 0)
203             obj->returnErrorFromNewStream = TRUE;
204         else if (strcasecmp(argn[i], "src") == 0 &&
205                  strcasecmp(argv[i], "data:application/x-webkit-test-netscape,alertwhenloaded") == 0)
206             executeScript(obj, "alert('Plugin Loaded!')");
207         else if (strcasecmp(argn[i], "onSetWindow") == 0 && !obj->onSetWindow)
208             obj->onSetWindow = strdup(argv[i]);
209         else if (strcasecmp(argn[i], "onNew") == 0 && !onNewScript)
210             onNewScript = argv[i];
211         else if (strcasecmp(argn[i], "onPaintEvent") == 0 && !obj->onPaintEvent)
212             obj->onPaintEvent = strdup(argv[i]);
213         else if (strcasecmp(argn[i], "logfirstsetwindow") == 0)
214             obj->logSetWindow = TRUE;
215         else if (strcasecmp(argn[i], "testnpruntime") == 0)
216             testNPRuntime(instance);
217         else if (strcasecmp(argn[i], "forcecarbon") == 0)
218             forceCarbon = true;
219         else if (strcasecmp(argn[i], "logSrc") == 0) {
220             for (int i = 0; i < argc; i++)
221                 if (strcasecmp(argn[i], "src") == 0)
222                     pluginLog(instance, "src: %s", argv[i]);
223         } else if (strcasecmp(argn[i], "cleardocumentduringnew") == 0)
224             executeScript(obj, "document.body.innerHTML = ''");
225         else if (!strcasecmp(argn[i], "ondestroy"))
226             obj->onDestroy = strdup(argv[i]);
227         else if (strcasecmp(argn[i], "testwindowopen") == 0)
228             obj->testWindowOpen = TRUE;
229         else if (strcasecmp(argn[i], "drawingmodel") == 0) {
230 #if defined(XP_MACOSX) && !defined(BUILDING_ON_TIGER)
231             const char* value = argv[i];
232             if (strcasecmp(value, "coreanimation") == 0) {
233                 if (supportsCoreAnimation)
234                     drawingModelToUse = NPDrawingModelCoreAnimation;
235                 else
236                     return NPERR_INCOMPATIBLE_VERSION_ERROR;
237              } else if (strcasecmp(value, "coregraphics") == 0) {
238                 if (supportsCoreGraphics)
239                     drawingModelToUse = NPDrawingModelCoreGraphics;
240                 else
241                     return NPERR_INCOMPATIBLE_VERSION_ERROR;
242              } else
243                 return NPERR_INCOMPATIBLE_VERSION_ERROR;
244 #endif
245         } else if (strcasecmp(argn[i], "testGetURLOnDestroy") == 0) {
246 #if defined(XP_WIN)
247             // FIXME: When https://bugs.webkit.org/show_bug.cgi?id=41831 is fixed, this #ifdef can be removed.
248             obj->testGetURLOnDestroy = TRUE;
249 #endif
250         } else if (!strcasecmp(argn[i], "src") && strstr(argv[i], "plugin-document-has-focus.pl"))
251             obj->testKeyboardFocusForPlugins = TRUE;
252         else if (!strcasecmp(argn[i], "evaluatescript")) {
253             char* script = argv[i];
254             if (script == strstr(script, "mouse::")) {
255                 obj->mouseDownForEvaluateScript = true;
256                 obj->evaluateScriptOnMouseDownOrKeyDown = strdup(script + sizeof("mouse::") - 1);
257             } else if (script == strstr(script, "key::")) {
258                 obj->evaluateScriptOnMouseDownOrKeyDown = strdup(script + sizeof("key::") - 1);
259             }
260             // When testing evaluate script on mouse-down or key-down, allow event logging to handle events.
261             if (obj->evaluateScriptOnMouseDownOrKeyDown)
262                 obj->eventLogging = true;
263         } else if (!strcasecmp(argn[i], "windowedPlugin")) {
264             void* windowed = 0;
265             if (!strcasecmp(argv[i], "false") || !strcasecmp(argv[i], "0"))
266                 windowed = 0;
267             else if (!strcasecmp(argv[i], "true") || !strcasecmp(argv[i], "1"))
268                 windowed = reinterpret_cast<void*>(1);
269             else
270                 assert(false);
271             browser->setvalue(instance, NPPVpluginWindowBool, windowed);
272         }
273     }
274 
275 #ifdef XP_MACOSX
276     browser->setvalue(instance, NPPVpluginDrawingModel, (void *)drawingModelToUse);
277 #if !defined(BUILDING_ON_TIGER)
278     if (drawingModelToUse == NPDrawingModelCoreAnimation)
279         obj->coreAnimationLayer = createCoreAnimationLayer();
280 #endif
281 #endif
282 
283     browser->getvalue(instance, NPNVprivateModeBool, (void *)&obj->cachedPrivateBrowsingMode);
284 
285     obj->pluginTest = PluginTest::create(instance, testIdentifier);
286 
287     if (!obj->pluginTest) {
288         pluginLog(instance, "NPP_New: Could not find a test named \"%s\", maybe its .cpp file wasn't added to the build system?", testIdentifier.c_str());
289         return NPERR_GENERIC_ERROR;
290     }
291 
292 #ifdef XP_UNIX
293     // On Unix, plugins only get events if they are windowless.
294     browser->setvalue(instance, NPPVpluginWindowBool, 0);
295 #endif
296 
297     if (onNewScript)
298         executeScript(obj, onNewScript);
299 
300     return obj->pluginTest->NPP_New(pluginType, mode, argc, argn, argv, saved);
301 }
302 
NPP_Destroy(NPP instance,NPSavedData ** save)303 NPError NPP_Destroy(NPP instance, NPSavedData **save)
304 {
305     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
306     if (obj) {
307         if (obj->testGetURLOnDestroy)
308             browser->geturlnotify(obj->npp, "about:blank", "", 0);
309 
310         if (obj->onDestroy) {
311             executeScript(obj, obj->onDestroy);
312             free(obj->onDestroy);
313         }
314 
315         if (obj->onStreamLoad)
316             free(obj->onStreamLoad);
317 
318         if (obj->onStreamDestroy)
319             free(obj->onStreamDestroy);
320 
321         if (obj->onURLNotify)
322             free(obj->onURLNotify);
323 
324         if (obj->onSetWindow)
325             free(obj->onSetWindow);
326 
327         if (obj->onPaintEvent)
328             free(obj->onPaintEvent);
329 
330         if (obj->logDestroy)
331             pluginLog(instance, "NPP_Destroy");
332 
333 #if defined(XP_MACOSX) && !defined(BUILDING_ON_TIGER)
334         if (obj->coreAnimationLayer)
335             CFRelease(obj->coreAnimationLayer);
336 #endif
337 
338         obj->pluginTest->NPP_Destroy(save);
339 
340         browser->releaseobject(&obj->header);
341     }
342     return NPERR_NO_ERROR;
343 }
344 
NPP_SetWindow(NPP instance,NPWindow * window)345 NPError NPP_SetWindow(NPP instance, NPWindow *window)
346 {
347     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
348 
349     if (obj) {
350         obj->lastWindow = *window;
351 
352         if (obj->logSetWindow) {
353             pluginLog(instance, "NPP_SetWindow: %d %d", (int)window->width, (int)window->height);
354             obj->logSetWindow = FALSE;
355         }
356 
357         if (obj->onSetWindow)
358             executeScript(obj, obj->onSetWindow);
359 
360         if (obj->testWindowOpen) {
361             testWindowOpen(instance);
362             obj->testWindowOpen = FALSE;
363         }
364 
365         if (obj->testKeyboardFocusForPlugins) {
366             obj->eventLogging = true;
367             executeScript(obj, "eventSender.keyDown('A');");
368         }
369     }
370 
371     return obj->pluginTest->NPP_SetWindow(instance, window);
372 }
373 
executeScript(const PluginObject * obj,const char * script)374 static void executeScript(const PluginObject* obj, const char* script)
375 {
376     NPObject *windowScriptObject;
377     browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
378 
379     NPString npScript;
380     npScript.UTF8Characters = script;
381     npScript.UTF8Length = strlen(script);
382 
383     NPVariant browserResult;
384     browser->evaluate(obj->npp, windowScriptObject, &npScript, &browserResult);
385     browser->releasevariantvalue(&browserResult);
386 }
387 
NPP_NewStream(NPP instance,NPMIMEType type,NPStream * stream,NPBool seekable,uint16_t * stype)388 NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16_t *stype)
389 {
390     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
391     obj->stream = stream;
392     *stype = NP_NORMAL;
393 
394     if (obj->returnErrorFromNewStream)
395         return NPERR_GENERIC_ERROR;
396 
397     if (browser->version >= NPVERS_HAS_RESPONSE_HEADERS)
398         notifyStream(obj, stream->url, stream->headers);
399 
400     if (obj->onStreamLoad)
401         executeScript(obj, obj->onStreamLoad);
402 
403     return NPERR_NO_ERROR;
404 }
405 
NPP_DestroyStream(NPP instance,NPStream * stream,NPReason reason)406 NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason)
407 {
408     PluginObject* obj = (PluginObject*)instance->pdata;
409 
410     if (obj->onStreamDestroy) {
411         NPObject* windowObject = 0;
412         NPError error = browser->getvalue(instance, NPNVWindowNPObject, &windowObject);
413 
414         if (error == NPERR_NO_ERROR) {
415             NPVariant onStreamDestroyVariant;
416             if (browser->getproperty(instance, windowObject, browser->getstringidentifier(obj->onStreamDestroy), &onStreamDestroyVariant)) {
417                 if (NPVARIANT_IS_OBJECT(onStreamDestroyVariant)) {
418                     NPObject* onStreamDestroyFunction = NPVARIANT_TO_OBJECT(onStreamDestroyVariant);
419 
420                     NPVariant reasonVariant;
421                     INT32_TO_NPVARIANT(reason, reasonVariant);
422 
423                     NPVariant result;
424                     browser->invokeDefault(instance, onStreamDestroyFunction, &reasonVariant, 1, &result);
425                     browser->releasevariantvalue(&result);
426                 }
427                 browser->releasevariantvalue(&onStreamDestroyVariant);
428             }
429             browser->releaseobject(windowObject);
430         }
431     }
432 
433     return obj->pluginTest->NPP_DestroyStream(stream, reason);
434 }
435 
NPP_WriteReady(NPP instance,NPStream * stream)436 int32_t NPP_WriteReady(NPP instance, NPStream *stream)
437 {
438     return 4096;
439 }
440 
NPP_Write(NPP instance,NPStream * stream,int32_t offset,int32_t len,void * buffer)441 int32_t NPP_Write(NPP instance, NPStream *stream, int32_t offset, int32_t len, void *buffer)
442 {
443     PluginObject* obj = (PluginObject*)instance->pdata;
444 
445     if (obj->returnNegativeOneFromWrite)
446         return -1;
447 
448     return len;
449 }
450 
NPP_StreamAsFile(NPP instance,NPStream * stream,const char * fname)451 void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname)
452 {
453 }
454 
NPP_Print(NPP instance,NPPrint * platformPrint)455 void NPP_Print(NPP instance, NPPrint *platformPrint)
456 {
457 }
458 
459 #ifdef XP_MACOSX
460 #ifndef NP_NO_CARBON
handleEventCarbon(NPP instance,PluginObject * obj,EventRecord * event)461 static int16_t handleEventCarbon(NPP instance, PluginObject* obj, EventRecord* event)
462 {
463     Point pt = { event->where.v, event->where.h };
464 
465     switch (event->what) {
466         case nullEvent:
467             // these are delivered non-deterministically, don't log.
468             break;
469         case mouseDown:
470             if (obj->eventLogging) {
471                 GlobalToLocal(&pt);
472                 pluginLog(instance, "mouseDown at (%d, %d)", pt.h, pt.v);
473             }
474             if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEvaluateScript)
475                 executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown);
476             break;
477         case mouseUp:
478             if (obj->eventLogging) {
479                 GlobalToLocal(&pt);
480                 pluginLog(instance, "mouseUp at (%d, %d)", pt.h, pt.v);
481             }
482             break;
483         case keyDown:
484             if (obj->eventLogging)
485                 pluginLog(instance, "keyDown '%c'", (char)(event->message & 0xFF));
486             if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEvaluateScript)
487                 executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown);
488             break;
489         case keyUp:
490             if (obj->eventLogging)
491                 pluginLog(instance, "keyUp '%c'", (char)(event->message & 0xFF));
492             if (obj->testKeyboardFocusForPlugins) {
493                 obj->eventLogging = false;
494                 obj->testKeyboardFocusForPlugins = FALSE;
495                 executeScript(obj, "layoutTestController.notifyDone();");
496             }
497             break;
498         case autoKey:
499             if (obj->eventLogging)
500                 pluginLog(instance, "autoKey '%c'", (char)(event->message & 0xFF));
501             break;
502         case updateEvt:
503             if (obj->eventLogging)
504                 pluginLog(instance, "updateEvt");
505             break;
506         case diskEvt:
507             if (obj->eventLogging)
508                 pluginLog(instance, "diskEvt");
509             break;
510         case activateEvt:
511             if (obj->eventLogging)
512                 pluginLog(instance, "activateEvt");
513             break;
514         case osEvt:
515             if (!obj->eventLogging)
516                 break;
517             printf("PLUGIN: osEvt - ");
518             switch ((event->message & 0xFF000000) >> 24) {
519                 case suspendResumeMessage:
520                     printf("%s\n", (event->message & 0x1) ? "resume" : "suspend");
521                     break;
522                 case mouseMovedMessage:
523                     printf("mouseMoved\n");
524                     break;
525                 default:
526                     printf("%08lX\n", event->message);
527             }
528             break;
529         case kHighLevelEvent:
530             if (obj->eventLogging)
531                 pluginLog(instance, "kHighLevelEvent");
532             break;
533         // NPAPI events
534         case NPEventType_GetFocusEvent:
535             if (obj->eventLogging)
536                 pluginLog(instance, "getFocusEvent");
537             break;
538         case NPEventType_LoseFocusEvent:
539             if (obj->eventLogging)
540                 pluginLog(instance, "loseFocusEvent");
541             break;
542         case NPEventType_AdjustCursorEvent:
543             if (obj->eventLogging)
544                 pluginLog(instance, "adjustCursorEvent");
545             break;
546         default:
547             if (obj->eventLogging)
548                 pluginLog(instance, "event %d", event->what);
549     }
550 
551     return 0;
552 }
553 #endif
554 
handleEventCocoa(NPP instance,PluginObject * obj,NPCocoaEvent * event)555 static int16_t handleEventCocoa(NPP instance, PluginObject* obj, NPCocoaEvent* event)
556 {
557     switch (event->type) {
558         case NPCocoaEventWindowFocusChanged:
559 
560         case NPCocoaEventFocusChanged:
561             if (obj->eventLogging) {
562                 if (event->data.focus.hasFocus)
563                     pluginLog(instance, "getFocusEvent");
564                 else
565                     pluginLog(instance, "loseFocusEvent");
566             }
567             return 1;
568 
569         case NPCocoaEventDrawRect: {
570             if (obj->onPaintEvent)
571                 executeScript(obj, obj->onPaintEvent);
572             return 1;
573         }
574 
575         case NPCocoaEventKeyDown:
576             if (obj->eventLogging && event->data.key.characters)
577                 pluginLog(instance, "keyDown '%c'", CFStringGetCharacterAtIndex(reinterpret_cast<CFStringRef>(event->data.key.characters), 0));
578             if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEvaluateScript)
579                 executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown);
580             return 1;
581 
582         case NPCocoaEventKeyUp:
583             if (obj->eventLogging && event->data.key.characters) {
584                 pluginLog(instance, "keyUp '%c'", CFStringGetCharacterAtIndex(reinterpret_cast<CFStringRef>(event->data.key.characters), 0));
585                 if (obj->testKeyboardFocusForPlugins) {
586                     obj->eventLogging = false;
587                     obj->testKeyboardFocusForPlugins = FALSE;
588                     executeScript(obj, "layoutTestController.notifyDone();");
589                 }
590             }
591             return 1;
592 
593         case NPCocoaEventFlagsChanged:
594             return 1;
595 
596         case NPCocoaEventMouseDown:
597             if (obj->eventLogging) {
598                 pluginLog(instance, "mouseDown at (%d, %d)",
599                        (int)event->data.mouse.pluginX,
600                        (int)event->data.mouse.pluginY);
601             }
602             if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEvaluateScript)
603                 executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown);
604             return 1;
605         case NPCocoaEventMouseUp:
606             if (obj->eventLogging) {
607                 pluginLog(instance, "mouseUp at (%d, %d)",
608                        (int)event->data.mouse.pluginX,
609                        (int)event->data.mouse.pluginY);
610             }
611             return 1;
612 
613         case NPCocoaEventMouseMoved:
614         case NPCocoaEventMouseEntered:
615         case NPCocoaEventMouseExited:
616         case NPCocoaEventMouseDragged:
617         case NPCocoaEventScrollWheel:
618         case NPCocoaEventTextInput:
619             return 1;
620     }
621 
622     return 0;
623 }
624 
625 #endif // XP_MACOSX
626 
627 #ifdef XP_UNIX
handleEventX11(NPP instance,PluginObject * obj,XEvent * event)628 static int16_t handleEventX11(NPP instance, PluginObject* obj, XEvent* event)
629 {
630     XButtonPressedEvent* buttonPressEvent = reinterpret_cast<XButtonPressedEvent*>(event);
631     XButtonReleasedEvent* buttonReleaseEvent = reinterpret_cast<XButtonReleasedEvent*>(event);
632     switch (event->type) {
633     case ButtonPress:
634         if (obj->eventLogging)
635             pluginLog(instance, "mouseDown at (%d, %d)", buttonPressEvent->x, buttonPressEvent->y);
636         if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEvaluateScript)
637             executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown);
638         break;
639     case ButtonRelease:
640         if (obj->eventLogging)
641             pluginLog(instance, "mouseUp at (%d, %d)", buttonReleaseEvent->x, buttonReleaseEvent->y);
642         break;
643     case KeyPress:
644         // FIXME: extract key code
645         if (obj->eventLogging)
646             pluginLog(instance, "NOTIMPLEMENTED: keyDown '%c'", ' ');
647         if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEvaluateScript)
648             executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown);
649         break;
650     case KeyRelease:
651         // FIXME: extract key code
652         if (obj->eventLogging)
653             pluginLog(instance, "NOTIMPLEMENTED: keyUp '%c'", ' ');
654         break;
655     case GraphicsExpose:
656         if (obj->eventLogging)
657             pluginLog(instance, "updateEvt");
658         break;
659     // NPAPI events
660     case FocusIn:
661         if (obj->eventLogging)
662             pluginLog(instance, "getFocusEvent");
663         break;
664     case FocusOut:
665         if (obj->eventLogging)
666             pluginLog(instance, "loseFocusEvent");
667         break;
668     case EnterNotify:
669     case LeaveNotify:
670     case MotionNotify:
671         if (obj->eventLogging)
672             pluginLog(instance, "adjustCursorEvent");
673         break;
674     default:
675         if (obj->eventLogging)
676             pluginLog(instance, "event %d", event->type);
677     }
678 
679     fflush(stdout);
680     return 0;
681 }
682 #endif // XP_UNIX
683 
684 #ifdef XP_WIN
handleEventWin(NPP instance,PluginObject * obj,NPEvent * event)685 static int16_t handleEventWin(NPP instance, PluginObject* obj, NPEvent* event)
686 {
687     switch (event->event) {
688     case WM_PAINT:
689         if (obj->onPaintEvent)
690             executeScript(obj, obj->onPaintEvent);
691         return 1;
692     }
693     return 0;
694 }
695 #endif // XP_WIN
696 
NPP_HandleEvent(NPP instance,void * event)697 int16_t NPP_HandleEvent(NPP instance, void *event)
698 {
699     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
700 
701     if (obj->pluginTest->NPP_HandleEvent(event) == 1)
702         return 1;
703 
704 #ifdef XP_MACOSX
705 #ifndef NP_NO_CARBON
706     if (obj->eventModel == NPEventModelCarbon)
707         return handleEventCarbon(instance, obj, static_cast<EventRecord*>(event));
708 #endif
709 
710     assert(obj->eventModel == NPEventModelCocoa);
711     return handleEventCocoa(instance, obj, static_cast<NPCocoaEvent*>(event));
712 #elif defined(XP_UNIX)
713     return handleEventX11(instance, obj, static_cast<XEvent*>(event));
714 #elif defined(XP_WIN)
715     return handleEventWin(instance, obj, static_cast<NPEvent*>(event));
716 #else
717     // FIXME: Implement for other platforms.
718     return 0;
719 #endif // XP_MACOSX
720 }
721 
NPP_URLNotify(NPP instance,const char * url,NPReason reason,void * notifyData)722 void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData)
723 {
724     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
725 
726      if (obj->onURLNotify)
727          executeScript(obj, obj->onURLNotify);
728 
729     handleCallback(obj, url, reason, notifyData);
730 }
731 
NPP_GetValue(NPP instance,NPPVariable variable,void * value)732 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
733 {
734 #ifdef XP_UNIX
735     if (variable == NPPVpluginNameString) {
736         *((char **)value) = const_cast<char*>("WebKit Test PlugIn");
737         return NPERR_NO_ERROR;
738     }
739     if (variable == NPPVpluginDescriptionString) {
740         *((char **)value) = const_cast<char*>("Simple Netscape plug-in that handles test content for WebKit");
741         return NPERR_NO_ERROR;
742     }
743 #endif
744 
745     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
746 
747     // First, check if the PluginTest object supports getting this value.
748     if (obj->pluginTest->NPP_GetValue(variable, value) == NPERR_NO_ERROR)
749         return NPERR_NO_ERROR;
750 
751     if (variable == NPPVpluginScriptableNPObject) {
752         void **v = (void **)value;
753         // Return value is expected to be retained
754         browser->retainobject((NPObject *)obj);
755         *v = obj;
756         return NPERR_NO_ERROR;
757     }
758 
759 #if defined(XP_MACOSX) && !defined(BUILDING_ON_TIGER)
760     if (variable == NPPVpluginCoreAnimationLayer) {
761         if (!obj->coreAnimationLayer)
762             return NPERR_GENERIC_ERROR;
763 
764         void **v = (void **)value;
765         *v = (void*)CFRetain(obj->coreAnimationLayer);
766         return NPERR_NO_ERROR;
767     }
768 #endif
769 
770     return NPERR_GENERIC_ERROR;
771 }
772 
NPP_SetValue(NPP instance,NPNVariable variable,void * value)773 NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
774 {
775     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
776 
777     switch (variable) {
778         case NPNVprivateModeBool:
779             obj->cachedPrivateBrowsingMode = *(NPBool*)value;
780             return NPERR_NO_ERROR;
781         default:
782             return NPERR_GENERIC_ERROR;
783     }
784 }
785 
786 #ifdef XP_UNIX
787 extern "C"
NP_GetMIMEDescription(void)788 const char* NP_GetMIMEDescription(void)
789 {
790     return "application/x-webkit-test-netscape:testnetscape:test netscape content;image/png:png:PNG image";
791 }
792 
793 extern "C"
NP_GetValue(NPP instance,NPPVariable variable,void * value)794 NPError NP_GetValue(NPP instance, NPPVariable variable, void* value)
795 {
796     return NPP_GetValue(instance, variable, value);
797 }
798 #endif
799