1 /* 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #import "PluginObject.h" 27 28 // Mach-o entry points 29 extern "C" { 30 NPError NP_Initialize(NPNetscapeFuncs *browserFuncs); 31 NPError NP_GetEntryPoints(NPPluginFuncs *pluginFuncs); 32 void NP_Shutdown(void); 33 } 34 35 // Mach-o entry points 36 NPError NP_Initialize(NPNetscapeFuncs *browserFuncs) 37 { 38 browser = browserFuncs; 39 return NPERR_NO_ERROR; 40 } 41 42 NPError NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) 43 { 44 pluginFuncs->version = 11; 45 pluginFuncs->size = sizeof(pluginFuncs); 46 pluginFuncs->newp = NPP_New; 47 pluginFuncs->destroy = NPP_Destroy; 48 pluginFuncs->setwindow = NPP_SetWindow; 49 pluginFuncs->newstream = NPP_NewStream; 50 pluginFuncs->destroystream = NPP_DestroyStream; 51 pluginFuncs->asfile = NPP_StreamAsFile; 52 pluginFuncs->writeready = NPP_WriteReady; 53 pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write; 54 pluginFuncs->print = NPP_Print; 55 pluginFuncs->event = NPP_HandleEvent; 56 pluginFuncs->urlnotify = NPP_URLNotify; 57 pluginFuncs->getvalue = NPP_GetValue; 58 pluginFuncs->setvalue = NPP_SetValue; 59 60 return NPERR_NO_ERROR; 61 } 62 63 void NP_Shutdown(void) 64 { 65 } 66 67 static void executeScript(const PluginObject* obj, const char* script); 68 69 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char *argn[], char *argv[], NPSavedData *saved) 70 { 71 bool forceCarbon = false; 72 73 // Always turn on the CG model 74 NPBool supportsCoreGraphics; 75 if (browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) != NPERR_NO_ERROR) 76 supportsCoreGraphics = false; 77 78 if (!supportsCoreGraphics) 79 return NPERR_INCOMPATIBLE_VERSION_ERROR; 80 81 browser->setvalue(instance, NPPVpluginDrawingModel, (void *)NPDrawingModelCoreGraphics); 82 83 PluginObject* obj = (PluginObject*)browser->createobject(instance, getPluginClass()); 84 instance->pdata = obj; 85 86 for (int i = 0; i < argc; i++) { 87 if (strcasecmp(argn[i], "onstreamload") == 0 && !obj->onStreamLoad) 88 obj->onStreamLoad = strdup(argv[i]); 89 else if (strcasecmp(argn[i], "onStreamDestroy") == 0 && !obj->onStreamDestroy) 90 obj->onStreamDestroy = strdup(argv[i]); 91 else if (strcasecmp(argn[i], "onURLNotify") == 0 && !obj->onURLNotify) 92 obj->onURLNotify = strdup(argv[i]); 93 else if (strcasecmp(argn[i], "src") == 0 && 94 strcasecmp(argv[i], "data:application/x-webkit-test-netscape,returnerrorfromnewstream") == 0) 95 obj->returnErrorFromNewStream = TRUE; 96 else if (strcasecmp(argn[i], "logfirstsetwindow") == 0) 97 obj->logSetWindow = TRUE; 98 else if (strcasecmp(argn[i], "testnpruntime") == 0) 99 testNPRuntime(instance); 100 else if (strcasecmp(argn[i], "forcecarbon") == 0) 101 forceCarbon = true; 102 else if (strcasecmp(argn[i], "logSrc") == 0) { 103 for (int i = 0; i < argc; i++) 104 if (strcasecmp(argn[i], "src") == 0) 105 pluginLog(instance, "src: %s", argv[i]); 106 } else if (strcasecmp(argn[i], "cleardocumentduringnew") == 0) 107 executeScript(obj, "document.body.innerHTML = ''"); 108 else if (!strcasecmp(argn[i], "ondestroy")) 109 obj->onDestroy = strdup(argv[i]); 110 else if (strcasecmp(argn[i], "testdocumentopenindestroystream") == 0) 111 obj->testDocumentOpenInDestroyStream = TRUE; 112 else if (strcasecmp(argn[i], "testwindowopen") == 0) 113 obj->testWindowOpen = TRUE; 114 } 115 116 #ifndef NP_NO_CARBON 117 NPBool supportsCarbon = false; 118 #endif 119 NPBool supportsCocoa = false; 120 121 #ifndef NP_NO_CARBON 122 // A browser that doesn't know about NPNVsupportsCarbonBool is one that only supports Carbon event model. 123 if (browser->getvalue(instance, NPNVsupportsCarbonBool, &supportsCarbon) != NPERR_NO_ERROR) 124 supportsCarbon = true; 125 #endif 126 127 if (browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoa) != NPERR_NO_ERROR) 128 supportsCocoa = false; 129 130 if (supportsCocoa && !forceCarbon) { 131 obj->eventModel = NPEventModelCocoa; 132 #ifndef NP_NO_CARBON 133 } else if (supportsCarbon) { 134 obj->eventModel = NPEventModelCarbon; 135 #endif 136 } else { 137 return NPERR_INCOMPATIBLE_VERSION_ERROR; 138 } 139 140 browser->getvalue(instance, NPNVprivateModeBool, (void *)&obj->cachedPrivateBrowsingMode); 141 browser->setvalue(instance, NPPVpluginEventModel, (void *)obj->eventModel); 142 143 return NPERR_NO_ERROR; 144 } 145 146 NPError NPP_Destroy(NPP instance, NPSavedData **save) 147 { 148 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 149 if (obj) { 150 if (obj->onDestroy) { 151 executeScript(obj, obj->onDestroy); 152 free(obj->onDestroy); 153 } 154 155 if (obj->onStreamLoad) 156 free(obj->onStreamLoad); 157 158 if (obj->onStreamDestroy) 159 free(obj->onStreamDestroy); 160 161 if (obj->onURLNotify) 162 free(obj->onURLNotify); 163 164 if (obj->logDestroy) 165 pluginLog(instance, "NPP_Destroy"); 166 167 browser->releaseobject(&obj->header); 168 } 169 return NPERR_NO_ERROR; 170 } 171 172 NPError NPP_SetWindow(NPP instance, NPWindow *window) 173 { 174 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 175 176 if (obj) { 177 if (obj->logSetWindow) { 178 pluginLog(instance, "NPP_SetWindow: %d %d", (int)window->width, (int)window->height); 179 obj->logSetWindow = false; 180 } 181 182 if (obj->testWindowOpen) { 183 testWindowOpen(instance); 184 obj->testWindowOpen = FALSE; 185 } 186 } 187 188 return NPERR_NO_ERROR; 189 } 190 191 static void executeScript(const PluginObject* obj, const char* script) 192 { 193 NPObject *windowScriptObject; 194 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); 195 196 NPString npScript; 197 npScript.UTF8Characters = script; 198 npScript.UTF8Length = strlen(script); 199 200 NPVariant browserResult; 201 browser->evaluate(obj->npp, windowScriptObject, &npScript, &browserResult); 202 browser->releasevariantvalue(&browserResult); 203 } 204 205 NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype) 206 { 207 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 208 obj->stream = stream; 209 *stype = NP_ASFILEONLY; 210 211 if (obj->returnErrorFromNewStream) 212 return NPERR_GENERIC_ERROR; 213 214 if (browser->version >= NPVERS_HAS_RESPONSE_HEADERS) 215 notifyStream(obj, stream->url, stream->headers); 216 217 if (obj->onStreamLoad) 218 executeScript(obj, obj->onStreamLoad); 219 220 return NPERR_NO_ERROR; 221 } 222 223 NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) 224 { 225 PluginObject* obj = (PluginObject*)instance->pdata; 226 227 if (obj->onStreamDestroy) 228 executeScript(obj, obj->onStreamDestroy); 229 230 if (obj->testDocumentOpenInDestroyStream) { 231 testDocumentOpen(instance); 232 obj->testDocumentOpenInDestroyStream = FALSE; 233 } 234 235 return NPERR_NO_ERROR; 236 } 237 238 int32 NPP_WriteReady(NPP instance, NPStream *stream) 239 { 240 return 0; 241 } 242 243 int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) 244 { 245 return 0; 246 } 247 248 void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) 249 { 250 } 251 252 void NPP_Print(NPP instance, NPPrint *platformPrint) 253 { 254 } 255 256 #ifndef NP_NO_CARBON 257 static int16_t handleEventCarbon(NPP instance, PluginObject* obj, EventRecord* event) 258 { 259 Point pt = { event->where.v, event->where.h }; 260 261 switch (event->what) { 262 case nullEvent: 263 // these are delivered non-deterministically, don't log. 264 break; 265 case mouseDown: 266 GlobalToLocal(&pt); 267 pluginLog(instance, "mouseDown at (%d, %d)", pt.h, pt.v); 268 break; 269 case mouseUp: 270 GlobalToLocal(&pt); 271 pluginLog(instance, "mouseUp at (%d, %d)", pt.h, pt.v); 272 break; 273 case keyDown: 274 pluginLog(instance, "keyDown '%c'", (char)(event->message & 0xFF)); 275 break; 276 case keyUp: 277 pluginLog(instance, "keyUp '%c'", (char)(event->message & 0xFF)); 278 break; 279 case autoKey: 280 pluginLog(instance, "autoKey '%c'", (char)(event->message & 0xFF)); 281 break; 282 case updateEvt: 283 pluginLog(instance, "updateEvt"); 284 break; 285 case diskEvt: 286 pluginLog(instance, "diskEvt"); 287 break; 288 case activateEvt: 289 pluginLog(instance, "activateEvt"); 290 break; 291 case osEvt: 292 printf("PLUGIN: osEvt - "); 293 switch ((event->message & 0xFF000000) >> 24) { 294 case suspendResumeMessage: 295 printf("%s\n", (event->message & 0x1) ? "resume" : "suspend"); 296 break; 297 case mouseMovedMessage: 298 printf("mouseMoved\n"); 299 break; 300 default: 301 printf("%08lX\n", event->message); 302 } 303 break; 304 case kHighLevelEvent: 305 pluginLog(instance, "kHighLevelEvent"); 306 break; 307 // NPAPI events 308 case getFocusEvent: 309 pluginLog(instance, "getFocusEvent"); 310 break; 311 case loseFocusEvent: 312 pluginLog(instance, "loseFocusEvent"); 313 break; 314 case adjustCursorEvent: 315 pluginLog(instance, "adjustCursorEvent"); 316 break; 317 default: 318 pluginLog(instance, "event %d", event->what); 319 } 320 321 return 0; 322 } 323 #endif 324 325 static int16_t handleEventCocoa(NPP instance, PluginObject* obj, NPCocoaEvent* event) 326 { 327 switch (event->type) { 328 case NPCocoaEventWindowFocusChanged: 329 330 case NPCocoaEventFocusChanged: 331 if (event->data.focus.hasFocus) 332 pluginLog(instance, "getFocusEvent"); 333 else 334 pluginLog(instance, "loseFocusEvent"); 335 return 1; 336 337 case NPCocoaEventDrawRect: 338 return 1; 339 340 case NPCocoaEventKeyDown: 341 case NPCocoaEventKeyUp: 342 case NPCocoaEventFlagsChanged: 343 return 1; 344 345 case NPCocoaEventMouseDown: 346 pluginLog(instance, "mouseDown at (%d, %d)", 347 (int)event->data.mouse.pluginX, 348 (int)event->data.mouse.pluginY); 349 return 1; 350 case NPCocoaEventMouseUp: 351 pluginLog(instance, "mouseUp at (%d, %d)", 352 (int)event->data.mouse.pluginX, 353 (int)event->data.mouse.pluginY); 354 return 1; 355 356 case NPCocoaEventMouseMoved: 357 case NPCocoaEventMouseEntered: 358 case NPCocoaEventMouseExited: 359 case NPCocoaEventMouseDragged: 360 case NPCocoaEventScrollWheel: 361 case NPCocoaEventTextInput: 362 return 1; 363 } 364 365 return 0; 366 } 367 368 int16 NPP_HandleEvent(NPP instance, void *event) 369 { 370 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 371 if (!obj->eventLogging) 372 return 0; 373 374 #ifndef NP_NO_CARBON 375 if (obj->eventModel == NPEventModelCarbon) 376 return handleEventCarbon(instance, obj, static_cast<EventRecord*>(event)); 377 #endif 378 379 assert(obj->eventModel == NPEventModelCocoa); 380 return handleEventCocoa(instance, obj, static_cast<NPCocoaEvent*>(event)); 381 } 382 383 void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData) 384 { 385 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 386 387 if (obj->onURLNotify) 388 executeScript(obj, obj->onURLNotify); 389 390 handleCallback(obj, url, reason, notifyData); 391 } 392 393 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) 394 { 395 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 396 397 if (variable == NPPVpluginScriptableNPObject) { 398 void **v = (void **)value; 399 // Return value is expected to be retained 400 browser->retainobject((NPObject *)obj); 401 *v = obj; 402 return NPERR_NO_ERROR; 403 } 404 405 return NPERR_GENERIC_ERROR; 406 } 407 408 NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) 409 { 410 PluginObject* obj = static_cast<PluginObject*>(instance->pdata); 411 412 switch (variable) { 413 case NPNVprivateModeBool: 414 obj->cachedPrivateBrowsingMode = *(NPBool*)value; 415 return NPERR_NO_ERROR; 416 default: 417 return NPERR_GENERIC_ERROR; 418 } 419 } 420