1 /*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Holger Hans Peter Freyther
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "PluginObject.h"
28
29 #include "TestObject.h"
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33
34 #include <string.h>
35 #include <stdlib.h>
36
pluginLog(NPP instance,const char * format,...)37 void pluginLog(NPP instance, const char* format, ...)
38 {
39 va_list args;
40 va_start(args, format);
41 char message[2048] = "PLUGIN: ";
42 vsprintf(message + strlen(message), format, args);
43 va_end(args);
44
45 NPObject* windowObject = 0;
46 NPError error = browser->getvalue(instance, NPNVWindowNPObject, &windowObject);
47 if (error != NPERR_NO_ERROR) {
48 fprintf(stderr, "Failed to retrieve window object while logging: %s\n", message);
49 return;
50 }
51
52 NPVariant consoleVariant;
53 if (!browser->getproperty(instance, windowObject, browser->getstringidentifier("console"), &consoleVariant)) {
54 fprintf(stderr, "Failed to retrieve console object while logging: %s\n", message);
55 browser->releaseobject(windowObject);
56 return;
57 }
58
59 NPObject* consoleObject = NPVARIANT_TO_OBJECT(consoleVariant);
60
61 NPVariant messageVariant;
62 STRINGZ_TO_NPVARIANT(message, messageVariant);
63
64 NPVariant result;
65 if (!browser->invoke(instance, consoleObject, browser->getstringidentifier("log"), &messageVariant, 1, &result)) {
66 fprintf(stderr, "Failed to invoke console.log while logging: %s\n", message);
67 browser->releaseobject(consoleObject);
68 browser->releaseobject(windowObject);
69 return;
70 }
71
72 browser->releasevariantvalue(&result);
73 browser->releaseobject(consoleObject);
74 browser->releaseobject(windowObject);
75 }
76
77 static void pluginInvalidate(NPObject*);
78 static bool pluginHasProperty(NPObject*, NPIdentifier name);
79 static bool pluginHasMethod(NPObject*, NPIdentifier name);
80 static bool pluginGetProperty(NPObject*, NPIdentifier name, NPVariant*);
81 static bool pluginSetProperty(NPObject*, NPIdentifier name, const NPVariant*);
82 static bool pluginInvoke(NPObject*, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result);
83 static bool pluginInvokeDefault(NPObject*, const NPVariant* args, uint32_t argCount, NPVariant* result);
84 static NPObject* pluginAllocate(NPP npp, NPClass*);
85 static void pluginDeallocate(NPObject*);
86
87 NPNetscapeFuncs* browser;
88
89 static NPClass pluginClass = {
90 NP_CLASS_STRUCT_VERSION,
91 pluginAllocate,
92 pluginDeallocate,
93 pluginInvalidate,
94 pluginHasMethod,
95 pluginInvoke,
96 pluginInvokeDefault,
97 pluginHasProperty,
98 pluginGetProperty,
99 pluginSetProperty,
100 };
101
getPluginClass(void)102 NPClass *getPluginClass(void)
103 {
104 return &pluginClass;
105 }
106
107 static bool identifiersInitialized = false;
108
109 #define ID_PROPERTY_PROPERTY 0
110 #define ID_PROPERTY_EVENT_LOGGING 1
111 #define ID_PROPERTY_HAS_STREAM 2
112 #define ID_PROPERTY_TEST_OBJECT 3
113 #define ID_PROPERTY_LOG_DESTROY 4
114 #define ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM 5
115 #define NUM_PROPERTY_IDENTIFIERS 6
116
117 static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
118 static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
119 "property",
120 "eventLoggingEnabled",
121 "hasStream",
122 "testObject",
123 "logDestroy",
124 "returnErrorFromNewStream",
125 };
126
127 enum {
128 ID_TEST_CALLBACK_METHOD = 0,
129 ID_TEST_GETURL,
130 ID_REMOVE_DEFAULT_METHOD,
131 ID_TEST_DOM_ACCESS,
132 ID_TEST_GET_URL_NOTIFY,
133 ID_TEST_INVOKE_DEFAULT,
134 ID_DESTROY_STREAM,
135 ID_TEST_ENUMERATE,
136 ID_TEST_GETINTIDENTIFIER,
137 ID_TEST_GET_PROPERTY,
138 ID_TEST_HAS_PROPERTY,
139 ID_TEST_HAS_METHOD,
140 ID_TEST_EVALUATE,
141 ID_TEST_GET_PROPERTY_RETURN_VALUE,
142 ID_TEST_IDENTIFIER_TO_STRING,
143 ID_TEST_IDENTIFIER_TO_INT,
144 ID_TEST_POSTURL_FILE,
145 ID_TEST_CONSTRUCT,
146 ID_TEST_THROW_EXCEPTION_METHOD,
147 ID_DESTROY_NULL_STREAM,
148 NUM_METHOD_IDENTIFIERS
149 };
150
151 static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
152 static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
153 "testCallback",
154 "getURL",
155 "removeDefaultMethod",
156 "testDOMAccess",
157 "getURLNotify",
158 "testInvokeDefault",
159 "destroyStream",
160 "testEnumerate",
161 "testGetIntIdentifier",
162 "testGetProperty",
163 "testHasProperty",
164 "testHasMethod",
165 "testEvaluate",
166 "testGetPropertyReturnValue",
167 "testIdentifierToString",
168 "testIdentifierToInt",
169 "testPostURLFile",
170 "testConstruct",
171 "testThrowException",
172 "destroyNullStream"
173 };
174
createCStringFromNPVariant(const NPVariant * variant)175 static NPUTF8* createCStringFromNPVariant(const NPVariant* variant)
176 {
177 size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length;
178 NPUTF8* result = (NPUTF8*)malloc(length + 1);
179 memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length);
180 result[length] = '\0';
181 return result;
182 }
183
initializeIdentifiers(void)184 static void initializeIdentifiers(void)
185 {
186 browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, pluginPropertyIdentifiers);
187 browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, pluginMethodIdentifiers);
188 }
189
pluginHasProperty(NPObject * obj,NPIdentifier name)190 static bool pluginHasProperty(NPObject *obj, NPIdentifier name)
191 {
192 for (int i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++)
193 if (name == pluginPropertyIdentifiers[i])
194 return true;
195 return false;
196 }
197
pluginHasMethod(NPObject * obj,NPIdentifier name)198 static bool pluginHasMethod(NPObject *obj, NPIdentifier name)
199 {
200 for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++)
201 if (name == pluginMethodIdentifiers[i])
202 return true;
203 return false;
204 }
205
pluginGetProperty(NPObject * obj,NPIdentifier name,NPVariant * result)206 static bool pluginGetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)
207 {
208 PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
209 if (name == pluginPropertyIdentifiers[ID_PROPERTY_PROPERTY]) {
210 STRINGZ_TO_NPVARIANT("property", *result);
211 return true;
212 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
213 BOOLEAN_TO_NPVARIANT(plugin->eventLogging, *result);
214 return true;
215 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
216 BOOLEAN_TO_NPVARIANT(plugin->logDestroy, *result);
217 return true;
218 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_HAS_STREAM]) {
219 BOOLEAN_TO_NPVARIANT(plugin->stream != 0, *result);
220 return true;
221 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT]) {
222 NPObject* testObject = plugin->testObject;
223 browser->retainobject(testObject);
224 OBJECT_TO_NPVARIANT(testObject, *result);
225 return true;
226 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) {
227 BOOLEAN_TO_NPVARIANT(plugin->returnErrorFromNewStream, *result);
228 return true;
229 }
230 return false;
231 }
232
pluginSetProperty(NPObject * obj,NPIdentifier name,const NPVariant * variant)233 static bool pluginSetProperty(NPObject* obj, NPIdentifier name, const NPVariant* variant)
234 {
235 PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
236 if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
237 plugin->eventLogging = NPVARIANT_TO_BOOLEAN(*variant);
238 return true;
239 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
240 plugin->logDestroy = NPVARIANT_TO_BOOLEAN(*variant);
241 return true;
242 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) {
243 plugin->returnErrorFromNewStream = NPVARIANT_TO_BOOLEAN(*variant);
244 return true;
245 }
246
247 return false;
248 }
249
testDOMAccess(PluginObject * obj,const NPVariant *,uint32_t,NPVariant * result)250 static bool testDOMAccess(PluginObject* obj, const NPVariant*, uint32_t, NPVariant* result)
251 {
252 // Get plug-in's DOM element
253 NPObject* elementObject;
254 if (browser->getvalue(obj->npp, NPNVPluginElementNPObject, &elementObject) == NPERR_NO_ERROR) {
255 // Get style
256 NPVariant styleVariant;
257 NPIdentifier styleIdentifier = browser->getstringidentifier("style");
258 if (browser->getproperty(obj->npp, elementObject, styleIdentifier, &styleVariant) && NPVARIANT_IS_OBJECT(styleVariant)) {
259 // Set style.border
260 NPIdentifier borderIdentifier = browser->getstringidentifier("border");
261 NPVariant borderVariant;
262 STRINGZ_TO_NPVARIANT("3px solid red", borderVariant);
263 browser->setproperty(obj->npp, NPVARIANT_TO_OBJECT(styleVariant), borderIdentifier, &borderVariant);
264 browser->releasevariantvalue(&styleVariant);
265 }
266
267 browser->releaseobject(elementObject);
268 }
269 VOID_TO_NPVARIANT(*result);
270 return true;
271 }
272
stringVariantToIdentifier(NPVariant variant)273 static NPIdentifier stringVariantToIdentifier(NPVariant variant)
274 {
275 assert(NPVARIANT_IS_STRING(variant));
276 NPUTF8* utf8String = createCStringFromNPVariant(&variant);
277 NPIdentifier identifier = browser->getstringidentifier(utf8String);
278 free(utf8String);
279 return identifier;
280 }
281
int32VariantToIdentifier(NPVariant variant)282 static NPIdentifier int32VariantToIdentifier(NPVariant variant)
283 {
284 assert(NPVARIANT_IS_INT32(variant));
285 int32 integer = NPVARIANT_TO_INT32(variant);
286 return browser->getintidentifier(integer);
287 }
288
doubleVariantToIdentifier(NPVariant variant)289 static NPIdentifier doubleVariantToIdentifier(NPVariant variant)
290 {
291 assert(NPVARIANT_IS_DOUBLE(variant));
292 double value = NPVARIANT_TO_DOUBLE(variant);
293 // Sadly there is no "getdoubleidentifier"
294 int32 integer = static_cast<int32>(value);
295 return browser->getintidentifier(integer);
296 }
297
variantToIdentifier(NPVariant variant)298 static NPIdentifier variantToIdentifier(NPVariant variant)
299 {
300 if (NPVARIANT_IS_STRING(variant))
301 return stringVariantToIdentifier(variant);
302 else if (NPVARIANT_IS_INT32(variant))
303 return int32VariantToIdentifier(variant);
304 else if (NPVARIANT_IS_DOUBLE(variant))
305 return doubleVariantToIdentifier(variant);
306 return 0;
307 }
308
testIdentifierToString(PluginObject *,const NPVariant * args,uint32_t argCount,NPVariant * result)309 static bool testIdentifierToString(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
310 {
311 if (argCount != 1)
312 return false;
313 NPIdentifier identifier = variantToIdentifier(args[0]);
314 if (!identifier)
315 return false;
316 NPUTF8* utf8String = browser->utf8fromidentifier(identifier);
317 if (!utf8String)
318 return false;
319 STRINGZ_TO_NPVARIANT(utf8String, *result);
320 return true;
321 }
322
testIdentifierToInt(PluginObject *,const NPVariant * args,uint32_t argCount,NPVariant * result)323 static bool testIdentifierToInt(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
324 {
325 if (argCount != 1)
326 return false;
327 NPIdentifier identifier = variantToIdentifier(args[0]);
328 if (!identifier)
329 return false;
330 int32 integer = browser->intfromidentifier(identifier);
331 INT32_TO_NPVARIANT(integer, *result);
332 return true;
333 }
334
testCallback(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)335 static bool testCallback(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
336 {
337 if (argCount == 0 || !NPVARIANT_IS_STRING(args[0]))
338 return false;
339
340 NPObject* windowScriptObject;
341 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
342
343 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
344 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
345 free(callbackString);
346
347 NPVariant browserResult;
348 browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, 0, 0, &browserResult);
349 browser->releasevariantvalue(&browserResult);
350
351 browser->releaseobject(windowScriptObject);
352
353 VOID_TO_NPVARIANT(*result);
354 return true;
355 }
356
getURL(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)357 static bool getURL(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
358 {
359 if (argCount == 2 && NPVARIANT_IS_STRING(args[0]) && NPVARIANT_IS_STRING(args[1])) {
360 NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
361 NPUTF8* targetString = createCStringFromNPVariant(&args[1]);
362 NPError npErr = browser->geturl(obj->npp, urlString, targetString);
363 free(urlString);
364 free(targetString);
365
366 INT32_TO_NPVARIANT(npErr, *result);
367 return true;
368 } else if (argCount == 1 && NPVARIANT_IS_STRING(args[0])) {
369 NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
370 NPError npErr = browser->geturl(obj->npp, urlString, 0);
371 free(urlString);
372
373 INT32_TO_NPVARIANT(npErr, *result);
374 return true;
375 }
376 return false;
377 }
378
removeDefaultMethod(PluginObject *,const NPVariant * args,uint32_t argCount,NPVariant * result)379 static bool removeDefaultMethod(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
380 {
381 pluginClass.invokeDefault = 0;
382 VOID_TO_NPVARIANT(*result);
383 return true;
384 }
385
getURLNotify(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)386 static bool getURLNotify(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
387 {
388 if (argCount != 3 || !NPVARIANT_IS_STRING(args[0])
389 || (!NPVARIANT_IS_STRING(args[1]) && !NPVARIANT_IS_NULL(args[1]))
390 || !NPVARIANT_IS_STRING(args[2]))
391 return false;
392
393 NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
394 NPUTF8* targetString = (NPVARIANT_IS_STRING(args[1]) ? createCStringFromNPVariant(&args[1]) : NULL);
395 NPUTF8* callbackString = createCStringFromNPVariant(&args[2]);
396
397 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
398 browser->geturlnotify(obj->npp, urlString, targetString, callbackIdentifier);
399
400 free(urlString);
401 free(targetString);
402 free(callbackString);
403
404 VOID_TO_NPVARIANT(*result);
405 return true;
406 }
407
testInvokeDefault(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)408 static bool testInvokeDefault(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
409 {
410 if (!NPVARIANT_IS_OBJECT(args[0]))
411 return false;
412
413 NPObject *callback = NPVARIANT_TO_OBJECT(args[0]);
414
415 NPVariant invokeArgs[1];
416 NPVariant browserResult;
417
418 STRINGZ_TO_NPVARIANT("test", invokeArgs[0]);
419 bool retval = browser->invokeDefault(obj->npp, callback, invokeArgs, 1, &browserResult);
420
421 if (retval)
422 browser->releasevariantvalue(&browserResult);
423
424 BOOLEAN_TO_NPVARIANT(retval, *result);
425 return true;
426 }
427
destroyStream(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)428 static bool destroyStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
429 {
430 NPError npError = browser->destroystream(obj->npp, obj->stream, NPRES_USER_BREAK);
431 INT32_TO_NPVARIANT(npError, *result);
432 return true;
433 }
434
destroyNullStream(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)435 static bool destroyNullStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
436 {
437 NPError npError = browser->destroystream(obj->npp, 0, NPRES_USER_BREAK);
438 INT32_TO_NPVARIANT(npError, *result);
439 return true;
440 }
441
testEnumerate(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)442 static bool testEnumerate(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
443 {
444 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_OBJECT(args[1]))
445 return false;
446
447 uint32_t count;
448 NPIdentifier* identifiers;
449 if (browser->enumerate(obj->npp, NPVARIANT_TO_OBJECT(args[0]), &identifiers, &count)) {
450 NPObject* outArray = NPVARIANT_TO_OBJECT(args[1]);
451 NPIdentifier pushIdentifier = browser->getstringidentifier("push");
452
453 for (uint32_t i = 0; i < count; i++) {
454 NPUTF8* string = browser->utf8fromidentifier(identifiers[i]);
455
456 if (!string)
457 continue;
458
459 NPVariant args[1];
460 STRINGZ_TO_NPVARIANT(string, args[0]);
461 NPVariant browserResult;
462 browser->invoke(obj->npp, outArray, pushIdentifier, args, 1, &browserResult);
463 browser->releasevariantvalue(&browserResult);
464 browser->memfree(string);
465 }
466
467 browser->memfree(identifiers);
468 }
469
470 VOID_TO_NPVARIANT(*result);
471 return true;
472 }
473
testGetIntIdentifier(PluginObject *,const NPVariant * args,uint32_t argCount,NPVariant * result)474 static bool testGetIntIdentifier(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
475 {
476 if (argCount != 1 || !NPVARIANT_IS_DOUBLE(args[0]))
477 return false;
478
479 NPIdentifier identifier = browser->getintidentifier((int)NPVARIANT_TO_DOUBLE(args[0]));
480 INT32_TO_NPVARIANT((int32)(long long)identifier, *result);
481 return true;
482 }
483
testGetProperty(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)484 static bool testGetProperty(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
485 {
486 if (argCount == 0)
487 return false;
488
489 NPObject *object;
490 browser->getvalue(obj->npp, NPNVWindowNPObject, &object);
491
492 for (uint32_t i = 0; i < argCount; i++) {
493 assert(NPVARIANT_IS_STRING(args[i]));
494 NPUTF8* propertyString = createCStringFromNPVariant(&args[i]);
495 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
496 free(propertyString);
497
498 NPVariant variant;
499 bool retval = browser->getproperty(obj->npp, object, propertyIdentifier, &variant);
500 browser->releaseobject(object);
501
502 if (!retval)
503 break;
504
505 if (i + 1 < argCount) {
506 assert(NPVARIANT_IS_OBJECT(variant));
507 object = NPVARIANT_TO_OBJECT(variant);
508 } else {
509 *result = variant;
510 return true;
511 }
512 }
513
514 VOID_TO_NPVARIANT(*result);
515 return false;
516 }
517
testHasProperty(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)518 static bool testHasProperty(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
519 {
520 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
521 return false;
522
523 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
524 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
525 free(propertyString);
526
527 bool retval = browser->hasproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier);
528
529 BOOLEAN_TO_NPVARIANT(retval, *result);
530 return true;
531 }
532
testHasMethod(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)533 static bool testHasMethod(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
534 {
535 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
536 return false;
537
538 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
539 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
540 free(propertyString);
541
542 bool retval = browser->hasmethod(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier);
543
544 BOOLEAN_TO_NPVARIANT(retval, *result);
545 return true;
546 }
547
testEvaluate(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)548 static bool testEvaluate(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
549 {
550 if (argCount != 1 || !NPVARIANT_IS_STRING(args[0]))
551 return false;
552 NPObject* windowScriptObject;
553 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
554
555 NPString s = NPVARIANT_TO_STRING(args[0]);
556
557 bool retval = browser->evaluate(obj->npp, windowScriptObject, &s, result);
558 browser->releaseobject(windowScriptObject);
559 return retval;
560 }
561
testGetPropertyReturnValue(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)562 static bool testGetPropertyReturnValue(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
563 {
564 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
565 return false;
566
567 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
568 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
569 free(propertyString);
570
571 NPVariant variant;
572 bool retval = browser->getproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier, &variant);
573 if (retval)
574 browser->releasevariantvalue(&variant);
575
576 BOOLEAN_TO_NPVARIANT(retval, *result);
577 return true;
578 }
579
toCString(const NPString & string)580 static char* toCString(const NPString& string)
581 {
582 char* result = static_cast<char*>(malloc(string.UTF8Length + 1));
583 memcpy(result, string.UTF8Characters, string.UTF8Length);
584 result[string.UTF8Length] = '\0';
585
586 return result;
587 }
588
testPostURLFile(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)589 static bool testPostURLFile(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
590 {
591 if (argCount != 4 || !NPVARIANT_IS_STRING(args[0]) || !NPVARIANT_IS_STRING(args[1]) || !NPVARIANT_IS_STRING(args[2]) || !NPVARIANT_IS_STRING(args[3]))
592 return false;
593
594 NPString urlString = NPVARIANT_TO_STRING(args[0]);
595 char* url = toCString(urlString);
596
597 NPString targetString = NPVARIANT_TO_STRING(args[1]);
598 char* target = toCString(targetString);
599
600 NPString pathString = NPVARIANT_TO_STRING(args[2]);
601 char* path = toCString(pathString);
602
603 NPString contentsString = NPVARIANT_TO_STRING(args[3]);
604
605 FILE* tempFile = fopen(path, "w");
606 if (!tempFile)
607 return false;
608
609 fwrite(contentsString.UTF8Characters, contentsString.UTF8Length, 1, tempFile);
610 fclose(tempFile);
611
612 NPError error = browser->posturl(obj->npp, url, target, pathString.UTF8Length, path, TRUE);
613
614 free(path);
615 free(target);
616 free(url);
617
618 BOOLEAN_TO_NPVARIANT(error == NPERR_NO_ERROR, *result);
619 return true;
620 }
621
testConstruct(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)622 static bool testConstruct(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
623 {
624 if (!argCount || !NPVARIANT_IS_OBJECT(args[0]))
625 return false;
626
627 return browser->construct(obj->npp, NPVARIANT_TO_OBJECT(args[0]), args + 1, argCount - 1, result);
628 }
629
pluginInvoke(NPObject * header,NPIdentifier name,const NPVariant * args,uint32_t argCount,NPVariant * result)630 static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)
631 {
632 PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
633 if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD])
634 return testCallback(plugin, args, argCount, result);
635 else if (name == pluginMethodIdentifiers[ID_TEST_GETURL])
636 return getURL(plugin, args, argCount, result);
637 else if (name == pluginMethodIdentifiers[ID_REMOVE_DEFAULT_METHOD])
638 return removeDefaultMethod(plugin, args, argCount, result);
639 else if (name == pluginMethodIdentifiers[ID_TEST_DOM_ACCESS])
640 return testDOMAccess(plugin, args, argCount, result);
641 else if (name == pluginMethodIdentifiers[ID_TEST_GET_URL_NOTIFY])
642 return getURLNotify(plugin, args, argCount, result);
643 else if (name == pluginMethodIdentifiers[ID_TEST_INVOKE_DEFAULT])
644 return testInvokeDefault(plugin, args, argCount, result);
645 else if (name == pluginMethodIdentifiers[ID_TEST_ENUMERATE])
646 return testEnumerate(plugin, args, argCount, result);
647 else if (name == pluginMethodIdentifiers[ID_DESTROY_STREAM])
648 return destroyStream(plugin, args, argCount, result);
649 else if (name == pluginMethodIdentifiers[ID_TEST_GETINTIDENTIFIER])
650 return testGetIntIdentifier(plugin, args, argCount, result);
651 else if (name == pluginMethodIdentifiers[ID_TEST_EVALUATE])
652 return testEvaluate(plugin, args, argCount, result);
653 else if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY])
654 return testGetProperty(plugin, args, argCount, result);
655 else if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY_RETURN_VALUE])
656 return testGetPropertyReturnValue(plugin, args, argCount, result);
657 else if (name == pluginMethodIdentifiers[ID_TEST_HAS_PROPERTY])
658 return testHasProperty(plugin, args, argCount, result);
659 else if (name == pluginMethodIdentifiers[ID_TEST_HAS_METHOD])
660 return testHasMethod(plugin, args, argCount, result);
661 else if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_STRING])
662 return testIdentifierToString(plugin, args, argCount, result);
663 else if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_INT])
664 return testIdentifierToInt(plugin, args, argCount, result);
665 else if (name == pluginMethodIdentifiers[ID_TEST_POSTURL_FILE])
666 return testPostURLFile(plugin, args, argCount, result);
667 else if (name == pluginMethodIdentifiers[ID_TEST_CONSTRUCT])
668 return testConstruct(plugin, args, argCount, result);
669 else if (name == pluginMethodIdentifiers[ID_TEST_THROW_EXCEPTION_METHOD]) {
670 browser->setexception(header, "plugin object testThrowException SUCCESS");
671 return true;
672 } else if (name == pluginMethodIdentifiers[ID_DESTROY_NULL_STREAM])
673 return destroyNullStream(plugin, args, argCount, result);
674
675 return false;
676 }
677
pluginInvokeDefault(NPObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)678 static bool pluginInvokeDefault(NPObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
679 {
680 INT32_TO_NPVARIANT(1, *result);
681 return true;
682 }
683
pluginInvalidate(NPObject * header)684 static void pluginInvalidate(NPObject* header)
685 {
686 PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
687 plugin->testObject = 0;
688 }
689
pluginAllocate(NPP npp,NPClass * theClass)690 static NPObject *pluginAllocate(NPP npp, NPClass *theClass)
691 {
692 PluginObject* newInstance = (PluginObject*)malloc(sizeof(PluginObject));
693
694 if (!identifiersInitialized) {
695 identifiersInitialized = true;
696 initializeIdentifiers();
697 }
698
699 newInstance->npp = npp;
700 newInstance->testObject = browser->createobject(npp, getTestClass());
701 newInstance->eventLogging = FALSE;
702 newInstance->onStreamLoad = 0;
703 newInstance->onStreamDestroy = 0;
704 newInstance->onURLNotify = 0;
705 newInstance->logDestroy = FALSE;
706 newInstance->logSetWindow = FALSE;
707 newInstance->returnErrorFromNewStream = FALSE;
708 newInstance->stream = 0;
709
710 newInstance->firstUrl = NULL;
711 newInstance->firstHeaders = NULL;
712 newInstance->lastUrl = NULL;
713 newInstance->lastHeaders = NULL;
714
715 return (NPObject*)newInstance;
716 }
717
pluginDeallocate(NPObject * header)718 static void pluginDeallocate(NPObject* header)
719 {
720 PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
721 if (plugin->testObject)
722 browser->releaseobject(plugin->testObject);
723
724 free(plugin->firstUrl);
725 free(plugin->firstHeaders);
726 free(plugin->lastUrl);
727 free(plugin->lastHeaders);
728 free(plugin);
729 }
730
handleCallback(PluginObject * object,const char * url,NPReason reason,void * notifyData)731 void handleCallback(PluginObject* object, const char *url, NPReason reason, void *notifyData)
732 {
733 assert(object);
734
735 NPVariant args[2];
736
737 NPObject *windowScriptObject;
738 browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject);
739
740 NPIdentifier callbackIdentifier = notifyData;
741
742 INT32_TO_NPVARIANT(reason, args[0]);
743
744 char *strHdr = NULL;
745 if (object->firstUrl && object->firstHeaders && object->lastUrl && object->lastHeaders) {
746 // Format expected by JavaScript validator: four fields separated by \n\n:
747 // First URL; first header block; last URL; last header block.
748 // Note that header blocks already end with \n due to how NPStream::headers works.
749 int len = strlen(object->firstUrl) + 2
750 + strlen(object->firstHeaders) + 1
751 + strlen(object->lastUrl) + 2
752 + strlen(object->lastHeaders) + 1;
753 strHdr = (char*)malloc(len + 1);
754 snprintf(strHdr, len + 1, "%s\n\n%s\n%s\n\n%s\n",
755 object->firstUrl, object->firstHeaders, object->lastUrl, object->lastHeaders);
756 STRINGN_TO_NPVARIANT(strHdr, len, args[1]);
757 } else
758 NULL_TO_NPVARIANT(args[1]);
759
760 NPVariant browserResult;
761 browser->invoke(object->npp, windowScriptObject, callbackIdentifier, args, 2, &browserResult);
762 browser->releasevariantvalue(&browserResult);
763
764 free(strHdr);
765 }
766
notifyStream(PluginObject * object,const char * url,const char * headers)767 void notifyStream(PluginObject* object, const char *url, const char *headers)
768 {
769 if (object->firstUrl == NULL) {
770 if (url)
771 object->firstUrl = strdup(url);
772 if (headers)
773 object->firstHeaders = strdup(headers);
774 } else {
775 free(object->lastUrl);
776 free(object->lastHeaders);
777 object->lastUrl = (url ? strdup(url) : NULL);
778 object->lastHeaders = (headers ? strdup(headers) : NULL);
779 }
780 }
781
testNPRuntime(NPP npp)782 void testNPRuntime(NPP npp)
783 {
784 NPObject* windowScriptObject;
785 browser->getvalue(npp, NPNVWindowNPObject, &windowScriptObject);
786
787 // Invoke
788 NPIdentifier testNPInvoke = browser->getstringidentifier("testNPInvoke");
789 NPVariant args[7];
790
791 VOID_TO_NPVARIANT(args[0]);
792 NULL_TO_NPVARIANT(args[1]);
793 BOOLEAN_TO_NPVARIANT(true, args[2]);
794 INT32_TO_NPVARIANT(242, args[3]);
795 DOUBLE_TO_NPVARIANT(242.242, args[4]);
796 STRINGZ_TO_NPVARIANT("Hello, World", args[5]);
797 OBJECT_TO_NPVARIANT(windowScriptObject, args[6]);
798
799 NPVariant result;
800 if (browser->invoke(npp, windowScriptObject, testNPInvoke, args, 7, &result))
801 browser->releasevariantvalue(&result);
802
803 browser->releaseobject(windowScriptObject);
804 }
805