8680a4f92e2e88571c42491249ea429dfeec89e0
[WebKit-https.git] / WebKitTools / DumpRenderTree / TestNetscapePlugIn.subproj / PluginObject.cpp
1 /*
2  IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc. ("Apple") in
3  consideration of your agreement to the following terms, and your use, installation, 
4  modification or redistribution of this Apple software constitutes acceptance of these 
5  terms.  If you do not agree with these terms, please do not use, install, modify or 
6  redistribute this Apple software.
7  
8  In consideration of your agreement to abide by the following terms, and subject to these 
9  terms, Apple grants you a personal, non-exclusive license, under Appleā€™s copyrights in 
10  this original Apple software (the "Apple Software"), to use, reproduce, modify and 
11  redistribute the Apple Software, with or without modifications, in source and/or binary 
12  forms; provided that if you redistribute the Apple Software in its entirety and without 
13  modifications, you must retain this notice and the following text and disclaimers in all 
14  such redistributions of the Apple Software.  Neither the name, trademarks, service marks 
15  or logos of Apple Computer, Inc. may be used to endorse or promote products derived from 
16  the Apple Software without specific prior written permission from Apple. Except as expressly
17  stated in this notice, no other rights or licenses, express or implied, are granted by Apple
18  herein, including but not limited to any patent rights that may be infringed by your 
19  derivative works or by other works in which the Apple Software may be incorporated.
20  
21  The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO WARRANTIES, 
22  EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, 
23  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS 
24  USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
25  
26  IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL 
27  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 
28  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, 
29  REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND 
30  WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR 
31  OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include "PluginObject.h"
35
36 #include "TestObject.h"
37 #include <assert.h>
38 #include <stdio.h>
39
40 static void pluginInvalidate(NPObject *obj);
41 static bool pluginHasProperty(NPObject *obj, NPIdentifier name);
42 static bool pluginHasMethod(NPObject *obj, NPIdentifier name);
43 static bool pluginGetProperty(NPObject *obj, NPIdentifier name, NPVariant *variant);
44 static bool pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant);
45 static bool pluginInvoke(NPObject *obj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result);
46 static bool pluginInvokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result);
47 static NPObject *pluginAllocate(NPP npp, NPClass *theClass);
48 static void pluginDeallocate(NPObject *obj);
49
50 NPNetscapeFuncs *browser;
51
52 static NPClass pluginClass = { 
53     NP_CLASS_STRUCT_VERSION,
54     pluginAllocate, 
55     pluginDeallocate, 
56     pluginInvalidate,
57     pluginHasMethod,
58     pluginInvoke,
59     pluginInvokeDefault,
60     pluginHasProperty,
61     pluginGetProperty,
62     pluginSetProperty,
63 };
64  
65 NPClass *getPluginClass(void)
66 {
67     return &pluginClass;
68 }
69
70 static bool identifiersInitialized = false;
71
72 #define ID_PROPERTY_PROPERTY        0
73 #define ID_PROPERTY_EVENT_LOGGING   1
74 #define ID_PROPERTY_HAS_STREAM      2
75 #define ID_PROPERTY_TEST_OBJECT     3
76 #define ID_PROPERTY_LOG_DESTROY     4
77 #define NUM_PROPERTY_IDENTIFIERS    5
78
79 static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
80 static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
81     "property",
82     "eventLoggingEnabled",
83     "hasStream",
84     "testObject",
85     "logDestroy",
86 };
87
88 #define ID_TEST_CALLBACK_METHOD     0
89 #define ID_TEST_GETURL              1
90 #define ID_REMOVE_DEFAULT_METHOD    2
91 #define ID_TEST_DOM_ACCESS          3
92 #define ID_TEST_GET_URL_NOTIFY      4
93 #define ID_TEST_INVOKE_DEFAULT      5
94 #define ID_DESTROY_STREAM           6
95 #define ID_TEST_ENUMERATE           7
96 #define ID_TEST_GETINTIDENTIFIER    8
97 #define NUM_METHOD_IDENTIFIERS      9
98
99 static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
100 static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
101     "testCallback",
102     "getURL",
103     "removeDefaultMethod",
104     "testDOMAccess",
105     "getURLNotify",
106     "testInvokeDefault",
107     "destroyStream",
108     "testEnumerate",
109     "testGetIntIdentifier"
110 };
111
112 static NPUTF8* createCStringFromNPVariant(const NPVariant *variant)
113 {
114     size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length;
115     NPUTF8* result = (NPUTF8*)malloc(length + 1);
116     memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length);
117     result[length] = '\0';
118     return result;
119 }
120
121 static void initializeIdentifiers(void)
122 {
123     browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, pluginPropertyIdentifiers);
124     browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, pluginMethodIdentifiers);
125 }
126
127 static bool pluginHasProperty(NPObject *obj, NPIdentifier name)
128 {
129     for (int i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++)
130         if (name == pluginPropertyIdentifiers[i])
131             return true;
132     return false;
133 }
134
135 static bool pluginHasMethod(NPObject *obj, NPIdentifier name)
136 {
137     for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++)
138         if (name == pluginMethodIdentifiers[i])
139             return true;
140     return false;
141 }
142
143 static bool pluginGetProperty(NPObject *obj, NPIdentifier name, NPVariant *variant)
144 {
145     if (name == pluginPropertyIdentifiers[ID_PROPERTY_PROPERTY]) {
146         STRINGZ_TO_NPVARIANT("property", *variant);
147         return true;
148     } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
149         BOOLEAN_TO_NPVARIANT(((PluginObject *)obj)->eventLogging, *variant);
150         return true;
151     } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
152         BOOLEAN_TO_NPVARIANT(((PluginObject *)obj)->logDestroy, *variant);
153         return true;            
154     } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_HAS_STREAM]) {
155         BOOLEAN_TO_NPVARIANT(((PluginObject *)obj)->stream != 0, *variant);
156         return true;
157     } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT]) {
158         NPObject *testObject = ((PluginObject *)obj)->testObject;
159         browser->retainobject(testObject);
160         OBJECT_TO_NPVARIANT(testObject, *variant);
161         return true;
162     }
163     return false;
164 }
165
166 static bool pluginSetProperty(NPObject *obj, NPIdentifier name, const NPVariant *variant)
167 {
168     if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
169         ((PluginObject *)obj)->eventLogging = NPVARIANT_TO_BOOLEAN(*variant);
170         return true;
171     } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
172         ((PluginObject *)obj)->logDestroy = NPVARIANT_TO_BOOLEAN(*variant);
173         return true;
174     }
175     
176     return false;
177 }
178
179 static void testDOMAccess(PluginObject *obj)
180 {
181     // Get plug-in's DOM element
182     NPObject *elementObject;
183     if (browser->getvalue(obj->npp, NPNVPluginElementNPObject, &elementObject) == NPERR_NO_ERROR) {
184         // Get style
185         NPVariant styleVariant;
186         NPIdentifier styleIdentifier = browser->getstringidentifier("style");
187         if (browser->getproperty(obj->npp, elementObject, styleIdentifier, &styleVariant) && NPVARIANT_IS_OBJECT(styleVariant)) {
188             // Set style.border
189             NPIdentifier borderIdentifier = browser->getstringidentifier("border");
190             NPVariant borderVariant;
191             STRINGZ_TO_NPVARIANT("3px solid red", borderVariant);
192             browser->setproperty(obj->npp, NPVARIANT_TO_OBJECT(styleVariant), borderIdentifier, &borderVariant);
193             browser->releasevariantvalue(&styleVariant);
194         }
195         
196         browser->releaseobject(elementObject);
197     }
198 }
199
200 static bool pluginInvoke(NPObject *header, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result)
201 {
202     PluginObject *obj = (PluginObject *)header;
203     if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD]) {
204         // call whatever method name we're given
205         if (argCount > 0 && NPVARIANT_IS_STRING(args[0])) {
206             NPObject *windowScriptObject;
207             browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
208
209             NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
210             NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
211             free(callbackString);
212
213             NPVariant browserResult;
214             browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, 0, 0, &browserResult);
215             browser->releasevariantvalue(&browserResult);
216
217             VOID_TO_NPVARIANT(*result);
218             return true;
219         }
220     } else if (name == pluginMethodIdentifiers[ID_TEST_GETURL]) {
221         if (argCount == 2 && NPVARIANT_IS_STRING(args[0]) && NPVARIANT_IS_STRING(args[1])) {
222             NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
223             NPUTF8* targetString = createCStringFromNPVariant(&args[1]);
224             browser->geturl(obj->npp, urlString, targetString);
225             free(urlString);
226             free(targetString);
227
228             VOID_TO_NPVARIANT(*result);
229             return true;
230         } else if (argCount == 1 && NPVARIANT_IS_STRING(args[0])) {
231             NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
232             browser->geturl(obj->npp, urlString, 0);
233             free(urlString);
234
235             VOID_TO_NPVARIANT(*result);
236             return true;
237         }
238     } else if (name == pluginMethodIdentifiers[ID_REMOVE_DEFAULT_METHOD]) {
239         pluginClass.invokeDefault = 0;
240         VOID_TO_NPVARIANT(*result);
241         return true;
242     } else if (name == pluginMethodIdentifiers[ID_TEST_DOM_ACCESS]) {
243         testDOMAccess(obj);
244         VOID_TO_NPVARIANT(*result);
245         return true;
246     } else if (name == pluginMethodIdentifiers[ID_TEST_GET_URL_NOTIFY]) {
247         if (argCount == 3
248           && NPVARIANT_IS_STRING(args[0])
249           && (NPVARIANT_IS_STRING(args[1]) || NPVARIANT_IS_NULL(args[1]))
250           && NPVARIANT_IS_STRING(args[2])) {
251             NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
252             NPUTF8* targetString = (NPVARIANT_IS_STRING(args[1]) ? createCStringFromNPVariant(&args[1]) : NULL);
253             NPUTF8* callbackString = createCStringFromNPVariant(&args[2]);
254             
255             NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
256             browser->geturlnotify(obj->npp, urlString, targetString, callbackIdentifier);
257
258             free(urlString);
259             free(targetString);
260             free(callbackString);
261             
262             VOID_TO_NPVARIANT(*result);
263             return true;
264         }
265     } else if (name == pluginMethodIdentifiers[ID_TEST_INVOKE_DEFAULT] && NPVARIANT_IS_OBJECT(args[0])) {
266         NPObject *callback = NPVARIANT_TO_OBJECT(args[0]);
267         
268         NPVariant args[1];
269         NPVariant browserResult;
270         
271         STRINGZ_TO_NPVARIANT("test", args[0]);
272         bool retval = browser->invokeDefault(obj->npp, callback, args, 1, &browserResult);
273         
274         if (retval)
275             browser->releasevariantvalue(&browserResult);
276         
277         BOOLEAN_TO_NPVARIANT(retval, *result);
278         return true;
279     } else if (name == pluginMethodIdentifiers[ID_TEST_ENUMERATE]) {
280         if (argCount == 2 && NPVARIANT_IS_OBJECT(args[0]) && NPVARIANT_IS_OBJECT(args[1])) {
281             uint32_t count;            
282             NPIdentifier* identifiers;
283
284             if (browser->enumerate(obj->npp, NPVARIANT_TO_OBJECT(args[0]), &identifiers, &count)) {
285                 NPObject* outArray = NPVARIANT_TO_OBJECT(args[1]);
286                 NPIdentifier pushIdentifier = browser->getstringidentifier("push");
287                 
288                 for (uint32_t i = 0; i < count; i++) {
289                     NPUTF8* string = browser->utf8fromidentifier(identifiers[i]);
290                     
291                     if (!string)
292                         continue;
293                                         
294                     NPVariant args[1];
295                     STRINGZ_TO_NPVARIANT(string, args[0]);
296                     NPVariant browserResult;
297                     browser->invoke(obj->npp, outArray, pushIdentifier, args, 1, &browserResult);
298                     browser->releasevariantvalue(&browserResult);
299                     browser->memfree(string);
300                 }
301                 
302                 browser->memfree(identifiers);
303             }
304             
305             VOID_TO_NPVARIANT(*result);
306             return true;            
307         }
308     } else if (name == pluginMethodIdentifiers[ID_DESTROY_STREAM]) {
309         NPError npError = browser->destroystream(obj->npp, obj->stream, NPRES_USER_BREAK);
310         INT32_TO_NPVARIANT(npError, *result);
311         return true;        
312     } else if (name == pluginMethodIdentifiers[ID_TEST_GETINTIDENTIFIER]) {
313         if (argCount == 1 && NPVARIANT_IS_DOUBLE(args[0])) {
314             NPIdentifier identifier = browser->getintidentifier((int)NPVARIANT_TO_DOUBLE(args[0]));
315             INT32_TO_NPVARIANT((int32)identifier, *result);
316             return true;
317         }
318     }
319         
320     return false;
321 }
322
323 static bool pluginInvokeDefault(NPObject *obj, const NPVariant *args, uint32_t argCount, NPVariant *result)
324 {
325     INT32_TO_NPVARIANT(1, *result);
326     return true;
327 }
328
329 static void pluginInvalidate(NPObject *obj)
330 {
331 }
332
333 static NPObject *pluginAllocate(NPP npp, NPClass *theClass)
334 {
335     PluginObject *newInstance = (PluginObject*)malloc(sizeof(PluginObject));
336     
337     if (!identifiersInitialized) {
338         identifiersInitialized = true;
339         initializeIdentifiers();
340     }
341
342     newInstance->npp = npp;
343     newInstance->testObject = browser->createobject(npp, getTestClass());
344     newInstance->eventLogging = FALSE;
345     newInstance->logDestroy = FALSE;
346     newInstance->logSetWindow = FALSE;
347     newInstance->returnErrorFromNewStream = FALSE;
348     newInstance->stream = 0;
349     
350     newInstance->firstUrl = NULL;
351     newInstance->firstHeaders = NULL;
352     newInstance->lastUrl = NULL;
353     newInstance->lastHeaders = NULL;
354     
355     return (NPObject *)newInstance;
356 }
357
358 static void pluginDeallocate(NPObject *header) 
359 {
360     PluginObject* obj = (PluginObject*)header;
361     
362     browser->releaseobject(obj->testObject);
363
364     free(obj->firstUrl);
365     free(obj->firstHeaders);
366     free(obj->lastUrl);
367     free(obj->lastHeaders);
368
369     free(obj);
370 }
371
372 void handleCallback(PluginObject* object, const char *url, NPReason reason, void *notifyData)
373 {
374     assert(object);
375     
376     NPVariant args[2];
377     
378     NPObject *windowScriptObject;
379     browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject);
380     
381     NPIdentifier callbackIdentifier = notifyData;
382
383     INT32_TO_NPVARIANT(reason, args[0]);
384
385     char *strHdr = NULL;
386     if (object->firstUrl && object->firstHeaders && object->lastUrl && object->lastHeaders) {
387         // Format expected by JavaScript validator: four fields separated by \n\n:
388         // First URL; first header block; last URL; last header block.
389         // Note that header blocks already end with \n due to how NPStream::headers works.
390         int len = strlen(object->firstUrl) + 2
391             + strlen(object->firstHeaders) + 1
392             + strlen(object->lastUrl) + 2
393             + strlen(object->lastHeaders) + 1;
394         strHdr = (char*)malloc(len + 1);
395         snprintf(strHdr, len + 1, "%s\n\n%s\n%s\n\n%s\n",
396                  object->firstUrl, object->firstHeaders, object->lastUrl, object->lastHeaders);
397         STRINGN_TO_NPVARIANT(strHdr, len, args[1]);
398     } else
399         NULL_TO_NPVARIANT(args[1]);
400
401     NPVariant browserResult;
402     browser->invoke(object->npp, windowScriptObject, callbackIdentifier, args, 2, &browserResult);
403     browser->releasevariantvalue(&browserResult);
404
405     free(strHdr);
406 }
407
408 void notifyStream(PluginObject* object, const char *url, const char *headers)
409 {
410     if (object->firstUrl == NULL) {
411         if (url)
412             object->firstUrl = strdup(url);
413         if (headers)
414             object->firstHeaders = strdup(headers);
415     } else {
416         free(object->lastUrl);
417         free(object->lastHeaders);
418         object->lastUrl = (url ? strdup(url) : NULL);
419         object->lastHeaders = (headers ? strdup(headers) : NULL);
420     }
421 }