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
);
351 if (obj
->logDestroy
) {
352 // Note: this intentionally avoids using pluginLog(), because that
353 // requires running JS during document detach, which is forbidden.
354 puts("PLUGIN: NPP_Destroy");
359 if (obj
->coreAnimationLayer
)
360 CFRelease(obj
->coreAnimationLayer
);
364 obj
->pluginTest
->NPP_Destroy(save
);
366 browser
->releaseobject(&obj
->header
);
368 return NPERR_NO_ERROR
;
371 NPError
NPP_SetWindow(NPP instance
, NPWindow
*window
)
373 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
376 obj
->lastWindow
= *window
;
378 if (obj
->logSetWindow
) {
379 pluginLog(instance
, "NPP_SetWindow: %d %d", (int)window
->width
, (int)window
->height
);
380 obj
->logSetWindow
= false;
381 executeScript(obj
, "testRunner.notifyDone();");
384 if (obj
->onSetWindow
)
385 executeScript(obj
, obj
->onSetWindow
);
387 if (obj
->testWindowOpen
) {
388 testWindowOpen(instance
);
389 obj
->testWindowOpen
= false;
392 if (obj
->testKeyboardFocusForPlugins
) {
393 obj
->eventLogging
= true;
394 executeScript(obj
, "eventSender.keyDown('A');");
398 return obj
->pluginTest
->NPP_SetWindow(window
);
401 static void executeScript(const PluginObject
* obj
, const char* script
)
403 NPObject
*windowScriptObject
;
404 browser
->getvalue(obj
->npp
, NPNVWindowNPObject
, &windowScriptObject
);
407 npScript
.UTF8Characters
= script
;
408 npScript
.UTF8Length
= strlen(script
);
410 NPVariant browserResult
;
411 browser
->evaluate(obj
->npp
, windowScriptObject
, &npScript
, &browserResult
);
412 browser
->releasevariantvalue(&browserResult
);
415 NPError
NPP_NewStream(NPP instance
, NPMIMEType type
, NPStream
*stream
, NPBool seekable
, uint16_t *stype
)
417 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
418 obj
->stream
= stream
;
421 if (obj
->returnErrorFromNewStream
)
422 return NPERR_GENERIC_ERROR
;
424 if (browser
->version
>= NPVERS_HAS_RESPONSE_HEADERS
)
425 notifyStream(obj
, stream
->url
, stream
->headers
);
427 if (obj
->onStreamLoad
)
428 executeScript(obj
, obj
->onStreamLoad
);
430 return obj
->pluginTest
->NPP_NewStream(type
, stream
, seekable
, stype
);
433 NPError
NPP_DestroyStream(NPP instance
, NPStream
*stream
, NPReason reason
)
435 PluginObject
* obj
= (PluginObject
*)instance
->pdata
;
437 if (obj
->onStreamDestroy
) {
438 NPObject
* windowObject
= 0;
439 NPError error
= browser
->getvalue(instance
, NPNVWindowNPObject
, &windowObject
);
441 if (error
== NPERR_NO_ERROR
) {
442 NPVariant onStreamDestroyVariant
;
443 if (browser
->getproperty(instance
, windowObject
, browser
->getstringidentifier(obj
->onStreamDestroy
), &onStreamDestroyVariant
)) {
444 if (NPVARIANT_IS_OBJECT(onStreamDestroyVariant
)) {
445 NPObject
* onStreamDestroyFunction
= NPVARIANT_TO_OBJECT(onStreamDestroyVariant
);
447 NPVariant reasonVariant
;
448 INT32_TO_NPVARIANT(reason
, reasonVariant
);
451 browser
->invokeDefault(instance
, onStreamDestroyFunction
, &reasonVariant
, 1, &result
);
452 browser
->releasevariantvalue(&result
);
454 browser
->releasevariantvalue(&onStreamDestroyVariant
);
456 browser
->releaseobject(windowObject
);
460 return obj
->pluginTest
->NPP_DestroyStream(stream
, reason
);
463 int32_t NPP_WriteReady(NPP instance
, NPStream
*stream
)
465 PluginObject
* obj
= (PluginObject
*)instance
->pdata
;
466 return obj
->pluginTest
->NPP_WriteReady(stream
);
469 int32_t NPP_Write(NPP instance
, NPStream
*stream
, int32_t offset
, int32_t len
, void *buffer
)
471 PluginObject
* obj
= (PluginObject
*)instance
->pdata
;
473 if (obj
->returnNegativeOneFromWrite
)
476 return obj
->pluginTest
->NPP_Write(stream
, offset
, len
, buffer
);
479 void NPP_StreamAsFile(NPP instance
, NPStream
*stream
, const char *fname
)
483 void NPP_Print(NPP instance
, NPPrint
*platformPrint
)
489 static int16_t handleEventCarbon(NPP instance
, PluginObject
* obj
, EventRecord
* event
)
491 Point pt
= { event
->where
.v
, event
->where
.h
};
493 switch (event
->what
) {
495 // these are delivered non-deterministically, don't log.
498 if (obj
->eventLogging
) {
500 #pragma clang diagnostic push
501 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
505 #pragma clang diagnostic pop
507 pluginLog(instance
, "mouseDown at (%d, %d)", pt
.h
, pt
.v
);
509 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& obj
->mouseDownForEvaluateScript
)
510 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
513 if (obj
->eventLogging
) {
515 #pragma clang diagnostic push
516 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
520 #pragma clang diagnostic pop
522 pluginLog(instance
, "mouseUp at (%d, %d)", pt
.h
, pt
.v
);
526 if (obj
->eventLogging
)
527 pluginLog(instance
, "keyDown '%c'", (char)(event
->message
& 0xFF));
528 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& !obj
->mouseDownForEvaluateScript
)
529 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
532 if (obj
->eventLogging
)
533 pluginLog(instance
, "keyUp '%c'", (char)(event
->message
& 0xFF));
534 if (obj
->testKeyboardFocusForPlugins
) {
535 obj
->eventLogging
= false;
536 obj
->testKeyboardFocusForPlugins
= FALSE
;
537 executeScript(obj
, "testRunner.notifyDone();");
541 if (obj
->eventLogging
)
542 pluginLog(instance
, "autoKey '%c'", (char)(event
->message
& 0xFF));
545 if (obj
->eventLogging
)
546 pluginLog(instance
, "updateEvt");
549 if (obj
->eventLogging
)
550 pluginLog(instance
, "diskEvt");
553 if (obj
->eventLogging
)
554 pluginLog(instance
, "activateEvt");
557 if (!obj
->eventLogging
)
559 printf("PLUGIN: osEvt - ");
560 switch ((event
->message
& 0xFF000000) >> 24) {
561 case suspendResumeMessage
:
562 printf("%s\n", (event
->message
& 0x1) ? "resume" : "suspend");
564 case mouseMovedMessage
:
565 printf("mouseMoved\n");
568 printf("%08lX\n", event
->message
);
571 case kHighLevelEvent
:
572 if (obj
->eventLogging
)
573 pluginLog(instance
, "kHighLevelEvent");
576 case NPEventType_GetFocusEvent
:
577 if (obj
->eventLogging
)
578 pluginLog(instance
, "getFocusEvent");
580 case NPEventType_LoseFocusEvent
:
581 if (obj
->eventLogging
)
582 pluginLog(instance
, "loseFocusEvent");
584 case NPEventType_AdjustCursorEvent
:
585 if (obj
->eventLogging
)
586 pluginLog(instance
, "adjustCursorEvent");
589 if (obj
->eventLogging
)
590 pluginLog(instance
, "event %d", event
->what
);
597 static int16_t handleEventCocoa(NPP instance
, PluginObject
* obj
, NPCocoaEvent
* event
)
599 switch (event
->type
) {
600 case NPCocoaEventWindowFocusChanged
:
602 case NPCocoaEventFocusChanged
:
603 if (obj
->eventLogging
) {
604 if (event
->data
.focus
.hasFocus
)
605 pluginLog(instance
, "getFocusEvent");
607 pluginLog(instance
, "loseFocusEvent");
611 case NPCocoaEventDrawRect
: {
612 if (obj
->onPaintEvent
)
613 executeScript(obj
, obj
->onPaintEvent
);
617 case NPCocoaEventKeyDown
:
618 if (obj
->eventLogging
&& event
->data
.key
.characters
)
619 pluginLog(instance
, "keyDown '%c'", CFStringGetCharacterAtIndex(reinterpret_cast<CFStringRef
>(event
->data
.key
.characters
), 0));
620 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& !obj
->mouseDownForEvaluateScript
)
621 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
624 case NPCocoaEventKeyUp
:
625 if (obj
->eventLogging
&& event
->data
.key
.characters
) {
626 pluginLog(instance
, "keyUp '%c'", CFStringGetCharacterAtIndex(reinterpret_cast<CFStringRef
>(event
->data
.key
.characters
), 0));
627 if (obj
->testKeyboardFocusForPlugins
) {
628 obj
->eventLogging
= false;
629 obj
->testKeyboardFocusForPlugins
= FALSE
;
630 executeScript(obj
, "testRunner.notifyDone();");
635 case NPCocoaEventFlagsChanged
:
638 case NPCocoaEventMouseDown
:
639 if (obj
->eventLogging
) {
640 pluginLog(instance
, "mouseDown at (%d, %d)",
641 (int)event
->data
.mouse
.pluginX
,
642 (int)event
->data
.mouse
.pluginY
);
644 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& obj
->mouseDownForEvaluateScript
)
645 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
647 case NPCocoaEventMouseUp
:
648 if (obj
->eventLogging
) {
649 pluginLog(instance
, "mouseUp at (%d, %d)",
650 (int)event
->data
.mouse
.pluginX
,
651 (int)event
->data
.mouse
.pluginY
);
655 case NPCocoaEventMouseMoved
:
656 case NPCocoaEventMouseEntered
:
657 case NPCocoaEventMouseExited
:
658 case NPCocoaEventMouseDragged
:
659 case NPCocoaEventScrollWheel
:
660 case NPCocoaEventTextInput
:
671 static char keyEventToChar(XKeyEvent
* event
)
674 XLookupString(event
, &c
, sizeof(c
), 0, 0);
678 static int16_t handleEventX11(NPP instance
, PluginObject
* obj
, XEvent
* event
)
680 switch (event
->type
) {
682 if (obj
->eventLogging
)
683 pluginLog(instance
, "mouseDown at (%d, %d)", event
->xbutton
.x
, event
->xbutton
.y
);
684 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& obj
->mouseDownForEvaluateScript
)
685 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
688 if (obj
->eventLogging
)
689 pluginLog(instance
, "mouseUp at (%d, %d)", event
->xbutton
.x
, event
->xbutton
.y
);
692 // FIXME: extract key code
693 if (obj
->eventLogging
)
694 pluginLog(instance
, "keyDown '%c'", keyEventToChar(&event
->xkey
));
695 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& !obj
->mouseDownForEvaluateScript
)
696 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
699 // FIXME: extract key code
700 if (obj
->eventLogging
)
701 pluginLog(instance
, "keyUp '%c'", keyEventToChar(&event
->xkey
));
702 if (obj
->testKeyboardFocusForPlugins
) {
703 obj
->eventLogging
= false;
704 obj
->testKeyboardFocusForPlugins
= false;
705 executeScript(obj
, "testRunner.notifyDone();");
709 if (obj
->eventLogging
)
710 pluginLog(instance
, "updateEvt");
711 if (obj
->onPaintEvent
)
712 executeScript(obj
, obj
->onPaintEvent
);
716 if (obj
->eventLogging
)
717 pluginLog(instance
, "getFocusEvent");
720 if (obj
->eventLogging
)
721 pluginLog(instance
, "loseFocusEvent");
728 if (obj
->eventLogging
)
729 pluginLog(instance
, "event %d", event
->type
);
738 static int16_t handleEventWin(NPP instance
, PluginObject
* obj
, NPEvent
* event
)
740 switch (event
->event
) {
742 if (obj
->onPaintEvent
)
743 executeScript(obj
, obj
->onPaintEvent
);
746 if (obj
->eventLogging
)
747 pluginLog(instance
, "keyDown '%c'", event
->wParam
);
748 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& !obj
->mouseDownForEvaluateScript
)
749 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
754 if (obj
->eventLogging
)
755 pluginLog(instance
, "keyUp '%c'", event
->wParam
);
756 if (obj
->testKeyboardFocusForPlugins
) {
757 obj
->eventLogging
= false;
758 obj
->testKeyboardFocusForPlugins
= FALSE
;
759 executeScript(obj
, "testRunner.notifyDone();");
765 if (obj
->eventLogging
)
766 pluginLog(instance
, "mouseDown at (%d, %d)", LOWORD(event
->lParam
), HIWORD(event
->lParam
));
767 if (obj
->evaluateScriptOnMouseDownOrKeyDown
&& obj
->mouseDownForEvaluateScript
)
768 executeScript(obj
, obj
->evaluateScriptOnMouseDownOrKeyDown
);
773 if (obj
->eventLogging
)
774 pluginLog(instance
, "mouseUp at (%d, %d)", LOWORD(event
->lParam
), HIWORD(event
->lParam
));
777 if (obj
->eventLogging
)
778 pluginLog(instance
, "getFocusEvent");
781 if (obj
->eventLogging
)
782 pluginLog(instance
, "loseFocusEvent");
789 int16_t NPP_HandleEvent(NPP instance
, void *event
)
791 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
793 if (obj
->pluginTest
->NPP_HandleEvent(event
) == 1)
799 assert(obj
->eventModel
== NPEventModelCarbon
||
800 obj
->eventModel
== NPEventModelCocoa
);
801 if (obj
->eventModel
== NPEventModelCocoa
)
802 ret
= handleEventCocoa(instance
, obj
, static_cast<NPCocoaEvent
*>(event
));
803 else if (obj
->eventModel
== NPEventModelCarbon
)
804 ret
= handleEventCarbon(instance
, obj
, static_cast<EventRecord
*>(event
));
806 assert(obj
->eventModel
== NPEventModelCocoa
);
807 ret
= handleEventCocoa(instance
, obj
, static_cast<NPCocoaEvent
*>(event
));
809 #elif defined(XP_UNIX)
810 ret
= handleEventX11(instance
, obj
, static_cast<XEvent
*>(event
));
811 #elif defined(XP_WIN)
812 ret
= handleEventWin(instance
, obj
, static_cast<NPEvent
*>(event
));
814 // FIXME: Implement for other platforms.
815 return obj
->alwaysFilterEvents
;
818 if (ret
== 0 && obj
->alwaysFilterEvents
)
823 void NPP_URLNotify(NPP instance
, const char *url
, NPReason reason
, void *notifyData
)
825 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
826 if (obj
->pluginTest
->NPP_URLNotify(url
, reason
, notifyData
))
829 if (obj
->onURLNotify
)
830 executeScript(obj
, obj
->onURLNotify
);
832 handleCallback(obj
, url
, reason
, notifyData
);
835 NPError
NPP_GetValue(NPP instance
, NPPVariable variable
, void *value
)
838 if (variable
== NPPVpluginNameString
) {
839 *((char **)value
) = const_cast<char*>("WebKit Test PlugIn");
840 return NPERR_NO_ERROR
;
842 if (variable
== NPPVpluginDescriptionString
) {
843 *((char **)value
) = const_cast<char*>("Simple Netscape® plugin that handles test content for WebKit");
844 return NPERR_NO_ERROR
;
846 if (variable
== NPPVpluginNeedsXEmbed
) {
847 *((NPBool
*)value
) = true;
848 return NPERR_NO_ERROR
;
853 return NPERR_GENERIC_ERROR
;
854 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
856 // First, check if the PluginTest object supports getting this value.
857 if (obj
->pluginTest
->NPP_GetValue(variable
, value
) == NPERR_NO_ERROR
)
858 return NPERR_NO_ERROR
;
860 if (variable
== NPPVpluginScriptableNPObject
) {
861 void **v
= (void **)value
;
862 // Return value is expected to be retained
863 browser
->retainobject((NPObject
*)obj
);
865 return NPERR_NO_ERROR
;
869 if (variable
== NPPVpluginCoreAnimationLayer
) {
870 if (!obj
->coreAnimationLayer
)
871 return NPERR_GENERIC_ERROR
;
873 void **v
= (void **)value
;
874 *v
= (void*)CFRetain(obj
->coreAnimationLayer
);
875 return NPERR_NO_ERROR
;
879 return NPERR_GENERIC_ERROR
;
882 NPError
NPP_SetValue(NPP instance
, NPNVariable variable
, void *value
)
884 PluginObject
* obj
= static_cast<PluginObject
*>(instance
->pdata
);
885 return obj
->pluginTest
->NPP_SetValue(variable
, value
);
890 const char* NP_GetMIMEDescription(void)
892 return "application/x-webkit-test-netscape:testnetscape:test netscape content;image/png:png:PNG image";
896 NPError
NP_GetValue(NPP instance
, NPPVariable variable
, void* value
)
898 return NPP_GetValue(instance
, variable
, value
);