OLD | NEW |
| (Empty) |
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. | |
4 | |
5 /* | |
6 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. | |
7 * | |
8 * Redistribution and use in source and binary forms, with or without | |
9 * modification, are permitted provided that the following conditions | |
10 * are met: | |
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. | |
16 * | |
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. | |
28 */ | |
29 | |
30 #include <string.h> | |
31 #include <stdint.h> | |
32 | |
33 #include <cstdlib> | |
34 #include <cstring> | |
35 #include <string> | |
36 | |
37 #include "PluginObject.h" | |
38 #include "PluginTest.h" | |
39 #include "base/strings/string_util.h" | |
40 | |
41 #ifdef XP_UNIX | |
42 #include <X11/Xlib.h> | |
43 #include <X11/Xutil.h> | |
44 #endif | |
45 | |
46 #if !defined(NP_NO_CARBON) && defined(QD_HEADERS_ARE_PRIVATE) && QD_HEADERS_ARE_
PRIVATE | |
47 extern "C" void GlobalToLocal(Point*); | |
48 #endif | |
49 | |
50 using namespace std; | |
51 | |
52 #define CRASH() do { \ | |
53 *(int *)(uintptr_t)0xbbadbeef = 0; \ | |
54 ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \ | |
55 } while(false) | |
56 | |
57 static bool getEntryPointsWasCalled = false; | |
58 static bool initializeWasCalled = false; | |
59 static NPClass* pluginObjectClass = 0; | |
60 | |
61 #if defined(XP_WIN) | |
62 #define STDCALL __stdcall | |
63 | |
64 static inline int strcasecmp(const char* s1, const char* s2) | |
65 { | |
66 return _stricmp(s1, s2); | |
67 } | |
68 | |
69 #else | |
70 #define STDCALL | |
71 #endif | |
72 | |
73 extern "C" { | |
74 NPError STDCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs); | |
75 } | |
76 | |
77 // Entry points | |
78 extern "C" | |
79 NPError STDCALL NP_Initialize(NPNetscapeFuncs *browserFuncs | |
80 #ifdef XP_UNIX | |
81 , NPPluginFuncs *pluginFuncs | |
82 #endif | |
83 ) | |
84 { | |
85 // Create a copy of the PluginObject NPClass that we can trash on shutdown. | |
86 pluginObjectClass = createPluginClass(); | |
87 | |
88 initializeWasCalled = true; | |
89 | |
90 #if defined(XP_WIN) | |
91 // Simulate Flash and QuickTime's behavior of crashing when NP_Initialize is
called before NP_GetEntryPoints. | |
92 if (!getEntryPointsWasCalled) | |
93 CRASH(); | |
94 #endif | |
95 | |
96 browser = browserFuncs; | |
97 | |
98 #ifdef XP_UNIX | |
99 return NP_GetEntryPoints(pluginFuncs); | |
100 #else | |
101 return NPERR_NO_ERROR; | |
102 #endif | |
103 } | |
104 | |
105 extern "C" | |
106 NPError STDCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) | |
107 { | |
108 getEntryPointsWasCalled = true; | |
109 | |
110 #ifdef XP_MACOSX | |
111 // Simulate Silverlight's behavior of crashing when NP_GetEntryPoints is cal
led before NP_Initialize. | |
112 if (!initializeWasCalled) | |
113 CRASH(); | |
114 #endif | |
115 | |
116 pluginFunctions = pluginFuncs; | |
117 | |
118 pluginFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; | |
119 pluginFuncs->size = sizeof(pluginFuncs); | |
120 pluginFuncs->newp = NPP_New; | |
121 pluginFuncs->destroy = NPP_Destroy; | |
122 pluginFuncs->setwindow = NPP_SetWindow; | |
123 pluginFuncs->newstream = NPP_NewStream; | |
124 pluginFuncs->destroystream = NPP_DestroyStream; | |
125 pluginFuncs->asfile = NPP_StreamAsFile; | |
126 pluginFuncs->writeready = NPP_WriteReady; | |
127 pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write; | |
128 pluginFuncs->print = NPP_Print; | |
129 pluginFuncs->event = NPP_HandleEvent; | |
130 pluginFuncs->urlnotify = NPP_URLNotify; | |
131 pluginFuncs->getvalue = NPP_GetValue; | |
132 pluginFuncs->setvalue = NPP_SetValue; | |
133 | |
134 return NPERR_NO_ERROR; | |
135 } | |
136 | |
137 extern "C" | |
138 void STDCALL NP_Shutdown(void) | |
139 { | |
140 // Trash the PluginObject NPClass so that the process will deterministically | |
141 // crash if Blink tries to call into the plugin's NPObjects after unloading | |
142 // it, rather than relying on OS-specific DLL unload behaviour. | |
143 // Note that we leak the NPClass copy, to act as a guard for the lifetime of | |
144 // the process. | |
145 memset(pluginObjectClass, 0xf00dbeef, sizeof(NPClass)); | |
146 | |
147 PluginTest::NP_Shutdown(); | |
148 } | |
149 | |
150 static void executeScript(const PluginObject* obj, const char* script); | |
151 | |
152 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc
, char *argn[], char *argv[], NPSavedData *saved) | |
153 { | |
154 #ifdef XP_MACOSX | |
155 NPEventModel eventModel; | |
156 | |
157 // Always turn on the CG model | |
158 NPBool supportsCoreGraphics; | |
159 if (browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreG
raphics) != NPERR_NO_ERROR) | |
160 supportsCoreGraphics = false; | |
161 | |
162 if (!supportsCoreGraphics) | |
163 return NPERR_INCOMPATIBLE_VERSION_ERROR; | |
164 | |
165 #ifndef NP_NO_CARBON | |
166 NPBool supportsCarbon = false; | |
167 #endif | |
168 NPBool supportsCocoa = false; | |
169 | |
170 #ifndef NP_NO_CARBON | |
171 // A browser that doesn't know about NPNVsupportsCarbonBool is one that only
supports Carbon event model. | |
172 if (browser->getvalue(instance, NPNVsupportsCarbonBool, &supportsCarbon) !=
NPERR_NO_ERROR) | |
173 supportsCarbon = true; | |
174 #endif | |
175 | |
176 if (browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoa) != NP
ERR_NO_ERROR) | |
177 supportsCocoa = false; | |
178 | |
179 if (supportsCocoa) { | |
180 eventModel = NPEventModelCocoa; | |
181 #ifndef NP_NO_CARBON | |
182 } else if (supportsCarbon) { | |
183 eventModel = NPEventModelCarbon; | |
184 #endif | |
185 } else { | |
186 return NPERR_INCOMPATIBLE_VERSION_ERROR; | |
187 } | |
188 | |
189 browser->setvalue(instance, NPPVpluginEventModel, (void *)eventModel); | |
190 #endif // XP_MACOSX | |
191 | |
192 PluginObject* obj = (PluginObject*)browser->createobject(instance, pluginObj
ectClass); | |
193 instance->pdata = obj; | |
194 | |
195 #ifdef XP_MACOSX | |
196 obj->eventModel = eventModel; | |
197 #endif // XP_MACOSX | |
198 obj->alwaysFilterEvents = false; | |
199 | |
200 string testIdentifier; | |
201 const char* onNewScript = 0; | |
202 | |
203 for (int i = 0; i < argc; i++) { | |
204 if (strcasecmp(argn[i], "test") == 0) | |
205 testIdentifier = argv[i]; | |
206 if (strcasecmp(argn[i], "onstreamload") == 0 && !obj->onStreamLoad) | |
207 obj->onStreamLoad = base::strdup(argv[i]); | |
208 else if (strcasecmp(argn[i], "onStreamDestroy") == 0 && !obj->onStreamDe
stroy) | |
209 obj->onStreamDestroy = base::strdup(argv[i]); | |
210 else if (strcasecmp(argn[i], "onURLNotify") == 0 && !obj->onURLNotify) | |
211 obj->onURLNotify = base::strdup(argv[i]); | |
212 else if (strcasecmp(argn[i], "src") == 0 && | |
213 strcasecmp(argv[i], "data:application/x-webkit-test-netscape,re
turnerrorfromnewstream") == 0) | |
214 obj->returnErrorFromNewStream = true; | |
215 else if (strcasecmp(argn[i], "src") == 0 && | |
216 strcasecmp(argv[i], "data:application/x-webkit-test-netscape,al
ertwhenloaded") == 0) | |
217 executeScript(obj, "alert('Plugin Loaded!')"); | |
218 else if (strcasecmp(argn[i], "src") == 0 && | |
219 strcasecmp(argv[i], "data:application/x-webkit-test-netscape,lo
gifloaded") == 0) { | |
220 for (int j = 0; j < argc; j++) { | |
221 if (strcasecmp(argn[j], "log") == 0) { | |
222 int length = 26 + strlen(argv[j]) + 1; | |
223 char* buffer = (char*) malloc(length); | |
224 snprintf(buffer, length, "xWebkitTestNetscapeLog('%s')", argv[j]
); | |
225 executeScript(obj, buffer); | |
226 free(buffer); | |
227 } | |
228 } | |
229 } else if (strcasecmp(argn[i], "onSetWindow") == 0 && !obj->onSetWindow) | |
230 obj->onSetWindow = base::strdup(argv[i]); | |
231 else if (strcasecmp(argn[i], "onNew") == 0 && !onNewScript) | |
232 onNewScript = argv[i]; | |
233 else if (strcasecmp(argn[i], "onPaintEvent") == 0 && !obj->onPaintEvent) | |
234 obj->onPaintEvent = base::strdup(argv[i]); | |
235 else if (strcasecmp(argn[i], "logfirstsetwindow") == 0) | |
236 obj->logSetWindow = true; | |
237 else if (strcasecmp(argn[i], "testnpruntime") == 0) | |
238 testNPRuntime(instance); | |
239 else if (strcasecmp(argn[i], "logSrc") == 0) { | |
240 for (int i = 0; i < argc; i++) | |
241 if (strcasecmp(argn[i], "src") == 0) | |
242 pluginLog(instance, "src: %s", argv[i]); | |
243 } else if (strcasecmp(argn[i], "cleardocumentduringnew") == 0) | |
244 executeScript(obj, "document.body.innerHTML = ''"); | |
245 else if (!strcasecmp(argn[i], "ondestroy")) | |
246 obj->onDestroy = base::strdup(argv[i]); | |
247 else if (strcasecmp(argn[i], "testwindowopen") == 0) | |
248 obj->testWindowOpen = true; | |
249 else if (strcasecmp(argn[i], "testGetURLOnDestroy") == 0) { | |
250 #if defined(XP_WIN) | |
251 // FIXME: When https://bugs.webkit.org/show_bug.cgi?id=41831 is fixe
d, this #ifdef can be removed. | |
252 obj->testGetURLOnDestroy = TRUE; | |
253 #endif | |
254 } else if (!strcasecmp(argn[i], "src") && strstr(argv[i], "plugin-docume
nt-has-focus.pl")) | |
255 obj->testKeyboardFocusForPlugins = true; | |
256 else if (!strcasecmp(argn[i], "evaluatescript")) { | |
257 char* script = argv[i]; | |
258 if (script == strstr(script, "mouse::")) { | |
259 obj->mouseDownForEvaluateScript = true; | |
260 obj->evaluateScriptOnMouseDownOrKeyDown = base::strdup(script +
sizeof("mouse::") - 1); | |
261 } else if (script == strstr(script, "key::")) { | |
262 obj->evaluateScriptOnMouseDownOrKeyDown = base::strdup(script +
sizeof("key::") - 1); | |
263 } | |
264 // When testing evaluate script on mouse-down or key-down, allow eve
nt logging to handle events. | |
265 if (obj->evaluateScriptOnMouseDownOrKeyDown) | |
266 obj->eventLogging = true; | |
267 } else if (!strcasecmp(argn[i], "alwaysFilterEvents")) { | |
268 obj->alwaysFilterEvents = true; | |
269 } | |
270 } | |
271 | |
272 #ifdef XP_MACOSX | |
273 browser->setvalue(instance, NPPVpluginDrawingModel, (void *)NPDrawingModelCo
reGraphics); | |
274 #endif | |
275 | |
276 obj->pluginTest = PluginTest::create(instance, testIdentifier); | |
277 | |
278 if (!obj->pluginTest) { | |
279 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()); | |
280 return NPERR_GENERIC_ERROR; | |
281 } | |
282 | |
283 if (onNewScript) | |
284 executeScript(obj, onNewScript); | |
285 | |
286 return obj->pluginTest->NPP_New(pluginType, mode, argc, argn, argv, saved); | |
287 } | |
288 | |
289 NPError NPP_Destroy(NPP instance, NPSavedData **save) | |
290 { | |
291 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); | |
292 | |
293 if (obj) { | |
294 if (obj->testGetURLOnDestroy) | |
295 browser->geturlnotify(obj->npp, "about:blank", "", 0); | |
296 | |
297 if (obj->onDestroy) { | |
298 executeScript(obj, obj->onDestroy); | |
299 free(obj->onDestroy); | |
300 } | |
301 | |
302 if (obj->onStreamLoad) | |
303 free(obj->onStreamLoad); | |
304 | |
305 if (obj->onStreamDestroy) | |
306 free(obj->onStreamDestroy); | |
307 | |
308 if (obj->onURLNotify) | |
309 free(obj->onURLNotify); | |
310 | |
311 if (obj->onSetWindow) | |
312 free(obj->onSetWindow); | |
313 | |
314 if (obj->onPaintEvent) | |
315 free(obj->onPaintEvent); | |
316 | |
317 if (obj->evaluateScriptOnMouseDownOrKeyDown) | |
318 free(obj->evaluateScriptOnMouseDownOrKeyDown); | |
319 | |
320 if (obj->logDestroy) { | |
321 // Note: this intentionally avoids using pluginLog(), because that | |
322 // requires running JS during document detach, which is forbidden. | |
323 puts("PLUGIN: NPP_Destroy"); | |
324 fflush(stdout); | |
325 } | |
326 | |
327 if (obj->pluginTest) | |
328 obj->pluginTest->NPP_Destroy(save); | |
329 | |
330 browser->releaseobject(&obj->header); | |
331 } | |
332 return NPERR_NO_ERROR; | |
333 } | |
334 | |
335 NPError NPP_SetWindow(NPP instance, NPWindow *window) | |
336 { | |
337 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); | |
338 | |
339 if (obj) { | |
340 obj->lastWindow = *window; | |
341 | |
342 if (obj->logSetWindow) { | |
343 pluginLog(instance, "NPP_SetWindow: %d %d", (int)window->width, (int
)window->height); | |
344 obj->logSetWindow = false; | |
345 executeScript(obj, "testRunner.notifyDone();"); | |
346 } | |
347 | |
348 if (obj->onSetWindow) | |
349 executeScript(obj, obj->onSetWindow); | |
350 | |
351 if (obj->testWindowOpen) { | |
352 testWindowOpen(instance); | |
353 obj->testWindowOpen = false; | |
354 } | |
355 | |
356 if (obj->testKeyboardFocusForPlugins) { | |
357 obj->eventLogging = true; | |
358 executeScript(obj, "eventSender.keyDown('A');"); | |
359 } | |
360 } | |
361 | |
362 return obj->pluginTest->NPP_SetWindow(window); | |
363 } | |
364 | |
365 static void executeScript(const PluginObject* obj, const char* script) | |
366 { | |
367 NPObject *windowScriptObject; | |
368 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); | |
369 | |
370 NPString npScript; | |
371 npScript.UTF8Characters = script; | |
372 npScript.UTF8Length = strlen(script); | |
373 | |
374 NPVariant browserResult; | |
375 browser->evaluate(obj->npp, windowScriptObject, &npScript, &browserResult); | |
376 browser->releasevariantvalue(&browserResult); | |
377 } | |
378 | |
379 NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool se
ekable, uint16_t *stype) | |
380 { | |
381 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); | |
382 obj->stream = stream; | |
383 *stype = NP_NORMAL; | |
384 | |
385 if (obj->returnErrorFromNewStream) | |
386 return NPERR_GENERIC_ERROR; | |
387 | |
388 if (browser->version >= NPVERS_HAS_RESPONSE_HEADERS) | |
389 notifyStream(obj, stream->url, stream->headers); | |
390 | |
391 if (obj->onStreamLoad) | |
392 executeScript(obj, obj->onStreamLoad); | |
393 | |
394 return obj->pluginTest->NPP_NewStream(type, stream, seekable, stype); | |
395 } | |
396 | |
397 NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) | |
398 { | |
399 PluginObject* obj = (PluginObject*)instance->pdata; | |
400 | |
401 if (obj->onStreamDestroy) { | |
402 NPObject* windowObject = 0; | |
403 NPError error = browser->getvalue(instance, NPNVWindowNPObject, &windowO
bject); | |
404 | |
405 if (error == NPERR_NO_ERROR) { | |
406 NPVariant onStreamDestroyVariant; | |
407 if (browser->getproperty(instance, windowObject, browser->getstringi
dentifier(obj->onStreamDestroy), &onStreamDestroyVariant)) { | |
408 if (NPVARIANT_IS_OBJECT(onStreamDestroyVariant)) { | |
409 NPObject* onStreamDestroyFunction = NPVARIANT_TO_OBJECT(onSt
reamDestroyVariant); | |
410 | |
411 NPVariant reasonVariant; | |
412 INT32_TO_NPVARIANT(reason, reasonVariant); | |
413 | |
414 NPVariant result; | |
415 browser->invokeDefault(instance, onStreamDestroyFunction, &r
easonVariant, 1, &result); | |
416 browser->releasevariantvalue(&result); | |
417 } | |
418 browser->releasevariantvalue(&onStreamDestroyVariant); | |
419 } | |
420 browser->releaseobject(windowObject); | |
421 } | |
422 } | |
423 | |
424 return obj->pluginTest->NPP_DestroyStream(stream, reason); | |
425 } | |
426 | |
427 int32_t NPP_WriteReady(NPP instance, NPStream *stream) | |
428 { | |
429 PluginObject* obj = (PluginObject*)instance->pdata; | |
430 return obj->pluginTest->NPP_WriteReady(stream); | |
431 } | |
432 | |
433 int32_t NPP_Write(NPP instance, NPStream *stream, int32_t offset, int32_t len, v
oid *buffer) | |
434 { | |
435 PluginObject* obj = (PluginObject*)instance->pdata; | |
436 | |
437 if (obj->returnNegativeOneFromWrite) | |
438 return -1; | |
439 | |
440 return obj->pluginTest->NPP_Write(stream, offset, len, buffer); | |
441 } | |
442 | |
443 void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) | |
444 { | |
445 } | |
446 | |
447 void NPP_Print(NPP instance, NPPrint *platformPrint) | |
448 { | |
449 } | |
450 | |
451 #ifdef XP_MACOSX | |
452 #ifndef NP_NO_CARBON | |
453 static int16_t handleEventCarbon(NPP instance, PluginObject* obj, EventRecord* e
vent) | |
454 { | |
455 Point pt = { event->where.v, event->where.h }; | |
456 | |
457 switch (event->what) { | |
458 case nullEvent: | |
459 // these are delivered non-deterministically, don't log. | |
460 break; | |
461 case mouseDown: | |
462 if (obj->eventLogging) { | |
463 #if __clang__ | |
464 #pragma clang diagnostic push | |
465 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | |
466 #endif | |
467 GlobalToLocal(&pt); | |
468 #if __clang__ | |
469 #pragma clang diagnostic pop | |
470 #endif | |
471 pluginLog(instance, "mouseDown at (%d, %d)", pt.h, pt.v); | |
472 } | |
473 if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEval
uateScript) | |
474 executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); | |
475 break; | |
476 case mouseUp: | |
477 if (obj->eventLogging) { | |
478 #if __clang__ | |
479 #pragma clang diagnostic push | |
480 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | |
481 #endif | |
482 GlobalToLocal(&pt); | |
483 #if __clang__ | |
484 #pragma clang diagnostic pop | |
485 #endif | |
486 pluginLog(instance, "mouseUp at (%d, %d)", pt.h, pt.v); | |
487 } | |
488 break; | |
489 case keyDown: | |
490 if (obj->eventLogging) | |
491 pluginLog(instance, "keyDown '%c'", (char)(event->message & 0xFF
)); | |
492 if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEva
luateScript) | |
493 executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); | |
494 break; | |
495 case keyUp: | |
496 if (obj->eventLogging) | |
497 pluginLog(instance, "keyUp '%c'", (char)(event->message & 0xFF))
; | |
498 if (obj->testKeyboardFocusForPlugins) { | |
499 obj->eventLogging = false; | |
500 obj->testKeyboardFocusForPlugins = FALSE; | |
501 executeScript(obj, "testRunner.notifyDone();"); | |
502 } | |
503 break; | |
504 case autoKey: | |
505 if (obj->eventLogging) | |
506 pluginLog(instance, "autoKey '%c'", (char)(event->message & 0xFF
)); | |
507 break; | |
508 case updateEvt: | |
509 if (obj->eventLogging) | |
510 pluginLog(instance, "updateEvt"); | |
511 break; | |
512 case diskEvt: | |
513 if (obj->eventLogging) | |
514 pluginLog(instance, "diskEvt"); | |
515 break; | |
516 case activateEvt: | |
517 if (obj->eventLogging) | |
518 pluginLog(instance, "activateEvt"); | |
519 break; | |
520 case osEvt: | |
521 if (!obj->eventLogging) | |
522 break; | |
523 printf("PLUGIN: osEvt - "); | |
524 switch ((event->message & 0xFF000000) >> 24) { | |
525 case suspendResumeMessage: | |
526 printf("%s\n", (event->message & 0x1) ? "resume" : "suspend"
); | |
527 break; | |
528 case mouseMovedMessage: | |
529 printf("mouseMoved\n"); | |
530 break; | |
531 default: | |
532 printf("%08lX\n", event->message); | |
533 } | |
534 break; | |
535 case kHighLevelEvent: | |
536 if (obj->eventLogging) | |
537 pluginLog(instance, "kHighLevelEvent"); | |
538 break; | |
539 // NPAPI events | |
540 case NPEventType_GetFocusEvent: | |
541 if (obj->eventLogging) | |
542 pluginLog(instance, "getFocusEvent"); | |
543 break; | |
544 case NPEventType_LoseFocusEvent: | |
545 if (obj->eventLogging) | |
546 pluginLog(instance, "loseFocusEvent"); | |
547 break; | |
548 case NPEventType_AdjustCursorEvent: | |
549 if (obj->eventLogging) | |
550 pluginLog(instance, "adjustCursorEvent"); | |
551 break; | |
552 default: | |
553 if (obj->eventLogging) | |
554 pluginLog(instance, "event %d", event->what); | |
555 } | |
556 | |
557 return 0; | |
558 } | |
559 #endif | |
560 | |
561 static int16_t handleEventCocoa(NPP instance, PluginObject* obj, NPCocoaEvent* e
vent) | |
562 { | |
563 switch (event->type) { | |
564 case NPCocoaEventWindowFocusChanged: | |
565 | |
566 case NPCocoaEventFocusChanged: | |
567 if (obj->eventLogging) { | |
568 if (event->data.focus.hasFocus) | |
569 pluginLog(instance, "getFocusEvent"); | |
570 else | |
571 pluginLog(instance, "loseFocusEvent"); | |
572 } | |
573 return 1; | |
574 | |
575 case NPCocoaEventDrawRect: { | |
576 if (obj->onPaintEvent) | |
577 executeScript(obj, obj->onPaintEvent); | |
578 return 1; | |
579 } | |
580 | |
581 case NPCocoaEventKeyDown: | |
582 if (obj->eventLogging && event->data.key.characters) | |
583 pluginLog(instance, "keyDown '%c'", CFStringGetCharacterAtIndex(
reinterpret_cast<CFStringRef>(event->data.key.characters), 0)); | |
584 if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEva
luateScript) | |
585 executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); | |
586 return 1; | |
587 | |
588 case NPCocoaEventKeyUp: | |
589 if (obj->eventLogging && event->data.key.characters) { | |
590 pluginLog(instance, "keyUp '%c'", CFStringGetCharacterAtIndex(re
interpret_cast<CFStringRef>(event->data.key.characters), 0)); | |
591 if (obj->testKeyboardFocusForPlugins) { | |
592 obj->eventLogging = false; | |
593 obj->testKeyboardFocusForPlugins = FALSE; | |
594 executeScript(obj, "testRunner.notifyDone();"); | |
595 } | |
596 } | |
597 return 1; | |
598 | |
599 case NPCocoaEventFlagsChanged: | |
600 return 1; | |
601 | |
602 case NPCocoaEventMouseDown: | |
603 if (obj->eventLogging) { | |
604 pluginLog(instance, "mouseDown at (%d, %d)", | |
605 (int)event->data.mouse.pluginX, | |
606 (int)event->data.mouse.pluginY); | |
607 } | |
608 if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEval
uateScript) | |
609 executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); | |
610 return 1; | |
611 case NPCocoaEventMouseUp: | |
612 if (obj->eventLogging) { | |
613 pluginLog(instance, "mouseUp at (%d, %d)", | |
614 (int)event->data.mouse.pluginX, | |
615 (int)event->data.mouse.pluginY); | |
616 } | |
617 return 1; | |
618 | |
619 case NPCocoaEventMouseMoved: | |
620 case NPCocoaEventMouseEntered: | |
621 case NPCocoaEventMouseExited: | |
622 case NPCocoaEventMouseDragged: | |
623 case NPCocoaEventScrollWheel: | |
624 case NPCocoaEventTextInput: | |
625 return 1; | |
626 } | |
627 | |
628 return 0; | |
629 } | |
630 | |
631 #endif // XP_MACOSX | |
632 | |
633 #ifdef XP_UNIX | |
634 | |
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->mouseDownForEvaluate
Script) | |
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->mouseDownForEvaluat
eScript) | |
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 // XP_UNIX | |
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->mouseDownForEvaluat
eScript) | |
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->mouseDownForEvaluate
Script) | |
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), HI
WORD(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 int16_t ret = 0; | |
761 #ifdef XP_MACOSX | |
762 #ifndef NP_NO_CARBON | |
763 assert(obj->eventModel == NPEventModelCarbon || | |
764 obj->eventModel == NPEventModelCocoa); | |
765 if (obj->eventModel == NPEventModelCocoa) | |
766 ret = handleEventCocoa(instance, obj, static_cast<NPCocoaEvent*>(event))
; | |
767 else if (obj->eventModel == NPEventModelCarbon) | |
768 ret = handleEventCarbon(instance, obj, static_cast<EventRecord*>(event))
; | |
769 #else | |
770 assert(obj->eventModel == NPEventModelCocoa); | |
771 ret = handleEventCocoa(instance, obj, static_cast<NPCocoaEvent*>(event)); | |
772 #endif | |
773 #elif defined(XP_UNIX) | |
774 ret = handleEventX11(instance, obj, static_cast<XEvent*>(event)); | |
775 #elif defined(XP_WIN) | |
776 ret = handleEventWin(instance, obj, static_cast<NPEvent*>(event)); | |
777 #else | |
778 // FIXME: Implement for other platforms. | |
779 return obj->alwaysFilterEvents; | |
780 #endif // XP_MACOSX | |
781 | |
782 if (ret == 0 && obj->alwaysFilterEvents) | |
783 return 1; | |
784 return ret; | |
785 } | |
786 | |
787 void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyD
ata) | |
788 { | |
789 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); | |
790 if (obj->pluginTest->NPP_URLNotify(url, reason, notifyData)) | |
791 return; | |
792 | |
793 if (obj->onURLNotify) | |
794 executeScript(obj, obj->onURLNotify); | |
795 | |
796 handleCallback(obj, url, reason, notifyData); | |
797 } | |
798 | |
799 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) | |
800 { | |
801 #ifdef XP_UNIX | |
802 if (variable == NPPVpluginNameString) { | |
803 *((char **)value) = const_cast<char*>("WebKit Test PlugIn"); | |
804 return NPERR_NO_ERROR; | |
805 } | |
806 if (variable == NPPVpluginDescriptionString) { | |
807 *((char **)value) = const_cast<char*>("Simple Netscape® plugin that hand
les test content for WebKit"); | |
808 return NPERR_NO_ERROR; | |
809 } | |
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 return NPERR_GENERIC_ERROR; | |
833 } | |
834 | |
835 NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) | |
836 { | |
837 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); | |
838 return obj->pluginTest->NPP_SetValue(variable, value); | |
839 } | |
840 | |
841 #ifdef XP_UNIX | |
842 extern "C" | |
843 const char* NP_GetMIMEDescription(void) | |
844 { | |
845 return "application/x-webkit-test-netscape:testnetscape:test netscape conten
t"; | |
846 } | |
847 | |
848 extern "C" | |
849 NPError NP_GetValue(NPP instance, NPPVariable variable, void* value) | |
850 { | |
851 return NPP_GetValue(instance, variable, value); | |
852 } | |
853 #endif | |
OLD | NEW |