2
* Copyright © 2008 Christian Persch
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Library General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Library General Public License for more details.
14
* You should have received a copy of the GNU Library General Public
15
* License along with this library; if not, write to the
16
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
* Boston, MA 02111-1307, USA.
28
#include "totemNPClass.h"
29
#include "totemNPObject.h"
37
static const char *variantTypes[] = {
48
#define VARIANT_TYPE(type) (variantTypes[MIN (type, NPVariantType_Object + 1)])
51
totemNPObject::operator new (size_t aSize) throw ()
53
void *instance = ::operator new (aSize);
55
memset (instance, 0, aSize);
61
totemNPObject::totemNPObject (NPP aNPP)
63
mPlugin (reinterpret_cast<totemPlugin*>(aNPP->pdata))
65
NOTE (g_print ("totemNPObject ctor [%p]\n", (void*) this));
68
totemNPObject::~totemNPObject ()
70
NOTE (g_print ("totemNPObject dtor [%p]\n", (void*) this));
74
totemNPObject::Throw (const char *aMessage)
76
NOTE (g_print ("totemNPObject::Throw [%p] : %s\n", (void*) this, aMessage));
78
NPN_SetException (this, aMessage);
83
totemNPObject::ThrowPropertyNotWritable ()
85
return Throw ("Property not writable");
89
totemNPObject::ThrowSecurityError ()
91
return Throw ("Access denied");
95
totemNPObject::CheckArgc (uint32_t argc,
100
if (argc >= minArgc && argc <= maxArgc)
103
if (argc < minArgc) {
105
return Throw ("Not enough arguments");
111
return Throw ("Too many arguments");
117
totemNPObject::CheckArgType (NPVariantType argType,
118
NPVariantType expectedType,
124
case NPVariantType_Void:
125
case NPVariantType_Null:
126
conforms = (argType == expectedType);
129
case NPVariantType_Bool:
130
conforms = (argType == NPVariantType_Bool ||
131
argType == NPVariantType_Int32 ||
132
argType == NPVariantType_Double);
135
case NPVariantType_Int32:
136
case NPVariantType_Double:
137
/* FIXMEchpe: also accept NULL or VOID ? */
138
conforms = (argType == NPVariantType_Int32 ||
139
argType == NPVariantType_Double);
142
case NPVariantType_String:
143
case NPVariantType_Object:
144
conforms = (argType == expectedType ||
145
argType == NPVariantType_Null ||
146
argType == NPVariantType_Void);
154
g_snprintf (msg, sizeof (msg),
155
"Wrong type of argument %d: expected %s but got %s\n",
156
argNum, VARIANT_TYPE (expectedType), VARIANT_TYPE (argType));
165
totemNPObject::CheckArg (const NPVariant *argv,
170
if (!CheckArgc (argc, argNum + 1))
173
return CheckArgType (argv[argNum].type, type, argNum);
177
totemNPObject::CheckArgv (const NPVariant* argv,
179
uint32_t expectedArgc,
182
if (!CheckArgc (argc, expectedArgc, expectedArgc))
186
va_start (type_args, expectedArgc);
188
for (uint32_t i = 0; i < argc; ++i) {
189
NPVariantType type = NPVariantType (va_arg (type_args, int /* promotion */));
191
if (!CheckArgType (argv[i].type, type)) {
203
totemNPObject::GetBoolFromArguments (const NPVariant* argv,
208
if (!CheckArg (argv, argc, argNum, NPVariantType_Bool))
211
NPVariant arg = argv[argNum];
212
if (NPVARIANT_IS_BOOLEAN (arg)) {
213
_result = NPVARIANT_TO_BOOLEAN (arg);
214
} else if (NPVARIANT_IS_INT32 (arg)) {
215
_result = NPVARIANT_TO_INT32 (arg) != 0;
216
} else if (NPVARIANT_IS_DOUBLE (arg)) {
217
_result = NPVARIANT_TO_DOUBLE (arg) != 0.0;
227
totemNPObject::GetInt32FromArguments (const NPVariant* argv,
232
if (!CheckArg (argv, argc, argNum, NPVariantType_Int32))
235
NPVariant arg = argv[argNum];
236
if (NPVARIANT_IS_INT32 (arg)) {
237
_result = NPVARIANT_TO_INT32 (arg);
238
} else if (NPVARIANT_IS_DOUBLE (arg)) {
239
_result = int32_t (NPVARIANT_TO_DOUBLE (arg));
240
/* FIXMEchpe: overflow? */
247
totemNPObject::GetDoubleFromArguments (const NPVariant* argv,
252
if (!CheckArg (argv, argc, argNum, NPVariantType_Double))
255
NPVariant arg = argv[argNum];
256
if (NPVARIANT_IS_DOUBLE (arg)) {
257
_result = NPVARIANT_TO_DOUBLE (arg);
258
} else if (NPVARIANT_IS_INT32 (arg)) {
259
_result = double (NPVARIANT_TO_INT32 (arg));
266
totemNPObject::GetStringFromArguments (const NPVariant* argv,
269
const char*& _result)
271
if (!CheckArg (argv, argc, argNum, NPVariantType_String))
274
NPVariant arg = argv[argNum];
275
if (NPVARIANT_IS_STRING (arg)) {
276
NPString string = NPVARIANT_TO_STRING (arg);
277
// FIXMEchpe this assumes it's 0-terminated, check that this holds!
278
_result = string.UTF8Characters;
279
} else if (NPVARIANT_IS_NULL (arg) ||
280
NPVARIANT_IS_VOID (arg)) {
288
totemNPObject::DupStringFromArguments (const NPVariant* argv,
293
NPN_MemFree (_result);
296
const char *newValue;
297
if (!GetStringFromArguments (argv, argc, argNum, newValue))
300
/* This assumes every NPString is 0-terminated. FIXMEchpe check that this holds! */
301
_result = NPN_StrDup (newValue);
306
totemNPObject::GetObjectFromArguments (const NPVariant* argv,
311
if (!CheckArg (argv, argc, argNum, NPVariantType_Object))
314
NPVariant arg = argv[argNum];
315
if (NPVARIANT_IS_STRING (arg)) {
316
_result = NPVARIANT_TO_OBJECT (arg);
317
} else if (NPVARIANT_IS_NULL (arg) ||
318
NPVARIANT_IS_VOID (arg)) {
326
totemNPObject::VoidVariant (NPVariant* _result)
328
VOID_TO_NPVARIANT (*_result);
333
totemNPObject::NullVariant (NPVariant* _result)
335
NULL_TO_NPVARIANT (*_result);
340
totemNPObject::BoolVariant (NPVariant* _result,
343
BOOLEAN_TO_NPVARIANT (value, *_result);
348
totemNPObject::Int32Variant (NPVariant* _result,
351
INT32_TO_NPVARIANT (value, *_result);
356
totemNPObject::DoubleVariant (NPVariant* _result,
359
DOUBLE_TO_NPVARIANT (value, *_result);
364
totemNPObject::StringVariant (NPVariant* _result,
369
NULL_TO_NPVARIANT (*_result);
374
len = strlen (value);
375
dup = (char*) NPN_MemDup (value, len + 1);
377
dup = (char*) NPN_MemDup (value, len);
381
STRINGN_TO_NPVARIANT (dup, len, *_result);
383
NULL_TO_NPVARIANT (*_result);
391
totemNPObject::ObjectVariant (NPVariant* _result,
395
NPN_RetainObject (object);
396
OBJECT_TO_NPVARIANT (object, *_result);
398
NULL_TO_NPVARIANT (*_result);
404
/* NPObject method default implementations */
407
totemNPObject::Invalidate ()
409
NOTE (g_print ("totemNPObject %p invalidated\n", (void*) this));
416
totemNPObject::HasMethod (NPIdentifier aName)
421
NOTE (g_print ("totemNPObject::HasMethod [%p] %s\n", (void*) this, NPN_UTF8FromIdentifier (aName)));
422
if (GetClass()->GetMethodIndex (aName) >= 0)
425
if (aName == NPN_GetStringIdentifier ("__noSuchMethod__"))
432
totemNPObject::Invoke (NPIdentifier aName,
433
const NPVariant *argv,
440
NOTE (g_print ("totemNPObject::Invoke [%p] %s\n", (void*) this, NPN_UTF8FromIdentifier (aName)));
441
int methodIndex = GetClass()->GetMethodIndex (aName);
442
if (methodIndex >= 0)
443
return InvokeByIndex (methodIndex, argv, argc, _result);
445
if (aName == NPN_GetStringIdentifier ("__noSuchMethod__")) {
446
/* http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Object:_noSuchMethod */
447
if (!CheckArgv (argv, argc, 2, NPVariantType_String, NPVariantType_Object))
450
const char *id = NPVARIANT_TO_STRING (argv[0]).UTF8Characters;
451
g_message ("NOTE: site calls unknown function \"%s\" on totemNPObject %p\n", id ? id : "(null)", (void*) this);
453
/* Silently ignore the invocation */
454
VOID_TO_NPVARIANT (*_result);
458
return Throw ("No method with this name exists.");
462
totemNPObject::InvokeDefault (const NPVariant *argv,
469
NOTE (g_print ("totemNPObject::InvokeDefault [%p]\n", (void*) this));
470
int defaultMethodIndex = GetClass()->GetDefaultMethodIndex ();
471
if (defaultMethodIndex >= 0)
472
return InvokeByIndex (defaultMethodIndex, argv, argc, _result);
478
totemNPObject::HasProperty (NPIdentifier aName)
483
NOTE (g_print ("totemNPObject::HasProperty [%p] %s\n", (void*) this, NPN_UTF8FromIdentifier (aName)));
484
if (GetClass()->GetPropertyIndex (aName) >= 0)
491
totemNPObject::GetProperty (NPIdentifier aName,
497
NOTE (g_print ("totemNPObject::GetProperty [%p] %s\n", (void*) this, NPN_UTF8FromIdentifier (aName)));
498
int propertyIndex = GetClass()->GetPropertyIndex (aName);
499
if (propertyIndex >= 0)
500
return GetPropertyByIndex (propertyIndex, _result);
502
return Throw ("No property with this name exists.");
506
totemNPObject::SetProperty (NPIdentifier aName,
507
const NPVariant *aValue)
512
NOTE (g_print ("totemNPObject::SetProperty [%p] %s\n", (void*) this, NPN_UTF8FromIdentifier (aName)));
513
int propertyIndex = GetClass()->GetPropertyIndex (aName);
514
if (propertyIndex >= 0)
515
return SetPropertyByIndex (propertyIndex, aValue);
517
return Throw ("No property with this name exists.");
521
totemNPObject::RemoveProperty (NPIdentifier aName)
526
NOTE (g_print ("totemNPObject::RemoveProperty [%p] %s\n", (void*) this, NPN_UTF8FromIdentifier (aName)));
527
int propertyIndex = GetClass()->GetPropertyIndex (aName);
528
if (propertyIndex >= 0)
529
return RemovePropertyByIndex (propertyIndex);
531
return Throw ("No property with this name exists.");
535
totemNPObject::Enumerate (NPIdentifier **_result,
541
NOTE (g_print ("totemNPObject::Enumerate [%p]\n", (void*) this));
542
return GetClass()->EnumerateProperties (_result, _count);
546
totemNPObject::Construct (const NPVariant *argv,
553
NOTE (g_print ("totemNPObject::Construct [%p]\n", (void*) this));
554
return false; /* FIXMEchpe! */
557
/* by-index methods */
560
totemNPObject::InvokeByIndex (int aIndex,
561
const NPVariant *argv,
569
totemNPObject::GetPropertyByIndex (int aIndex,
576
totemNPObject::SetPropertyByIndex (int aIndex,
577
const NPVariant *aValue)
583
totemNPObject::RemovePropertyByIndex (int aIndex)
585
return Throw ("Removing properties is not supported.");