Updated plugin binding API to reflect latest revision from
[WebKit-https.git] / JavaScriptCore / bindings / npruntime.cpp
1 /*
2  * Copyright (C) 2004 Apple Computer, 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 COMPUTER, 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 COMPUTER, 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 #include <CoreFoundation/CoreFoundation.h>
26
27 #include <npruntime.h>
28 #include <c_utility.h>
29
30 static Boolean identifierEqual(const void *value1, const void *value2)
31 {
32     return strcmp((const char *)value1, (const char *)value2) == 0;
33 }
34
35 static CFHashCode identifierHash (const void *value)
36 {
37     const char *key = (const char *)value;
38     unsigned int len = strlen(key);
39     unsigned int result = len;
40
41     if (len <= 16) {
42         unsigned cnt = len;
43         while (cnt--) result = result * 257 + *(unsigned char *)key++;
44     } else {
45         unsigned cnt;
46         for (cnt = 8; cnt > 0; cnt--) result = result * 257 + *(unsigned char *)key++;
47         key += (len - 16);
48         for (cnt = 8; cnt > 0; cnt--) result = result * 257 + *(unsigned char *)key++;
49     }
50     result += (result << (len & 31));
51
52     return result;
53 }
54
55 CFDictionaryKeyCallBacks identifierCallbacks = {
56     0,
57     NULL,
58     NULL,
59     NULL,
60     identifierEqual,
61     identifierHash
62 };
63
64 static CFMutableDictionaryRef identifierDictionary = 0;
65
66 static CFMutableDictionaryRef getIdentifierDictionary()
67 {
68     if (!identifierDictionary)
69         identifierDictionary = CFDictionaryCreateMutable(NULL, 0, &identifierCallbacks, NULL);
70     return identifierDictionary;
71 }
72
73 #define INITIAL_IDENTIFIER_NAME_COUNT   128
74
75 static const char **identifierNames = 0;
76 static unsigned int maxIdentifierNames;
77 static uint32_t identifierCount = 1;
78
79 NPIdentifier NPN_GetIdentifier (const NPUTF8 *name)
80 {
81     assert (name);
82     
83     if (name) {
84         NPIdentifier identifier = 0;
85         
86         identifier = (NPIdentifier)CFDictionaryGetValue (getIdentifierDictionary(), (const void *)name);
87         if (identifier == 0) {
88             identifier = (NPIdentifier)identifierCount++;
89             // We never release identifier names, so this dictionary will grow, as will
90             // the memory for the identifier name strings.
91             const char *identifierName = strdup (name);
92             
93             if (!identifierNames) {
94                 identifierNames = (const char **)malloc (sizeof(const char *)*INITIAL_IDENTIFIER_NAME_COUNT);
95                 maxIdentifierNames = INITIAL_IDENTIFIER_NAME_COUNT;
96             }
97             
98             if (identifierCount >= maxIdentifierNames) {
99                 maxIdentifierNames *= 2;
100                 identifierNames = (const char **)realloc ((void *)identifierNames, sizeof(const char *)*maxIdentifierNames);
101             }
102             
103             identifierNames[(uint32_t)identifier] = identifierName;
104
105             CFDictionaryAddValue (getIdentifierDictionary(), identifierName, (const void *)identifier);
106         }
107         return identifier;
108     }
109     
110     return 0;
111 }
112
113 bool NPN_IsValidIdentifier (const NPUTF8 *name)
114 {
115     assert (name);
116     
117     if (name)
118         return CFDictionaryGetValue (getIdentifierDictionary(), (const void *)name) == 0 ? false : true;
119
120     return false;
121 }
122
123 void NPN_GetIdentifiers (const NPUTF8 **names, int nameCount, NPIdentifier *identifiers)
124 {
125     assert (names);
126     assert (identifiers);
127     
128     if (names && identifiers) {
129         int i;
130         
131         for (i = 0; i < nameCount; i++) {
132             identifiers[i] = NPN_GetIdentifier (names[i]);
133         }
134     }
135 }
136
137 const NPUTF8 *NPN_UTF8FromIdentifier (NPIdentifier identifier)
138 {
139     if (identifier == 0 || (uint32_t)identifier >= identifierCount)
140         return NULL;
141         
142     return (const NPUTF8 *)identifierNames[(uint32_t)identifier];
143 }
144
145 NPBool NPN_VariantIsVoid (const NPVariant *variant)
146 {
147     return variant->type == NPVariantVoidType;
148 }
149
150 NPBool NPN_VariantIsNull (const NPVariant *variant)
151 {
152     return variant->type == NPVariantNullType;
153 }
154
155 NPBool NPN_VariantIsUndefined (const NPVariant *variant)
156 {
157     return variant->type == NPVariantUndefinedType;
158 }
159
160 NPBool NPN_VariantIsBool (const NPVariant *variant)
161 {
162     return variant->type == NPVariantBoolType;
163 }
164
165 NPBool NPN_VariantIsInt32 (const NPVariant *variant)
166 {
167     return variant->type == NPVariantInt32Type;
168 }
169
170 NPBool NPN_VariantIsDouble (const NPVariant *variant)
171 {
172     return variant->type == NPVariantDoubleType;
173 }
174
175 NPBool NPN_VariantIsString (const NPVariant *variant)
176 {
177     return variant->type == NPVariantStringType;
178 }
179
180 NPBool NPN_VariantIsObject (const NPVariant *variant)
181 {
182     return variant->type == NPVariantObjectType;
183 }
184
185 NPBool NPN_VariantToBool (const NPVariant *variant, NPBool *result)
186 {
187     if (variant->type != NPVariantBoolType)
188         return false;
189         
190     *result = variant->value.boolValue;
191     
192     return true;
193 }
194
195 NPString NPN_VariantToString (const NPVariant *variant)
196 {
197     if (variant->type != NPVariantStringType) {
198         NPString emptyString = { 0, 0 };
199         return emptyString;
200     }
201             
202     return variant->value.stringValue;
203 }
204
205 NPBool NPN_VariantToInt32 (const NPVariant *variant, int32_t *result)
206 {
207     if (variant->type == NPVariantInt32Type)
208         *result = variant->value.intValue;
209     else if (variant->type != NPVariantDoubleType)
210         *result = (int32_t)variant->value.doubleValue;
211     else
212         return false;
213     
214     return true;
215 }
216
217 NPBool NPN_VariantToDouble (const NPVariant *variant, double *result)
218 {
219     if (variant->type == NPVariantInt32Type)
220         *result = (double)variant->value.intValue;
221     else if (variant->type != NPVariantDoubleType)
222         *result = variant->value.doubleValue;
223     else
224         return false;
225     
226     return true;
227 }
228
229 NPBool NPN_VariantToObject (const NPVariant *variant, NPObject **result)
230 {
231     if (variant->type != NPVariantObjectType)
232         return false;
233             
234     *result = variant->value.objectValue;
235     
236     return true;
237 }
238
239 void NPN_InitializeVariantAsVoid (NPVariant *variant)
240 {
241     variant->type = NPVariantVoidType;
242 }
243
244 void NPN_InitializeVariantAsNull (NPVariant *variant)
245 {
246     variant->type = NPVariantNullType;
247 }
248
249 void NPN_InitializeVariantAsUndefined (NPVariant *variant)
250 {
251     variant->type = NPVariantUndefinedType;
252 }
253
254 void NPN_InitializeVariantWithBool (NPVariant *variant, NPBool value)
255 {
256     variant->type = NPVariantBoolType;
257     variant->value.boolValue = value;
258 }
259
260 void NPN_InitializeVariantWithInt32 (NPVariant *variant, int32_t value)
261 {
262     variant->type = NPVariantInt32Type;
263     variant->value.intValue = value;
264 }
265
266 void NPN_InitializeVariantWithDouble (NPVariant *variant, double value)
267 {
268     variant->type = NPVariantDoubleType;
269     variant->value.doubleValue = value;
270 }
271
272 void NPN_InitializeVariantWithString (NPVariant *variant, const NPString *value)
273 {
274     variant->type = NPVariantStringType;
275     variant->value.stringValue = *value;
276 }
277
278 void NPN_InitializeVariantWithStringCopy (NPVariant *variant, const NPString *value)
279 {
280     variant->type = NPVariantStringType;
281     variant->value.stringValue.UTF8Length = value->UTF8Length;
282     variant->value.stringValue.UTF8Characters = (NPUTF8 *)malloc(sizeof(NPUTF8) * value->UTF8Length);
283     memcpy ((void *)variant->value.stringValue.UTF8Characters, value->UTF8Characters, sizeof(NPUTF8) * value->UTF8Length);
284 }
285
286 void NPN_InitializeVariantWithObject (NPVariant *variant, NPObject *value)
287 {
288     variant->type = NPVariantObjectType;
289     variant->value.objectValue = NPN_RetainObject (value);
290 }
291
292 void NPN_InitializeVariantWithVariant (NPVariant *destination, const NPVariant *source)
293 {
294     switch (source->type){
295         case NPVariantVoidType: {
296             NPN_InitializeVariantAsVoid (destination);
297             break;
298         }
299         case NPVariantNullType: {
300             NPN_InitializeVariantAsNull (destination);
301             break;
302         }
303         case NPVariantUndefinedType: {
304             NPN_InitializeVariantAsUndefined (destination);
305             break;
306         }
307         case NPVariantBoolType: {
308             NPN_InitializeVariantWithBool (destination, source->value.boolValue);
309             break;
310         }
311         case NPVariantInt32Type: {
312             NPN_InitializeVariantWithInt32 (destination, source->value.intValue);
313             break;
314         }
315         case NPVariantDoubleType: {
316             NPN_InitializeVariantWithDouble (destination, source->value.doubleValue);
317             break;
318         }
319         case NPVariantStringType: {
320             NPN_InitializeVariantWithStringCopy (destination, &source->value.stringValue);
321             break;
322         }
323         case NPVariantObjectType: {
324             NPN_InitializeVariantWithObject (destination, source->value.objectValue);
325             break;
326         }
327         default: {
328             NPN_InitializeVariantAsUndefined (destination);
329             break;
330         }
331     }
332 }
333
334 void NPN_ReleaseVariantValue (NPVariant *variant)
335 {
336     assert (variant);
337     
338     if (variant->type == NPVariantObjectType) {
339         NPN_ReleaseObject (variant->value.objectValue);
340         variant->value.objectValue = 0;
341     }
342     else if (variant->type == NPVariantStringType) {
343         free ((void *)variant->value.stringValue.UTF8Characters);
344         variant->value.stringValue.UTF8Characters = 0;
345         variant->value.stringValue.UTF8Length = 0;
346     }
347     
348     variant->type = NPVariantUndefinedType;
349 }
350
351
352 NPObject *NPN_CreateObject (NPClass *aClass)
353 {
354     assert (aClass);
355
356     if (aClass) {
357         NPObject *obj;
358         
359         if (aClass->allocate != NULL)
360             obj = aClass->allocate ();
361         else
362             obj = (NPObject *)malloc (sizeof(NPObject));
363             
364         obj->_class = aClass;
365         obj->referenceCount = 1;
366
367         return obj;
368     }
369     
370     return 0;
371 }
372
373
374 NPObject *NPN_RetainObject (NPObject *obj)
375 {
376     assert (obj);
377
378     if (obj)
379         obj->referenceCount++;
380
381     return obj;
382 }
383
384
385 void NPN_ReleaseObject (NPObject *obj)
386 {
387     assert (obj);
388     assert (obj->referenceCount >= 1);
389
390     if (obj && obj->referenceCount >= 1) {
391         obj->referenceCount--;
392                 
393         if (obj->referenceCount == 0) {
394             if (obj->_class->deallocate)
395                 obj->_class->deallocate (obj);
396             else
397                 free (obj);
398         }
399     }
400 }
401
402 bool NPN_IsKindOfClass (const NPObject *obj, const NPClass *aClass)
403 {
404     assert (obj);
405     assert (aClass);
406     
407     if (obj && aClass) {
408         if (obj->_class == aClass)
409             return true;
410     }
411     
412     return false;
413 }
414
415
416 void NPN_SetExceptionWithUTF8 (NPObject *obj, const NPUTF8 *message, int32_t length)
417 {
418     assert (obj);
419     assert (message);
420  
421     if (obj && message) {
422         NPString string;
423         string.UTF8Characters = message;
424         string.UTF8Length = length;
425         NPN_SetException (obj, &string);
426     }
427 }
428
429
430 void NPN_SetException (NPObject *obj, NPString *message)
431 {
432     // FIX ME.  Need to implement.
433 }
434
435 // ---------------------------------- Types ----------------------------------
436
437 // ---------------------------------- NP_Array ----------------------------------
438
439 typedef struct
440 {
441     NPObject object;
442     NPObject **objects;
443     int32_t count;
444 } ArrayObject;
445
446 static NPObject *arrayAllocate()
447 {
448     return (NPObject *)malloc(sizeof(ArrayObject));
449 }
450
451 static void arrayDeallocate (ArrayObject *array)
452 {
453     int32_t i;
454     
455     for (i = 0; i < array->count; i++) {
456         NPN_ReleaseObject(array->objects[i]);
457     }
458     free (array->objects);
459     free (array);
460 }
461
462
463 static NPClass _arrayClass = { 
464     1,
465     arrayAllocate, 
466     (NPDeallocateFunctionPtr)arrayDeallocate, 
467     0,
468     0,
469     0,
470     0,
471     0,
472     0,
473 };
474
475 static NPClass *arrayClass = &_arrayClass;
476 NPClass *NPArrayClass = arrayClass;
477
478 NPArray *NPN_CreateArray (NPObject **objects, int32_t count)
479 {
480     int32_t i;
481
482     assert (count >= 0);
483     
484     ArrayObject *array = (ArrayObject *)NPN_CreateObject(arrayClass);
485     array->objects = (NPObject **)malloc (sizeof(NPObject *)*count);
486     for (i = 0; i < count; i++) {
487         array->objects[i] = NPN_RetainObject (objects[i]);
488     }
489     
490     return (NPArray *)array;
491 }
492
493 NPArray *NPN_CreateArrayV (int32_t count, ...)
494 {
495     va_list args;
496
497     assert (count >= 0);
498
499     ArrayObject *array = (ArrayObject *)NPN_CreateObject(arrayClass);
500     array->objects = (NPObject **)malloc (sizeof(NPObject *)*count);
501
502     va_start (args, count);
503     
504     int32_t i;
505     for (i = 0; i < count; i++) {
506         NPObject *obj = va_arg (args, NPObject *);
507         array->objects[i] = NPN_RetainObject (obj);
508     }
509         
510     va_end (args);
511
512     return (NPArray *)array;
513 }
514
515 NPObject *NPN_ObjectAtIndex (NPArray *obj, int32_t index)
516 {
517     ArrayObject *array = (ArrayObject *)obj;
518
519     assert (index < array->count && array > 0);
520
521     return NPN_RetainObject (array->objects[index]);
522 }
523