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