1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "PluginObject.h"
32 #include "PluginTest.h"
33 #include "base/strings/string_util.h"
40 #include <X11/Xutil.h>
43 #if !defined(NP_NO_CARBON) && defined(QD_HEADERS_ARE_PRIVATE) && QD_HEADERS_ARE_PRIVATE
44 extern "C" void GlobalToLocal(Point
*);
49 #define CRASH() do { \
50 *(int *)(uintptr_t)0xbbadbeef = 0; \
51 ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \
54 static bool getEntryPointsWasCalled
= false;
55 static bool initializeWasCalled
= false;
56 static NPClass
* pluginObjectClass
= 0;
59 #define STDCALL __stdcall
61 static inline int strcasecmp(const char* s1
, const char* s2
)
63 return _stricmp(s1
, s2
);
71 NPError STDCALL
NP_GetEntryPoints(NPPluginFuncs
*pluginFuncs
);
76 NPError STDCALL
NP_Initialize(NPNetscapeFuncs
*browserFuncs
78 , NPPluginFuncs
*pluginFuncs
82 // Create a copy of the PluginObject NPClass that we can trash on shutdown.
83 pluginObjectClass
= createPluginClass();
85 initializeWasCalled
= true;
88 // Simulate Flash and QuickTime's behavior of crashing when NP_Initialize is called before NP_GetEntryPoints.
89 if (!getEntryPointsWasCalled
)
93 browser
= browserFuncs
;
96 return NP_GetEntryPoints(pluginFuncs
);
98 return NPERR_NO_ERROR
;
103 NPError STDCALL
NP_GetEntryPoints(NPPluginFuncs
*pluginFuncs
)
105 getEntryPointsWasCalled
= true;
108 // Simulate Silverlight's behavior of crashing when NP_GetEntryPoints is called before NP_Initialize.
109 if (!initializeWasCalled
)
113 pluginFunctions
= pluginFuncs
;
115 pluginFuncs
->version
= (NP_VERSION_MAJOR
<< 8) | NP_VERSION_MINOR
;
116 pluginFuncs
->size
= sizeof(pluginFuncs
);
117 pluginFuncs
->newp
= NPP_New
;
118 pluginFuncs
->destroy
= NPP_Destroy
;
119 pluginFuncs
->setwindow
= NPP_SetWindow
;
120 pluginFuncs
->newstream
= NPP_NewStream
;
121 pluginFuncs
->destroystream
= NPP_DestroyStream
;
122 pluginFuncs
->asfile
= NPP_StreamAsFile
;
123 pluginFuncs
->writeready
= NPP_WriteReady
;
124 pluginFuncs
->write
= (NPP_WriteProcPtr
)NPP_Write
;
125 pluginFuncs
->print
= NPP_Print
;
126 pluginFuncs
->event
= NPP_HandleEvent
;
127 pluginFuncs
->urlnotify
= NPP_URLNotify
;
128 pluginFuncs
->getvalue
= NPP_GetValue
;
129 pluginFuncs
->setvalue
= NPP_SetValue
;
131 return NPERR_NO_ERROR
;
135 void STDCALL
NP_Shutdown(void)
137 // Trash the PluginObject NPClass so that the process will deterministically
138 // crash if Blink tries to call into the plugin's NPObjects after unloading
139 // it, rather than relying on OS-specific DLL unload behaviour.
140 // Note that we leak the NPClass copy, to act as a guard for the lifetime of
142 memset(pluginObjectClass
, 0xf00dbeef, sizeof(NPClass
));
144 PluginTest::NP_Shutdown();
147 static void executeScript(const PluginObject
* obj
, const char* script
);
149 NPError
NPP_New(NPMIMEType pluginType
, NPP instance
, uint16_t mode
, int16_t argc
, char *argn
[], char *argv
[], NPSavedData
*saved
)
152 NPEventModel eventModel
;
154 // Always turn on the CG model
155 NPBool supportsCoreGraphics
;
156 if (browser
->getvalue(instance
, NPNVsupportsCoreGraphicsBool
, &supportsCoreGraphics
) != NPERR_NO_ERROR
)
157 supportsCoreGraphics
= false;
159 if (!supportsCoreGraphics
)
160 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
162 NPDrawingModel drawingModelToUse
= NPDrawingModelCoreGraphics
;
164 NPBool supportsCoreAnimation
;
165 if (browser
->getvalue(instance
, NPNVsupportsCoreAnimationBool
, &supportsCoreAnimation
) != NPERR_NO_ERROR
)
166 supportsCoreAnimation
= false;
169 NPBool supportsCarbon
= false;
171 NPBool supportsCocoa
= false;
174 // A browser that doesn't know about NPNVsupportsCarbonBool is one that only supports Carbon event model.
175 if (browser
->getvalue(instance
, NPNVsupportsCarbonBool
, &supportsCarbon
) != NPERR_NO_ERROR
)
176 supportsCarbon
= true;
179 if (browser
->getvalue(instance
, NPNVsupportsCocoaBool
, &supportsCocoa
) != NPERR_NO_ERROR
)
180 supportsCocoa
= false;
183 eventModel
= NPEventModelCocoa
;
185 } else if (supportsCarbon
) {
186 eventModel
= NPEventModelCarbon
;
189 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
192 browser
->setvalue(instance
, NPPVpluginEventModel
, (void *)eventModel
);
195 PluginObject
* obj
= (PluginObject
*)browser
->createobject(instance
, pluginObjectClass
);
196 instance
->pdata
= obj
;
199 obj
->eventModel
= eventModel
;
200 obj
->coreAnimationLayer
= 0;
202 obj
->alwaysFilterEvents
= false;
204 string testIdentifier
;
205 const char* onNewScript
= 0;
207 for (int i
= 0; i
< argc
; i
++) {
208 if (strcasecmp(argn
[i
], "test") == 0)
209 testIdentifier
= argv
[i
];
210 if (strcasecmp(argn
[i
], "onstreamload") == 0 && !obj
->onStreamLoad
)
211 obj
->onStreamLoad
= base::strdup(argv
[i
]);
212 else if (strcasecmp(argn
[i
], "onStreamDestroy") == 0 && !obj
->onStreamDestroy
)
213 obj
->onStreamDestroy
= base::strdup(argv
[i
]);
214 else if (strcasecmp(argn
[i
], "onURLNotify") == 0 && !obj
->onURLNotify
)
215 obj
->onURLNotify
= base::strdup(argv
[i
]);
216 else if (strcasecmp(argn
[i
], "src") == 0 &&
217 strcasecmp(argv
[i
], "data:application/x-webkit-test-netscape,returnerrorfromnewstream") == 0)
218 obj
->returnErrorFromNewStream
= true;
219 else if (strcasecmp(argn
[i
], "src") == 0 &&
220 strcasecmp(argv
[i
], "data:application/x-webkit-test-netscape,alertwhenloaded") == 0)
221 executeScript(obj
, "alert('Plugin Loaded!')");
222 else if (strcasecmp(argn
[i
], "src") == 0 &&
223 strcasecmp(argv
[i
], "data:application/x-webkit-test-netscape,logifloaded") == 0) {
224 for (int j
= 0; j
< argc
; j
++) {
225 if (strcasecmp(argn
[j
], "log") == 0) {
226 int length
= 26 + strlen(argv
[j
]) + 1;
227 char* buffer
= (char*) malloc(length
);
228 snprintf(buffer
, length
, "xWebkitTestNetscapeLog('%s')", argv
[j
]);
229 executeScript(obj
, buffer
);
233 } else if (strcasecmp(argn
[i
], "onSetWindow") == 0 && !obj
->onSetWindow
)
234 obj
->onSetWindow
= base::strdup(argv
[i
]);
235 else if (strcasecmp(argn
[i
], "onNew") == 0 && !onNewScript
)
236 onNewScript
= argv
[i
];
237 else if (strcasecmp(argn
[i
], "onPaintEvent") == 0 && !obj
->onPaintEvent
)
238 obj
->onPaintEvent
= base::strdup(argv
[i
]);
239 else if (strcasecmp(argn
[i
], "logfirstsetwindow") == 0)
240 obj
->logSetWindow
= true;
241 else if (strcasecmp(argn
[i
], "testnpruntime") == 0)
242 testNPRuntime(instance
);
243 else if (strcasecmp(argn
[i
], "logSrc") == 0) {
244 for (int i
= 0; i
< argc
; i
++)
245 if (strcasecmp(argn
[i
], "src") == 0)
246 pluginLog(instance
, "src: %s", argv
[i
]);
247 } else if (strcasecmp(argn
[i
], "cleardocumentduringnew") == 0)
248 executeScript(obj
, "document.body.innerHTML = ''");
249 else if (!strcasecmp(argn
[i
], "ondestroy"))
250 obj
->onDestroy
= base::strdup(argv
[i
]);
251 else if (strcasecmp(argn
[i
], "testwindowopen") == 0)
252 obj
->testWindowOpen
= true;
253 else if (strcasecmp(argn
[i
], "drawingmodel") == 0) {
255 const char* value
= argv
[i
];
256 if (strcasecmp(value
, "coreanimation") == 0) {
257 if (supportsCoreAnimation
)
258 drawingModelToUse
= NPDrawingModelCoreAnimation
;
260 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
261 } else if (strcasecmp(value
, "coregraphics") == 0) {
262 if (supportsCoreGraphics
)
263 drawingModelToUse
= NPDrawingModelCoreGraphics
;
265 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
267 return NPERR_INCOMPATIBLE_VERSION_ERROR
;
269 } else if (strcasecmp(argn
[i
], "testGetURLOnDestroy") == 0) {
271 // FIXME: When https://bugs.webkit.org/show_bug.cgi?id=41831 is fixed, this #ifdef can be removed.
272 obj
->testGetURLOnDestroy
= TRUE
;
274 } else if (!strcasecmp(argn
[i
], "src") && strstr(argv
[i
], "plugin-document-has-focus.pl"))
275 obj
->testKeyboardFocusForPlugins
= true;
276 else if (!strcasecmp(argn
[i
], "evaluatescript")) {
277 char* script
= argv
[i
];
278 if (script
== strstr(script
, "mouse::")) {
279 obj
->mouseDownForEvaluateScript
= true;
280 obj
->evaluateScriptOnMouseDownOrKeyDown
= base::strdup(script
+ sizeof("mouse::") - 1);
281 } else if (script
== strstr(script
, "key::")) {
282 obj
->evaluateScriptOnMouseDownOrKeyDown
= base::strdup(script
+ sizeof("key::") - 1);
284 // When testing evaluate script on mouse-down or key-down, allow event logging to handle events.
285 if (obj
->evaluateScriptOnMouseDownOrKeyDown
)
286 obj
->eventLogging
= true;
287 } else if (!strcasecmp(argn
[i
], "windowedPlugin")) {
289 if (!strcasecmp(argv
[i
], "false") || !strcasecmp(argv
[i
], "0"))
291 else if (!strcasecmp(argv
[i
], "true") || !strcasecmp(argv
[i
], "1"))
292 windowed
= reinterpret_cast<void*>(1);
295 browser
->setvalue(instance
, NPPVpluginWindowBool
, windowed
);
296 } else if (!strcasecmp(argn
[i
], "alwaysFilterEvents")) {
297 obj
->alwaysFilterEvents
= true;
302 browser
->setvalue(instance
, NPPVpluginDrawingModel
, (void *)drawingModelToUse
);
303 if (drawingModelToUse
== NPDrawingModelCoreAnimation
)
304 obj
->coreAnimationLayer
= createCoreAnimationLayer();
307 obj
->pluginTest
= PluginTest::create(instance
, testIdentifier
);
309 if (!obj
->pluginTest
) {
310 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());
311 return NPERR_GENERIC_ERROR
;
315 executeScript(obj
, onNewScript
);
317 return obj
->pluginTest
->NPP_New(pluginType
, mode
, argc
, argn
, argv
, saved
);
320 NPError
NPP_Destroy(NPP instance
, NPSavedData
**save
)
322 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
325 if (obj
->testGetURLOnDestroy
)
326 browser
->geturlnotify(obj
->npp
, "about:blank", "", 0);
328 if (obj
->onDestroy
) {
329 executeScript(obj
, obj
->onDestroy
);
330 free(obj
->onDestroy
);
333 if (obj
->onStreamLoad
)
334 free(obj
->onStreamLoad
);
336 if (obj
->onStreamDestroy
)
337 free(obj
->onStreamDestroy
);
339 if (obj
->onURLNotify
)
340 free(obj
->onURLNotify
);
342 if (obj
->onSetWindow
)
343 free(obj
->onSetWindow
);
345 if (obj
->onPaintEvent
)
346 free(obj
->onPaintEvent
);
348 if (obj
->evaluateScriptOnMouseDownOrKeyDown
)
349 free(obj
->evaluateScriptOnMouseDownOrKeyDown
);
352 pluginLog(instance
, "NPP_Destroy");
355 if (obj
->coreAnimationLayer
)
356 CFRelease(obj
->coreAnimationLayer
);
360 obj
->pluginTest
->NPP_Destroy(save
);
362 browser
->releaseobject(&obj
->header
);
364 return NPERR_NO_ERROR
;
367 NPError
NPP_SetWindow(NPP instance
, NPWindow
*window
)
369 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
372 obj
->lastWindow
= *window
;
374 if (obj
->logSetWindow
) {
375 pluginLog(instance
, "NPP_SetWindow: %d %d", (int)window
->width
, (int)window
->height
);
376 obj
->logSetWindow
= false;
377 executeScript(obj
, "testRunner.notifyDone();");
380 if (obj
->onSetWindow
)
381 executeScript(obj
, obj
->onSetWindow
);
383 if (obj
->testWindowOpen
) {
384 testWindowOpen(instance
);
385 obj
->testWindowOpen
= false;
388 if (obj
->testKeyboardFocusForPlugins
) {
389 obj
->eventLogging
= true;
390 executeScript(obj
, "eventSender.keyDown('A');");
394 return obj
->pluginTest
->NPP_SetWindow(window
);
397 static void executeScript(const PluginObject
* obj
, const char* script
)
399 NPObject
*windowScriptObject
;
400 browser
->getvalue(obj
->npp
, NPNVWindowNPObject
, &windowScriptObject
);
403 npScript
.UTF8Characters
= script
;
404 npScript
.UTF8Length
= strlen(script
);
406 NPVariant browserResult
;
407 browser
->evaluate(obj
->npp
, windowScriptObject
, &npScript
, &browserResult
);
408 browser
->releasevariantvalue(&browserResult
);
411 NPError
NPP_NewStream(NPP instance
, NPMIMEType type
, NPStream
*stream
, NPBool seekable
, uint16_t *stype
)
413 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
414 obj
->stream
= stream
;
417 if (obj
->returnErrorFromNewStream
)
418 return NPERR_GENERIC_ERROR
;
420 if (browser
->version
>= NPVERS_HAS_RESPONSE_HEADERS
)
421 notifyStream(obj
, stream
->url
, stream
->headers
);
423 if (obj
->onStreamLoad
)
424 executeScript(obj
, obj
->onStreamLoad
);
426 return obj
->pluginTest
->NPP_NewStream(type
, stream
, seekable
, stype
);
429 NPError
NPP_DestroyStream(NPP instance
, NPStream
*stream
, NPReason reason
)
431 PluginObject
* obj
= (PluginObject
*)instance
->pdata
;
433 if (obj
->onStreamDestroy
) {
434 NPObject
* windowObject
= 0;
435 NPError error
= browser
->getvalue(instance
, NPNVWindowNPObject
, &windowObject
);
437 if (error
== NPERR_NO_ERROR
) {
438 NPVariant onStreamDestroyVariant
;
439 if (browser
->getproperty(instance
, windowObject
, browser
->getstringidentifier(obj
->onStreamDestroy
), &onStreamDestroyVariant
)) {
440 if (NPVARIANT_IS_OBJECT(onStreamDestroyVariant
)) {
441 NPObject
* onStreamDestroyFunction
= NPVARIANT_TO_OBJECT(onStreamDestroyVariant
);
443 NPVariant reasonVariant
;
444 INT32_TO_NPVARIANT(reason
, reasonVariant
);
447 browser
->invokeDefault(instance
, onStreamDestroyFunction
, &reasonVariant
, 1, &result
);
448 browser
->releasevariantvalue(&result
);
450 browser
->releasevariantvalue(&onStreamDestroyVariant
);
452 browser
->releaseobject(windowObject
);
456 return obj
->pluginTest
->NPP_DestroyStream(stream
, reason
);
459 int32_t NPP_WriteReady(NPP instance
, NPStream
*stream
)
461 PluginObject
* obj
= (PluginObject
*)instance
->pdata
;
462 return obj
->pluginTest
->NPP_WriteReady(stream
);
465 int32_t NPP_Write(NPP instance
, NPStream
*stream
, int32_t offset
, int32_t len
, void *buffer
)
467 PluginObject
* obj
= (PluginObject
*)instance
->pdata
;
469 if (obj
->returnNegativeOneFromWrite
)
472 return obj
->pluginTest
->NPP_Write(stream
, offset
, len
, buffer
);
475 void NPP_StreamAsFile(NPP instance
, NPStream
*stream
, const char *fname
)
479 void NPP_Print(NPP instance
, NPPrint
*platformPrint
)
485 static int16_t handleEventCarbon(NPP instance
, PluginObject
* obj
, EventRecord
* event
)
487 Point pt
= { event
->where
.v
, event
->where
.h
};
489 switch (event
->what
) {
491 // these are delivered non-deterministically, don't log.
494 if (obj
->eventLogging
) {
496 #pragma clang diagnostic push
497 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
501 #pragma clang diagnostic pop
503 pluginLog(instance
, "mouseDown at (%d, %d)", pt
.h
, pt
.v
);
505 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& obj
->mouseDownForEvaluateScript
)
506 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
509 if (obj
->eventLogging
) {
511 #pragma clang diagnostic push
512 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
516 #pragma clang diagnostic pop
518 pluginLog(instance
, "mouseUp at (%d, %d)", pt
.h
, pt
.v
);
522 if (obj
->eventLogging
)
523 pluginLog(instance
, "keyDown '%c'", (char)(event
->message
& 0xFF));
524 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& !obj
->mouseDownForEvaluateScript
)
525 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
528 if (obj
->eventLogging
)
529 pluginLog(instance
, "keyUp '%c'", (char)(event
->message
& 0xFF));
530 if (obj
->testKeyboardFocusForPlugins
) {
531 obj
->eventLogging
= false;
532 obj
->testKeyboardFocusForPlugins
= FALSE
;
533 executeScript(obj
, "testRunner.notifyDone();");
537 if (obj
->eventLogging
)
538 pluginLog(instance
, "autoKey '%c'", (char)(event
->message
& 0xFF));
541 if (obj
->eventLogging
)
542 pluginLog(instance
, "updateEvt");
545 if (obj
->eventLogging
)
546 pluginLog(instance
, "diskEvt");
549 if (obj
->eventLogging
)
550 pluginLog(instance
, "activateEvt");
553 if (!obj
->eventLogging
)
555 printf("PLUGIN: osEvt - ");
556 switch ((event
->message
& 0xFF000000) >> 24) {
557 case suspendResumeMessage
:
558 printf("%s\n", (event
->message
& 0x1) ? "resume" : "suspend");
560 case mouseMovedMessage
:
561 printf("mouseMoved\n");
564 printf("%08lX\n", event
->message
);
567 case kHighLevelEvent
:
568 if (obj
->eventLogging
)
569 pluginLog(instance
, "kHighLevelEvent");
572 case NPEventType_GetFocusEvent
:
573 if (obj
->eventLogging
)
574 pluginLog(instance
, "getFocusEvent");
576 case NPEventType_LoseFocusEvent
:
577 if (obj
->eventLogging
)
578 pluginLog(instance
, "loseFocusEvent");
580 case NPEventType_AdjustCursorEvent
:
581 if (obj
->eventLogging
)
582 pluginLog(instance
, "adjustCursorEvent");
585 if (obj
->eventLogging
)
586 pluginLog(instance
, "event %d", event
->what
);
593 static int16_t handleEventCocoa(NPP instance
, PluginObject
* obj
, NPCocoaEvent
* event
)
595 switch (event
->type
) {
596 case NPCocoaEventWindowFocusChanged
:
598 case NPCocoaEventFocusChanged
:
599 if (obj
->eventLogging
) {
600 if (event
->data
.focus
.hasFocus
)
601 pluginLog(instance
, "getFocusEvent");
603 pluginLog(instance
, "loseFocusEvent");
607 case NPCocoaEventDrawRect
: {
608 if (obj
->onPaintEvent
)
609 executeScript(obj
, obj
->onPaintEvent
);
613 case NPCocoaEventKeyDown
:
614 if (obj
->eventLogging
&& event
->data
.key
.characters
)
615 pluginLog(instance
, "keyDown '%c'", CFStringGetCharacterAtIndex(reinterpret_cast<CFStringRef
>(event
->data
.key
.characters
), 0));
616 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& !obj
->mouseDownForEvaluateScript
)
617 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
620 case NPCocoaEventKeyUp
:
621 if (obj
->eventLogging
&& event
->data
.key
.characters
) {
622 pluginLog(instance
, "keyUp '%c'", CFStringGetCharacterAtIndex(reinterpret_cast<CFStringRef
>(event
->data
.key
.characters
), 0));
623 if (obj
->testKeyboardFocusForPlugins
) {
624 obj
->eventLogging
= false;
625 obj
->testKeyboardFocusForPlugins
= FALSE
;
626 executeScript(obj
, "testRunner.notifyDone();");
631 case NPCocoaEventFlagsChanged
:
634 case NPCocoaEventMouseDown
:
635 if (obj
->eventLogging
) {
636 pluginLog(instance
, "mouseDown at (%d, %d)",
637 (int)event
->data
.mouse
.pluginX
,
638 (int)event
->data
.mouse
.pluginY
);
640 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& obj
->mouseDownForEvaluateScript
)
641 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
643 case NPCocoaEventMouseUp
:
644 if (obj
->eventLogging
) {
645 pluginLog(instance
, "mouseUp at (%d, %d)",
646 (int)event
->data
.mouse
.pluginX
,
647 (int)event
->data
.mouse
.pluginY
);
651 case NPCocoaEventMouseMoved
:
652 case NPCocoaEventMouseEntered
:
653 case NPCocoaEventMouseExited
:
654 case NPCocoaEventMouseDragged
:
655 case NPCocoaEventScrollWheel
:
656 case NPCocoaEventTextInput
:
667 static char keyEventToChar(XKeyEvent
* event
)
670 XLookupString(event
, &c
, sizeof(c
), 0, 0);
674 static int16_t handleEventX11(NPP instance
, PluginObject
* obj
, XEvent
* event
)
676 switch (event
->type
) {
678 if (obj
->eventLogging
)
679 pluginLog(instance
, "mouseDown at (%d, %d)", event
->xbutton
.x
, event
->xbutton
.y
);
680 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& obj
->mouseDownForEvaluateScript
)
681 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
684 if (obj
->eventLogging
)
685 pluginLog(instance
, "mouseUp at (%d, %d)", event
->xbutton
.x
, event
->xbutton
.y
);
688 // FIXME: extract key code
689 if (obj
->eventLogging
)
690 pluginLog(instance
, "keyDown '%c'", keyEventToChar(&event
->xkey
));
691 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& !obj
->mouseDownForEvaluateScript
)
692 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
695 // FIXME: extract key code
696 if (obj
->eventLogging
)
697 pluginLog(instance
, "keyUp '%c'", keyEventToChar(&event
->xkey
));
698 if (obj
->testKeyboardFocusForPlugins
) {
699 obj
->eventLogging
= false;
700 obj
->testKeyboardFocusForPlugins
= false;
701 executeScript(obj
, "testRunner.notifyDone();");
705 if (obj
->eventLogging
)
706 pluginLog(instance
, "updateEvt");
707 if (obj
->onPaintEvent
)
708 executeScript(obj
, obj
->onPaintEvent
);
712 if (obj
->eventLogging
)
713 pluginLog(instance
, "getFocusEvent");
716 if (obj
->eventLogging
)
717 pluginLog(instance
, "loseFocusEvent");
724 if (obj
->eventLogging
)
725 pluginLog(instance
, "event %d", event
->type
);
734 static int16_t handleEventWin(NPP instance
, PluginObject
* obj
, NPEvent
* event
)
736 switch (event
->event
) {
738 if (obj
->onPaintEvent
)
739 executeScript(obj
, obj
->onPaintEvent
);
742 if (obj
->eventLogging
)
743 pluginLog(instance
, "keyDown '%c'", event
->wParam
);
744 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& !obj
->mouseDownForEvaluateScript
)
745 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
750 if (obj
->eventLogging
)
751 pluginLog(instance
, "keyUp '%c'", event
->wParam
);
752 if (obj
->testKeyboardFocusForPlugins
) {
753 obj
->eventLogging
= false;
754 obj
->testKeyboardFocusForPlugins
= FALSE
;
755 executeScript(obj
, "testRunner.notifyDone();");
761 if (obj
->eventLogging
)
762 pluginLog(instance
, "mouseDown at (%d, %d)", LOWORD(event
->lParam
), HIWORD(event
->lParam
));
763 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& obj
->mouseDownForEvaluateScript
)
764 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
769 if (obj
->eventLogging
)
770 pluginLog(instance
, "mouseUp at (%d, %d)", LOWORD(event
->lParam
), HIWORD(event
->lParam
));
773 if (obj
->eventLogging
)
774 pluginLog(instance
, "getFocusEvent");
777 if (obj
->eventLogging
)
778 pluginLog(instance
, "loseFocusEvent");
785 int16_t NPP_HandleEvent(NPP instance
, void *event
)
787 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
789 if (obj
->pluginTest
->NPP_HandleEvent(event
) == 1)
795 assert(obj
->eventModel
== NPEventModelCarbon
||
796 obj
->eventModel
== NPEventModelCocoa
);
797 if (obj
->eventModel
== NPEventModelCocoa
)
798 ret
= handleEventCocoa(instance
, obj
, static_cast<NPCocoaEvent
*>(event
));
799 else if (obj
->eventModel
== NPEventModelCarbon
)
800 ret
= handleEventCarbon(instance
, obj
, static_cast<EventRecord
*>(event
));
802 assert(obj
->eventModel
== NPEventModelCocoa
);
803 ret
= handleEventCocoa(instance
, obj
, static_cast<NPCocoaEvent
*>(event
));
805 #elif defined(XP_UNIX)
806 ret
= handleEventX11(instance
, obj
, static_cast<XEvent
*>(event
));
807 #elif defined(XP_WIN)
808 ret
= handleEventWin(instance
, obj
, static_cast<NPEvent
*>(event
));
810 // FIXME: Implement for other platforms.
811 return obj
->alwaysFilterEvents
;
814 if (ret
== 0 && obj
->alwaysFilterEvents
)
819 void NPP_URLNotify(NPP instance
, const char *url
, NPReason reason
, void *notifyData
)
821 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
822 if (obj
->pluginTest
->NPP_URLNotify(url
, reason
, notifyData
))
825 if (obj
->onURLNotify
)
826 executeScript(obj
, obj
->onURLNotify
);
828 handleCallback(obj
, url
, reason
, notifyData
);
831 NPError
NPP_GetValue(NPP instance
, NPPVariable variable
, void *value
)
834 if (variable
== NPPVpluginNameString
) {
835 *((char **)value
) = const_cast<char*>("WebKit Test PlugIn");
836 return NPERR_NO_ERROR
;
838 if (variable
== NPPVpluginDescriptionString
) {
839 *((char **)value
) = const_cast<char*>("Simple Netscape® plug-in that handles test content for WebKit");
840 return NPERR_NO_ERROR
;
842 if (variable
== NPPVpluginNeedsXEmbed
) {
843 *((NPBool
*)value
) = true;
844 return NPERR_NO_ERROR
;
849 return NPERR_GENERIC_ERROR
;
850 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
852 // First, check if the PluginTest object supports getting this value.
853 if (obj
->pluginTest
->NPP_GetValue(variable
, value
) == NPERR_NO_ERROR
)
854 return NPERR_NO_ERROR
;
856 if (variable
== NPPVpluginScriptableNPObject
) {
857 void **v
= (void **)value
;
858 // Return value is expected to be retained
859 browser
->retainobject((NPObject
*)obj
);
861 return NPERR_NO_ERROR
;
865 if (variable
== NPPVpluginCoreAnimationLayer
) {
866 if (!obj
->coreAnimationLayer
)
867 return NPERR_GENERIC_ERROR
;
869 void **v
= (void **)value
;
870 *v
= (void*)CFRetain(obj
->coreAnimationLayer
);
871 return NPERR_NO_ERROR
;
875 return NPERR_GENERIC_ERROR
;
878 NPError
NPP_SetValue(NPP instance
, NPNVariable variable
, void *value
)
880 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
881 return obj
->pluginTest
->NPP_SetValue(variable
, value
);
886 const char* NP_GetMIMEDescription(void)
888 return "application/x-webkit-test-netscape:testnetscape:test netscape content;image/png:png:PNG image";
892 NPError
NP_GetValue(NPP instance
, NPPVariable variable
, void* value
)
894 return NPP_GetValue(instance
, variable
, value
);