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