Clean up ChunkedUpdateDrawingAreaProxy
[WebKit-https.git] / WebKitTools / DumpRenderTree / unix / TestNetscapePlugin / TestNetscapePlugin.cpp
1 /*
2  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Zan Dobersek <zandobersek@gmail.com>
4  * Copyright (C) 2009 Holger Hans Peter Freyther
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29 #include "PluginObject.h"
30 #include "PluginTest.h"
31
32 #include "npapi.h"
33 #include "npruntime.h"
34 #include "npfunctions.h"
35
36 #include <stdarg.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <X11/Xlib.h>
41 #include <X11/Xutil.h>
42 #include <string>
43
44 using namespace std;
45  
46 extern "C" {
47     NPError NP_Initialize (NPNetscapeFuncs *aMozillaVTable, NPPluginFuncs *aPluginVTable);
48     NPError NP_Shutdown(void);
49     NPError NP_GetValue(void *future, NPPVariable variable, void *value);
50     char* NP_GetMIMEDescription(void);
51 }
52
53 static void executeScript(const PluginObject* obj, const char* script);
54
55 static NPError
56 webkit_test_plugin_new_instance(NPMIMEType mimetype,
57                                 NPP instance,
58                                 uint16_t mode,
59                                 int16_t argc,
60                                 char *argn[],
61                                 char *argv[],
62                                 NPSavedData* savedData)
63 {
64     if (browser->version >= 14) {
65         PluginObject* obj = (PluginObject*)browser->createobject(instance, getPluginClass());
66         instance->pdata = obj;
67
68         string testIdentifier;
69
70         for (int i = 0; i < argc; i++) {
71             if (strcasecmp(argn[i], "test") == 0)
72                 testIdentifier = argv[i];
73             else if (strcasecmp(argn[i], "onstreamload") == 0 && !obj->onStreamLoad)
74                 obj->onStreamLoad = strdup(argv[i]);
75             else if (strcasecmp(argn[i], "onStreamDestroy") == 0 && !obj->onStreamDestroy)
76                 obj->onStreamDestroy = strdup(argv[i]);
77             else if (strcasecmp(argn[i], "onURLNotify") == 0 && !obj->onURLNotify)
78                 obj->onURLNotify = strdup(argv[i]);
79             else if (strcasecmp(argn[i], "src") == 0 &&
80                      strcasecmp(argv[i], "data:application/x-webkit-test-netscape,returnerrorfromnewstream") == 0)
81                 obj->returnErrorFromNewStream = TRUE;
82             else if (strcasecmp(argn[i], "logfirstsetwindow") == 0)
83                 obj->logSetWindow = TRUE;
84             else if (strcasecmp(argn[i], "testnpruntime") == 0)
85                 testNPRuntime(instance);
86             else if (strcasecmp(argn[i], "logSrc") == 0) {
87                 for (int i = 0; i < argc; i++)
88                     if (strcasecmp(argn[i], "src") == 0)
89                         pluginLog(instance, "src: %s", argv[i]);
90             } else if (strcasecmp(argn[i], "cleardocumentduringnew") == 0)
91                 executeScript(obj, "document.body.innerHTML = ''");
92             else if (!strcasecmp(argn[i], "ondestroy"))
93                 obj->onDestroy = strdup(argv[i]);
94             else if (strcasecmp(argn[i], "testwindowopen") == 0)
95                 obj->testWindowOpen = TRUE;
96             else if (strcasecmp(argn[i], "onSetWindow") == 0 && !obj->onSetWindow)
97                 obj->onSetWindow = strdup(argv[i]);
98         }
99
100         browser->getvalue(instance, NPNVprivateModeBool, (void *)&obj->cachedPrivateBrowsingMode);
101
102         obj->pluginTest = PluginTest::create(instance, testIdentifier);
103
104         return obj->pluginTest->NPP_New(mimetype, mode, argc, argn, argv, savedData);
105     }
106
107     return NPERR_NO_ERROR;
108 }
109
110 static NPError
111 webkit_test_plugin_destroy_instance(NPP instance, NPSavedData** save)
112 {
113     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
114     if (obj) {
115         if (obj->onDestroy) {
116             executeScript(obj, obj->onDestroy);
117             free(obj->onDestroy);
118         }
119
120         if (obj->onStreamLoad)
121             free(obj->onStreamLoad);
122
123         if (obj->onStreamDestroy)
124             free(obj->onStreamDestroy);
125
126         if (obj->onURLNotify)
127             free(obj->onURLNotify);
128
129         if (obj->logDestroy)
130             pluginLog(instance, "NPP_Destroy");
131
132         if (obj->onSetWindow)
133             free(obj->onSetWindow);
134
135         obj->pluginTest->NPP_Destroy(save);
136
137         browser->releaseobject(&obj->header);
138     }
139
140     return NPERR_NO_ERROR;
141 }
142
143 static NPError
144 webkit_test_plugin_set_window(NPP instance, NPWindow *window)
145 {
146     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
147
148     if (obj) {
149         obj->lastWindow = *window;
150
151         if (obj->logSetWindow) {
152             pluginLog(instance, "NPP_SetWindow: %d %d", (int)window->width, (int)window->height);
153             obj->logSetWindow = false;
154         }
155         if (obj->onSetWindow)
156             executeScript(obj, obj->onSetWindow);
157
158         if (obj->testWindowOpen) {
159             testWindowOpen(instance);
160             obj->testWindowOpen = FALSE;
161         }
162
163     }
164
165     return obj->pluginTest->NPP_SetWindow(instance, window);
166 }
167
168 static void executeScript(const PluginObject* obj, const char* script)
169 {
170     NPObject *windowScriptObject;
171     browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
172
173     NPString npScript;
174     npScript.UTF8Characters = script;
175     npScript.UTF8Length = strlen(script);
176
177     NPVariant browserResult;
178     browser->evaluate(obj->npp, windowScriptObject, &npScript, &browserResult);
179     browser->releasevariantvalue(&browserResult);
180 }
181
182 static NPError
183 webkit_test_plugin_new_stream(NPP instance,
184                               NPMIMEType /*type*/,
185                               NPStream *stream,
186                               NPBool /*seekable*/,
187                               uint16_t* stype)
188 {
189     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
190     obj->stream = stream;
191     *stype = NP_NORMAL;
192
193     if (obj->returnErrorFromNewStream)
194         return NPERR_GENERIC_ERROR;
195
196     if (browser->version >= NPVERS_HAS_RESPONSE_HEADERS)
197         notifyStream(obj, stream->url, stream->headers);
198
199     if (obj->onStreamLoad)
200         executeScript(obj, obj->onStreamLoad);
201
202     return NPERR_NO_ERROR;
203 }
204
205 static NPError
206 webkit_test_plugin_destroy_stream(NPP instance, NPStream* stream, NPError reason)
207 {
208     PluginObject* obj = (PluginObject*)instance->pdata;
209
210     if (obj->onStreamDestroy) {
211         NPObject* windowObject = 0;
212         NPError error = browser->getvalue(instance, NPNVWindowNPObject, &windowObject);
213         
214         if (error == NPERR_NO_ERROR) {
215             NPVariant onStreamDestroyVariant;
216             if (browser->getproperty(instance, windowObject, browser->getstringidentifier(obj->onStreamDestroy), &onStreamDestroyVariant)) {
217                 if (NPVARIANT_IS_OBJECT(onStreamDestroyVariant)) {
218                     NPObject* onStreamDestroyFunction = NPVARIANT_TO_OBJECT(onStreamDestroyVariant);
219
220                     NPVariant reasonVariant;
221                     INT32_TO_NPVARIANT(reason, reasonVariant);
222
223                     NPVariant result;
224                     browser->invokeDefault(instance, onStreamDestroyFunction, &reasonVariant, 1, &result);
225                     browser->releasevariantvalue(&result);
226                 }
227                 browser->releasevariantvalue(&onStreamDestroyVariant);
228             }
229             browser->releaseobject(windowObject);
230         }
231     }
232
233     return obj->pluginTest->NPP_DestroyStream(stream, reason);
234 }
235
236 static void
237 webkit_test_plugin_stream_as_file(NPP /*instance*/, NPStream* /*stream*/, const char* /*fname*/)
238 {
239 }
240
241 static int32_t
242 webkit_test_plugin_write_ready(NPP /*instance*/, NPStream* /*stream*/)
243 {
244     return 4096;
245 }
246
247 static int32_t
248 webkit_test_plugin_write(NPP instance,
249                          NPStream* /*stream*/,
250                          int32_t /*offset*/,
251                          int32_t len,
252                          void* /*buffer*/)
253 {
254     PluginObject* obj = (PluginObject*)instance->pdata;
255
256     if (obj->returnNegativeOneFromWrite)
257         return -1;
258
259     return len;
260 }
261
262 static void
263 webkit_test_plugin_print(NPP /*instance*/, NPPrint* /*platformPrint*/)
264 {
265 }
266
267 static char keyEventToChar(XKeyEvent* event)
268 {
269     char c = ' ';
270     XLookupString(event, &c, sizeof(c), 0, 0);
271     return c;
272 }
273
274 static int16_t
275 webkit_test_plugin_handle_event(NPP instance, void* event)
276 {
277     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
278     if (!obj->eventLogging)
279         return 0;
280
281     XEvent* evt = static_cast<XEvent*>(event);
282
283     switch (evt->type) {
284         case ButtonRelease:
285             pluginLog(instance, "mouseUp at (%d, %d)", evt->xbutton.x, evt->xbutton.y);
286             break;
287         case ButtonPress:
288             pluginLog(instance, "mouseDown at (%d, %d)", evt->xbutton.x, evt->xbutton.y);
289             break;
290         case KeyRelease:
291             pluginLog(instance, "keyUp '%c'", keyEventToChar(&evt->xkey));
292             break;
293         case KeyPress:
294             pluginLog(instance, "keyDown '%c'", keyEventToChar(&evt->xkey));
295             break;
296         case MotionNotify:
297         case EnterNotify:
298         case LeaveNotify:
299             break;
300         case FocusIn:
301             pluginLog(instance, "getFocusEvent");
302             break;
303         case FocusOut:
304             pluginLog(instance, "loseFocusEvent");
305             break;
306         default:
307             pluginLog(instance, "event %d", evt->type);
308     }
309
310     return 0;
311 }
312
313 static void
314 webkit_test_plugin_url_notify(NPP instance, const char* url, NPReason reason, void* notifyData)
315 {
316     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
317
318     if (obj->onURLNotify)
319         executeScript(obj, obj->onURLNotify);
320
321     handleCallback(obj, url, reason, notifyData);
322 }
323
324 static NPError
325 webkit_test_plugin_get_value(NPP instance, NPPVariable variable, void *value)
326 {
327     PluginObject* obj = 0;
328     if (instance)
329         obj = static_cast<PluginObject*>(instance->pdata);
330
331     // First, check if the PluginTest object supports getting this value.
332     if (obj && obj->pluginTest->NPP_GetValue(variable, value) == NPERR_NO_ERROR)
333         return NPERR_NO_ERROR;
334     
335     NPError err = NPERR_NO_ERROR;
336
337     switch (variable) {
338         case NPPVpluginNameString:
339             *((char **)value) = const_cast<char*>("WebKit Test PlugIn");
340             break;
341         case NPPVpluginDescriptionString:
342             *((char **)value) = const_cast<char*>("Simple Netscape plug-in that handles test content for WebKit");
343             break;
344         case NPPVpluginNeedsXEmbed:
345             *((NPBool *)value) = TRUE;
346             break;
347         case NPPVpluginScriptableIID:
348         case NPPVpluginScriptableInstance:
349         case NPPVpluginScriptableNPObject:
350             err = NPERR_GENERIC_ERROR;
351             break;
352         default:
353             err = NPERR_GENERIC_ERROR;
354             break;
355     }
356
357     if (variable == NPPVpluginScriptableNPObject) {
358         void **v = (void **)value;
359         browser->retainobject((NPObject *)obj);
360         *v = obj;
361         err = NPERR_NO_ERROR;
362     }
363
364     return err;
365 }
366
367 static NPError
368 webkit_test_plugin_set_value(NPP instance, NPNVariable variable, void* value)
369 {
370     PluginObject* obj = static_cast<PluginObject*>(instance->pdata);
371
372     switch (variable) {
373         case NPNVprivateModeBool:
374             obj->cachedPrivateBrowsingMode = *(NPBool*)value;
375             return NPERR_NO_ERROR;
376         default:
377             return NPERR_GENERIC_ERROR;
378     }
379 }
380
381 char *
382 NP_GetMIMEDescription(void)
383 {
384     // We sentence-case the mime-type here to ensure that ports are not
385     // case-sensitive when loading plugins. See https://webkit.org/b/36815
386     return const_cast<char*>("application/x-Webkit-Test-Netscape:testnetscape:test netscape content");
387 }
388
389 NPError
390 NP_Initialize (NPNetscapeFuncs *aMozillaVTable, NPPluginFuncs *aPluginVTable)
391 {
392     if (aMozillaVTable == NULL || aPluginVTable == NULL)
393         return NPERR_INVALID_FUNCTABLE_ERROR;
394
395     if ((aMozillaVTable->version >> 8) > NP_VERSION_MAJOR)
396         return NPERR_INCOMPATIBLE_VERSION_ERROR;
397
398     if (aPluginVTable->size < sizeof (NPPluginFuncs))
399         return NPERR_INVALID_FUNCTABLE_ERROR;
400
401     browser = aMozillaVTable;
402     pluginFunctions = aPluginVTable;
403
404         aPluginVTable->size           = sizeof (NPPluginFuncs);
405         aPluginVTable->version        = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;
406         aPluginVTable->newp           = webkit_test_plugin_new_instance;
407         aPluginVTable->destroy        = webkit_test_plugin_destroy_instance;
408         aPluginVTable->setwindow      = webkit_test_plugin_set_window;
409         aPluginVTable->newstream      = webkit_test_plugin_new_stream;
410         aPluginVTable->destroystream  = webkit_test_plugin_destroy_stream;
411         aPluginVTable->asfile         = webkit_test_plugin_stream_as_file;
412         aPluginVTable->writeready     = webkit_test_plugin_write_ready;
413         aPluginVTable->write          = webkit_test_plugin_write;
414         aPluginVTable->print          = webkit_test_plugin_print;
415         aPluginVTable->event          = webkit_test_plugin_handle_event;
416         aPluginVTable->urlnotify      = webkit_test_plugin_url_notify;
417         aPluginVTable->javaClass      = NULL;
418         aPluginVTable->getvalue       = webkit_test_plugin_get_value;
419         aPluginVTable->setvalue       = webkit_test_plugin_set_value;
420
421     return NPERR_NO_ERROR;
422 }
423
424 NPError
425 NP_Shutdown(void)
426 {
427     return NPERR_NO_ERROR;
428 }
429
430 NPError
431 NP_GetValue(void* /*future*/, NPPVariable variable, void *value)
432 {
433     return webkit_test_plugin_get_value(NULL, variable, value);
434 }