| 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 |