• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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