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
NP_Initialize(NPNetscapeFuncs * browserFuncs)36 NPError NP_Initialize(NPNetscapeFuncs *browserFuncs)
37 {
38 browser = browserFuncs;
39 return NPERR_NO_ERROR;
40 }
41
NP_GetEntryPoints(NPPluginFuncs * pluginFuncs)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
NP_Shutdown(void)63 void NP_Shutdown(void)
64 {
65 }
66
NPP_New(NPMIMEType pluginType,NPP instance,uint16 mode,int16 argc,char * argn[],char * argv[],NPSavedData * saved)67 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char *argn[], char *argv[], NPSavedData *saved)
68 {
69 bool forceCarbon = false;
70
71 // Always turn on the CG model
72 NPBool supportsCoreGraphics;
73 if (browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) != NPERR_NO_ERROR)
74 supportsCoreGraphics = false;
75
76 if (!supportsCoreGraphics)
77 return NPERR_INCOMPATIBLE_VERSION_ERROR;
78
79 browser->setvalue(instance, NPPVpluginDrawingModel, (void *)NPDrawingModelCoreGraphics);
80
81 PluginObject* obj = (PluginObject*)browser->createobject(instance, getPluginClass());
82 instance->pdata = obj;
83
84 for (int i = 0; i < argc; i++) {
85 if (strcasecmp(argn[i], "onstreamload") == 0 && !obj->onStreamLoad)
86 obj->onStreamLoad = strdup(argv[i]);
87 else if (strcasecmp(argn[i], "onStreamDestroy") == 0 && !obj->onStreamDestroy)
88 obj->onStreamDestroy = strdup(argv[i]);
89 else if (strcasecmp(argn[i], "onURLNotify") == 0 && !obj->onURLNotify)
90 obj->onURLNotify = strdup(argv[i]);
91 else if (strcasecmp(argn[i], "src") == 0 &&
92 strcasecmp(argv[i], "data:application/x-webkit-test-netscape,returnerrorfromnewstream") == 0)
93 obj->returnErrorFromNewStream = TRUE;
94 else if (strcasecmp(argn[i], "logfirstsetwindow") == 0)
95 obj->logSetWindow = TRUE;
96 else if (strcasecmp(argn[i], "testnpruntime") == 0)
97 testNPRuntime(instance);
98 else if (strcasecmp(argn[i], "forcecarbon") == 0)
99 forceCarbon = true;
100 else if (strcasecmp(argn[i], "logSrc") == 0) {
101 for (int i = 0; i < argc; i++)
102 if (strcasecmp(argn[i], "src") == 0)
103 pluginLog(instance, "src: %s", argv[i]);
104 }
105 }
106
107 #ifndef NP_NO_CARBON
108 NPBool supportsCarbon = false;
109 #endif
110 NPBool supportsCocoa = false;
111
112 #ifndef NP_NO_CARBON
113 if (browser->getvalue(instance, NPNVsupportsCarbonBool, &supportsCarbon) != NPERR_NO_ERROR)
114 supportsCarbon = false;
115 #endif
116
117 if (browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoa) != NPERR_NO_ERROR)
118 supportsCocoa = false;
119
120 if (supportsCocoa && !forceCarbon) {
121 obj->eventModel = NPEventModelCocoa;
122 #ifndef NP_NO_CARBON
123 } else if (supportsCarbon) {
124 obj->eventModel = NPEventModelCarbon;
125 #endif
126 } else {
127 return NPERR_INCOMPATIBLE_VERSION_ERROR;
128 }
129
130 browser->setvalue(instance, NPPVpluginEventModel, (void *)obj->eventModel);
131 return NPERR_NO_ERROR;
132 }
133
NPP_Destroy(NPP instance,NPSavedData ** save)134 NPError NPP_Destroy(NPP instance, NPSavedData **save)
135 {
136 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
137 if (obj) {
138 if (obj->onStreamLoad)
139 free(obj->onStreamLoad);
140
141 if (obj->onStreamDestroy)
142 free(obj->onStreamDestroy);
143
144 if (obj->onURLNotify)
145 free(obj->onURLNotify);
146
147 if (obj->logDestroy)
148 pluginLog(instance, "NPP_Destroy");
149
150 browser->releaseobject(&obj->header);
151 }
152 return NPERR_NO_ERROR;
153 }
154
NPP_SetWindow(NPP instance,NPWindow * window)155 NPError NPP_SetWindow(NPP instance, NPWindow *window)
156 {
157 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
158
159 if (obj) {
160 if (obj->logSetWindow) {
161 pluginLog(instance, "NPP_SetWindow: %d %d", (int)window->width, (int)window->height);
162 obj->logSetWindow = false;
163 }
164 }
165
166 return NPERR_NO_ERROR;
167 }
168
executeScript(const PluginObject * obj,const char * script)169 static void executeScript(const PluginObject* obj, const char* script)
170 {
171 NPObject *windowScriptObject;
172 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
173
174 NPString npScript;
175 npScript.UTF8Characters = script;
176 npScript.UTF8Length = strlen(script);
177
178 NPVariant browserResult;
179 browser->evaluate(obj->npp, windowScriptObject, &npScript, &browserResult);
180 browser->releasevariantvalue(&browserResult);
181 }
182
NPP_NewStream(NPP instance,NPMIMEType type,NPStream * stream,NPBool seekable,uint16 * stype)183 NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype)
184 {
185 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
186 obj->stream = stream;
187 *stype = NP_ASFILEONLY;
188
189 if (obj->returnErrorFromNewStream)
190 return NPERR_GENERIC_ERROR;
191
192 if (browser->version >= NPVERS_HAS_RESPONSE_HEADERS)
193 notifyStream(obj, stream->url, stream->headers);
194
195 if (obj->onStreamLoad)
196 executeScript(obj, obj->onStreamLoad);
197
198 return NPERR_NO_ERROR;
199 }
200
NPP_DestroyStream(NPP instance,NPStream * stream,NPReason reason)201 NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason)
202 {
203 PluginObject* obj = (PluginObject*)instance->pdata;
204
205 if (obj->onStreamDestroy)
206 executeScript(obj, obj->onStreamDestroy);
207
208 return NPERR_NO_ERROR;
209 }
210
NPP_WriteReady(NPP instance,NPStream * stream)211 int32 NPP_WriteReady(NPP instance, NPStream *stream)
212 {
213 return 0;
214 }
215
NPP_Write(NPP instance,NPStream * stream,int32 offset,int32 len,void * buffer)216 int32 NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer)
217 {
218 return 0;
219 }
220
NPP_StreamAsFile(NPP instance,NPStream * stream,const char * fname)221 void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname)
222 {
223 }
224
NPP_Print(NPP instance,NPPrint * platformPrint)225 void NPP_Print(NPP instance, NPPrint *platformPrint)
226 {
227 }
228
229 #ifndef NP_NO_CARBON
handleEventCarbon(NPP instance,PluginObject * obj,EventRecord * event)230 static int16_t handleEventCarbon(NPP instance, PluginObject* obj, EventRecord* event)
231 {
232 Point pt = { event->where.v, event->where.h };
233
234 switch (event->what) {
235 case nullEvent:
236 // these are delivered non-deterministically, don't log.
237 break;
238 case mouseDown:
239 GlobalToLocal(&pt);
240 pluginLog(instance, "mouseDown at (%d, %d)", pt.h, pt.v);
241 break;
242 case mouseUp:
243 GlobalToLocal(&pt);
244 pluginLog(instance, "mouseUp at (%d, %d)", pt.h, pt.v);
245 break;
246 case keyDown:
247 pluginLog(instance, "keyDown '%c'", (char)(event->message & 0xFF));
248 break;
249 case keyUp:
250 pluginLog(instance, "keyUp '%c'", (char)(event->message & 0xFF));
251 break;
252 case autoKey:
253 pluginLog(instance, "autoKey '%c'", (char)(event->message & 0xFF));
254 break;
255 case updateEvt:
256 pluginLog(instance, "updateEvt");
257 break;
258 case diskEvt:
259 pluginLog(instance, "diskEvt");
260 break;
261 case activateEvt:
262 pluginLog(instance, "activateEvt");
263 break;
264 case osEvt:
265 printf("PLUGIN: osEvt - ");
266 switch ((event->message & 0xFF000000) >> 24) {
267 case suspendResumeMessage:
268 printf("%s\n", (event->message & 0x1) ? "resume" : "suspend");
269 break;
270 case mouseMovedMessage:
271 printf("mouseMoved\n");
272 break;
273 default:
274 printf("%08lX\n", event->message);
275 }
276 break;
277 case kHighLevelEvent:
278 pluginLog(instance, "kHighLevelEvent");
279 break;
280 // NPAPI events
281 case getFocusEvent:
282 pluginLog(instance, "getFocusEvent");
283 break;
284 case loseFocusEvent:
285 pluginLog(instance, "loseFocusEvent");
286 break;
287 case adjustCursorEvent:
288 pluginLog(instance, "adjustCursorEvent");
289 break;
290 default:
291 pluginLog(instance, "event %d", event->what);
292 }
293
294 return 0;
295 }
296 #endif
297
handleEventCocoa(NPP instance,PluginObject * obj,NPCocoaEvent * event)298 static int16_t handleEventCocoa(NPP instance, PluginObject* obj, NPCocoaEvent* event)
299 {
300 switch (event->type) {
301 case NPCocoaEventWindowFocusChanged:
302
303 case NPCocoaEventFocusChanged:
304 if (event->data.focus.hasFocus)
305 pluginLog(instance, "getFocusEvent");
306 else
307 pluginLog(instance, "loseFocusEvent");
308 return 1;
309
310 case NPCocoaEventDrawRect:
311 return 1;
312
313 case NPCocoaEventKeyDown:
314 case NPCocoaEventKeyUp:
315 case NPCocoaEventFlagsChanged:
316 return 1;
317
318 case NPCocoaEventMouseDown:
319 pluginLog(instance, "mouseDown at (%d, %d)",
320 (int)event->data.mouse.pluginX,
321 (int)event->data.mouse.pluginY);
322 return 1;
323 case NPCocoaEventMouseUp:
324 pluginLog(instance, "mouseUp at (%d, %d)",
325 (int)event->data.mouse.pluginX,
326 (int)event->data.mouse.pluginY);
327 return 1;
328
329 case NPCocoaEventMouseMoved:
330 case NPCocoaEventMouseEntered:
331 case NPCocoaEventMouseExited:
332 case NPCocoaEventMouseDragged:
333 case NPCocoaEventScrollWheel:
334 case NPCocoaEventTextInput:
335 return 1;
336 }
337
338 return 0;
339 }
340
NPP_HandleEvent(NPP instance,void * event)341 int16 NPP_HandleEvent(NPP instance, void *event)
342 {
343 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
344 if (!obj->eventLogging)
345 return 0;
346
347 #ifndef NP_NO_CARBON
348 if (obj->eventModel == NPEventModelCarbon)
349 return handleEventCarbon(instance, obj, static_cast<EventRecord*>(event));
350 #endif
351
352 assert(obj->eventModel == NPEventModelCocoa);
353 return handleEventCocoa(instance, obj, static_cast<NPCocoaEvent*>(event));
354 }
355
NPP_URLNotify(NPP instance,const char * url,NPReason reason,void * notifyData)356 void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData)
357 {
358 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
359
360 if (obj->onURLNotify)
361 executeScript(obj, obj->onURLNotify);
362
363 handleCallback(obj, url, reason, notifyData);
364 }
365
NPP_GetValue(NPP instance,NPPVariable variable,void * value)366 NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value)
367 {
368 PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
369
370 if (variable == NPPVpluginScriptableNPObject) {
371 void **v = (void **)value;
372 // Return value is expected to be retained
373 browser->retainobject((NPObject *)obj);
374 *v = obj;
375 return NPERR_NO_ERROR;
376 }
377
378 return NPERR_GENERIC_ERROR;
379 }
380
NPP_SetValue(NPP instance,NPNVariable variable,void * value)381 NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value)
382 {
383 return NPERR_GENERIC_ERROR;
384 }
385