• 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  * Copyright (C) 2010 Collabora Ltd.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "PluginObject.h"
29 
30 #include "PluginTest.h"
31 #include "TestObject.h"
32 #include <assert.h>
33 #include <stdarg.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 
38 // Helper function which takes in the plugin window object for logging to the console object.
pluginLogWithWindowObject(NPObject * windowObject,NPP instance,const char * message)39 static void pluginLogWithWindowObject(NPObject* windowObject, NPP instance, const char* message)
40 {
41     NPVariant consoleVariant;
42     if (!browser->getproperty(instance, windowObject, browser->getstringidentifier("console"), &consoleVariant)) {
43         fprintf(stderr, "Failed to retrieve console object while logging: %s\n", message);
44         return;
45     }
46 
47     NPObject* consoleObject = NPVARIANT_TO_OBJECT(consoleVariant);
48 
49     NPVariant messageVariant;
50     STRINGZ_TO_NPVARIANT(message, messageVariant);
51 
52     NPVariant result;
53     if (!browser->invoke(instance, consoleObject, browser->getstringidentifier("log"), &messageVariant, 1, &result)) {
54         fprintf(stderr, "Failed to invoke console.log while logging: %s\n", message);
55         browser->releaseobject(consoleObject);
56         return;
57     }
58 
59     browser->releasevariantvalue(&result);
60     browser->releaseobject(consoleObject);
61 }
62 
63 // Helper function which takes in the plugin window object for logging to the console object. This function supports variable
64 // arguments.
pluginLogWithWindowObjectVariableArgs(NPObject * windowObject,NPP instance,const char * format,...)65 static void pluginLogWithWindowObjectVariableArgs(NPObject* windowObject, NPP instance, const char* format, ...)
66 {
67     va_list args;
68     va_start(args, format);
69     char message[2048] = "PLUGIN: ";
70     vsprintf(message + strlen(message), format, args);
71     va_end(args);
72 
73     pluginLogWithWindowObject(windowObject, instance, message);
74 }
75 
pluginLogWithArguments(NPP instance,const char * format,va_list args)76 void pluginLogWithArguments(NPP instance, const char* format, va_list args)
77 {
78     char message[2048] = "PLUGIN: ";
79     vsprintf(message + strlen(message), format, args);
80 
81     NPObject* windowObject = 0;
82     NPError error = browser->getvalue(instance, NPNVWindowNPObject, &windowObject);
83     if (error != NPERR_NO_ERROR) {
84         fprintf(stderr, "Failed to retrieve window object while logging: %s\n", message);
85         return;
86     }
87 
88     pluginLogWithWindowObject(windowObject, instance, message);
89     browser->releaseobject(windowObject);
90 }
91 
92 // Helper function to log to the console object.
pluginLog(NPP instance,const char * format,...)93 void pluginLog(NPP instance, const char* format, ...)
94 {
95     va_list args;
96     va_start(args, format);
97     pluginLogWithArguments(instance, format, args);
98     va_end(args);
99 }
100 
101 static void pluginInvalidate(NPObject*);
102 static bool pluginHasProperty(NPObject*, NPIdentifier name);
103 static bool pluginHasMethod(NPObject*, NPIdentifier name);
104 static bool pluginGetProperty(NPObject*, NPIdentifier name, NPVariant*);
105 static bool pluginSetProperty(NPObject*, NPIdentifier name, const NPVariant*);
106 static bool pluginInvoke(NPObject*, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result);
107 static NPObject* pluginAllocate(NPP npp, NPClass*);
108 static void pluginDeallocate(NPObject*);
109 
110 NPNetscapeFuncs* browser;
111 NPPluginFuncs* pluginFunctions;
112 
113 static NPClass pluginClass = {
114     NP_CLASS_STRUCT_VERSION,
115     pluginAllocate,
116     pluginDeallocate,
117     pluginInvalidate,
118     pluginHasMethod,
119     pluginInvoke,
120     0, // NPClass::invokeDefault,
121     pluginHasProperty,
122     pluginGetProperty,
123     pluginSetProperty,
124     0, // NPClass::removeProperty
125     0, // NPClass::enumerate
126     0, // NPClass::construct
127 };
128 
getPluginClass(void)129 NPClass* getPluginClass(void)
130 {
131     return &pluginClass;
132 }
133 
134 static bool identifiersInitialized = false;
135 
136 enum {
137     ID_PROPERTY_PROPERTY = 0,
138     ID_PROPERTY_EVENT_LOGGING,
139     ID_PROPERTY_HAS_STREAM,
140     ID_PROPERTY_TEST_OBJECT,
141     ID_PROPERTY_LOG_DESTROY,
142     ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM,
143     ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE,
144     ID_PROPERTY_PRIVATE_BROWSING_ENABLED,
145     ID_PROPERTY_CACHED_PRIVATE_BROWSING_ENABLED,
146     ID_PROPERTY_THROW_EXCEPTION_PROPERTY,
147     ID_LAST_SET_WINDOW_ARGUMENTS,
148     ID_PROPERTY_WINDOWED_PLUGIN,
149     ID_PROPERTY_TEST_OBJECT_COUNT,
150     NUM_PROPERTY_IDENTIFIERS
151 };
152 
153 static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
154 static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
155     "property",
156     "eventLoggingEnabled",
157     "hasStream",
158     "testObject",
159     "logDestroy",
160     "returnErrorFromNewStream",
161     "returnNegativeOneFromWrite",
162     "privateBrowsingEnabled",
163     "cachedPrivateBrowsingEnabled",
164     "testThrowExceptionProperty",
165     "lastSetWindowArguments",
166     "windowedPlugin",
167     "testObjectCount",
168 };
169 
170 enum {
171     ID_TEST_CALLBACK_METHOD = 0,
172     ID_TEST_CALLBACK_METHOD_RETURN,
173     ID_TEST_GETURL,
174     ID_TEST_DOM_ACCESS,
175     ID_TEST_GET_URL_NOTIFY,
176     ID_TEST_INVOKE_DEFAULT,
177     ID_DESTROY_STREAM,
178     ID_TEST_ENUMERATE,
179     ID_TEST_GETINTIDENTIFIER,
180     ID_TEST_GET_PROPERTY,
181     ID_TEST_HAS_PROPERTY,
182     ID_TEST_HAS_METHOD,
183     ID_TEST_EVALUATE,
184     ID_TEST_GET_PROPERTY_RETURN_VALUE,
185     ID_TEST_IDENTIFIER_TO_STRING,
186     ID_TEST_IDENTIFIER_TO_INT,
187     ID_TEST_PASS_TEST_OBJECT,
188     ID_TEST_POSTURL_FILE,
189     ID_TEST_CONSTRUCT,
190     ID_TEST_THROW_EXCEPTION_METHOD,
191     ID_TEST_FAIL_METHOD,
192     ID_TEST_CLONE_OBJECT,
193     ID_TEST_SCRIPT_OBJECT_INVOKE,
194     ID_TEST_CREATE_TEST_OBJECT,
195     ID_DESTROY_NULL_STREAM,
196     ID_TEST_RELOAD_PLUGINS_NO_PAGES,
197     ID_TEST_RELOAD_PLUGINS_AND_PAGES,
198     ID_TEST_GET_BROWSER_PROPERTY,
199     ID_TEST_SET_BROWSER_PROPERTY,
200     ID_REMEMBER,
201     ID_GET_REMEMBERED_OBJECT,
202     ID_GET_AND_FORGET_REMEMBERED_OBJECT,
203     ID_REF_COUNT,
204     ID_SET_STATUS,
205     ID_RESIZE_TO,
206     ID_NORMALIZE,
207     ID_INVALIDATE_RECT,
208     NUM_METHOD_IDENTIFIERS
209 };
210 
211 static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
212 static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
213     "testCallback",
214     "testCallbackReturn",
215     "getURL",
216     "testDOMAccess",
217     "getURLNotify",
218     "testInvokeDefault",
219     "destroyStream",
220     "testEnumerate",
221     "testGetIntIdentifier",
222     "testGetProperty",
223     "testHasProperty",
224     "testHasMethod",
225     "testEvaluate",
226     "testGetPropertyReturnValue",
227     "testIdentifierToString",
228     "testIdentifierToInt",
229     "testPassTestObject",
230     "testPostURLFile",
231     "testConstruct",
232     "testThrowException",
233     "testFail",
234     "testCloneObject",
235     "testScriptObjectInvoke",
236     "testCreateTestObject",
237     "destroyNullStream",
238     "reloadPluginsNoPages",
239     "reloadPluginsAndPages",
240     "testGetBrowserProperty",
241     "testSetBrowserProperty",
242     "remember",
243     "getRememberedObject",
244     "getAndForgetRememberedObject",
245     "refCount",
246     "setStatus",
247     "resizeTo",
248     "normalize",
249     "invalidateRect"
250 };
251 
createCStringFromNPVariant(const NPVariant * variant)252 static NPUTF8* createCStringFromNPVariant(const NPVariant* variant)
253 {
254     size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length;
255     NPUTF8* result = (NPUTF8*)malloc(length + 1);
256     memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length);
257     result[length] = '\0';
258     return result;
259 }
260 
initializeIdentifiers(void)261 static void initializeIdentifiers(void)
262 {
263     browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, pluginPropertyIdentifiers);
264     browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, pluginMethodIdentifiers);
265 }
266 
pluginHasProperty(NPObject * obj,NPIdentifier name)267 static bool pluginHasProperty(NPObject *obj, NPIdentifier name)
268 {
269     for (int i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++)
270         if (name == pluginPropertyIdentifiers[i])
271             return true;
272     return false;
273 }
274 
pluginHasMethod(NPObject * obj,NPIdentifier name)275 static bool pluginHasMethod(NPObject *obj, NPIdentifier name)
276 {
277     for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++)
278         if (name == pluginMethodIdentifiers[i])
279             return true;
280     return false;
281 }
282 
pluginGetProperty(NPObject * obj,NPIdentifier name,NPVariant * result)283 static bool pluginGetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)
284 {
285     PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
286     if (name == pluginPropertyIdentifiers[ID_PROPERTY_PROPERTY]) {
287         static const char* originalString = "property";
288         char* buf = static_cast<char*>(browser->memalloc(strlen(originalString) + 1));
289         strcpy(buf, originalString);
290         STRINGZ_TO_NPVARIANT(buf, *result);
291         return true;
292     }
293     if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
294         BOOLEAN_TO_NPVARIANT(plugin->eventLogging, *result);
295         return true;
296     }
297     if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
298         BOOLEAN_TO_NPVARIANT(plugin->logDestroy, *result);
299         return true;
300     }
301     if (name == pluginPropertyIdentifiers[ID_PROPERTY_HAS_STREAM]) {
302         BOOLEAN_TO_NPVARIANT(plugin->stream, *result);
303         return true;
304     }
305     if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT]) {
306         NPObject* testObject = plugin->testObject;
307         browser->retainobject(testObject);
308         OBJECT_TO_NPVARIANT(testObject, *result);
309         return true;
310     }
311     if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) {
312         BOOLEAN_TO_NPVARIANT(plugin->returnErrorFromNewStream, *result);
313         return true;
314     }
315     if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE]) {
316         BOOLEAN_TO_NPVARIANT(plugin->returnNegativeOneFromWrite, *result);
317         return true;
318     }
319     if (name == pluginPropertyIdentifiers[ID_PROPERTY_PRIVATE_BROWSING_ENABLED]) {
320         NPBool privateBrowsingEnabled = FALSE;
321         browser->getvalue(plugin->npp, NPNVprivateModeBool, &privateBrowsingEnabled);
322         BOOLEAN_TO_NPVARIANT(privateBrowsingEnabled, *result);
323         return true;
324     }
325     if (name == pluginPropertyIdentifiers[ID_PROPERTY_CACHED_PRIVATE_BROWSING_ENABLED]) {
326         BOOLEAN_TO_NPVARIANT(plugin->cachedPrivateBrowsingMode, *result);
327         return true;
328     }
329     if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PROPERTY]) {
330         browser->setexception(obj, "plugin object testThrowExceptionProperty SUCCESS");
331         return true;
332     }
333     if (name == pluginPropertyIdentifiers[ID_LAST_SET_WINDOW_ARGUMENTS]) {
334         char* buf = static_cast<char*>(browser->memalloc(256));
335         snprintf(buf, 256, "x: %d, y: %d, width: %u, height: %u, clipRect: (%u, %u, %u, %u)", (int)plugin->lastWindow.x, (int)plugin->lastWindow.y, (unsigned)plugin->lastWindow.width, (unsigned)plugin->lastWindow.height,
336             plugin->lastWindow.clipRect.left, plugin->lastWindow.clipRect.top, plugin->lastWindow.clipRect.right - plugin->lastWindow.clipRect.left, plugin->lastWindow.clipRect.bottom - plugin->lastWindow.clipRect.top);
337 
338         STRINGZ_TO_NPVARIANT(buf, *result);
339         return true;
340     }
341     if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT_COUNT]) {
342         INT32_TO_NPVARIANT(getTestObjectCount(), *result);
343         return true;
344     }
345 
346     return false;
347 }
348 
pluginSetProperty(NPObject * obj,NPIdentifier name,const NPVariant * variant)349 static bool pluginSetProperty(NPObject* obj, NPIdentifier name, const NPVariant* variant)
350 {
351     PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
352     if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
353         plugin->eventLogging = NPVARIANT_TO_BOOLEAN(*variant);
354         return true;
355     }
356     if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
357         plugin->logDestroy = NPVARIANT_TO_BOOLEAN(*variant);
358         return true;
359     }
360     if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) {
361         plugin->returnErrorFromNewStream = NPVARIANT_TO_BOOLEAN(*variant);
362         return true;
363     }
364     if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE]) {
365         plugin->returnNegativeOneFromWrite = NPVARIANT_TO_BOOLEAN(*variant);
366         return true;
367     }
368     if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PROPERTY]) {
369         browser->setexception(obj, "plugin object testThrowExceptionProperty SUCCESS");
370         return true;
371     }
372     if (name == pluginPropertyIdentifiers[ID_PROPERTY_WINDOWED_PLUGIN]) {
373         browser->setvalue(plugin->npp, NPPVpluginWindowBool, (void *)NPVARIANT_TO_BOOLEAN(*variant));
374         return true;
375     }
376 
377     return false;
378 }
379 
testDOMAccess(PluginObject * obj,const NPVariant *,uint32_t,NPVariant * result)380 static bool testDOMAccess(PluginObject* obj, const NPVariant*, uint32_t, NPVariant* result)
381 {
382     // Get plug-in's DOM element
383     NPObject* elementObject;
384     if (browser->getvalue(obj->npp, NPNVPluginElementNPObject, &elementObject) == NPERR_NO_ERROR) {
385         // Get style
386         NPVariant styleVariant;
387         NPIdentifier styleIdentifier = browser->getstringidentifier("style");
388         if (browser->getproperty(obj->npp, elementObject, styleIdentifier, &styleVariant) && NPVARIANT_IS_OBJECT(styleVariant)) {
389             // Set style.border
390             NPIdentifier borderIdentifier = browser->getstringidentifier("border");
391             NPVariant borderVariant;
392             STRINGZ_TO_NPVARIANT("3px solid red", borderVariant);
393             browser->setproperty(obj->npp, NPVARIANT_TO_OBJECT(styleVariant), borderIdentifier, &borderVariant);
394             browser->releasevariantvalue(&styleVariant);
395         }
396 
397         browser->releaseobject(elementObject);
398     }
399     VOID_TO_NPVARIANT(*result);
400     return true;
401 }
402 
stringVariantToIdentifier(NPVariant variant)403 static NPIdentifier stringVariantToIdentifier(NPVariant variant)
404 {
405     assert(NPVARIANT_IS_STRING(variant));
406     NPUTF8* utf8String = createCStringFromNPVariant(&variant);
407     NPIdentifier identifier = browser->getstringidentifier(utf8String);
408     free(utf8String);
409     return identifier;
410 }
411 
int32VariantToIdentifier(NPVariant variant)412 static NPIdentifier int32VariantToIdentifier(NPVariant variant)
413 {
414     assert(NPVARIANT_IS_INT32(variant));
415     int32_t integer = NPVARIANT_TO_INT32(variant);
416     return browser->getintidentifier(integer);
417 }
418 
doubleVariantToIdentifier(NPVariant variant)419 static NPIdentifier doubleVariantToIdentifier(NPVariant variant)
420 {
421     assert(NPVARIANT_IS_DOUBLE(variant));
422     double value = NPVARIANT_TO_DOUBLE(variant);
423     // Sadly there is no "getdoubleidentifier"
424     int32_t integer = static_cast<int32_t>(value);
425     return browser->getintidentifier(integer);
426 }
427 
variantToIdentifier(NPVariant variant)428 static NPIdentifier variantToIdentifier(NPVariant variant)
429 {
430     if (NPVARIANT_IS_STRING(variant))
431         return stringVariantToIdentifier(variant);
432     if (NPVARIANT_IS_INT32(variant))
433         return int32VariantToIdentifier(variant);
434     if (NPVARIANT_IS_DOUBLE(variant))
435         return doubleVariantToIdentifier(variant);
436     return 0;
437 }
438 
testIdentifierToString(PluginObject *,const NPVariant * args,uint32_t argCount,NPVariant * result)439 static bool testIdentifierToString(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
440 {
441     if (argCount != 1)
442         return true;
443     NPIdentifier identifier = variantToIdentifier(args[0]);
444     if (!identifier)
445         return true;
446     NPUTF8* utf8String = browser->utf8fromidentifier(identifier);
447     if (!utf8String)
448         return true;
449     STRINGZ_TO_NPVARIANT(utf8String, *result);
450     return true;
451 }
452 
testIdentifierToInt(PluginObject *,const NPVariant * args,uint32_t argCount,NPVariant * result)453 static bool testIdentifierToInt(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
454 {
455     if (argCount != 1)
456         return false;
457     NPIdentifier identifier = variantToIdentifier(args[0]);
458     if (!identifier)
459         return false;
460     int32_t integer = browser->intfromidentifier(identifier);
461     INT32_TO_NPVARIANT(integer, *result);
462     return true;
463 }
464 
testPassTestObject(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)465 static bool testPassTestObject(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
466 {
467     if (argCount != 2 || !NPVARIANT_IS_STRING(args[0]))
468         return false;
469 
470     NPObject* windowScriptObject;
471     browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
472 
473     NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
474     NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
475     free(callbackString);
476 
477     NPVariant browserResult;
478     browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, &args[1], 1, &browserResult);
479     browser->releasevariantvalue(&browserResult);
480 
481     VOID_TO_NPVARIANT(*result);
482     return true;
483 }
484 
testCallback(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)485 static bool testCallback(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
486 {
487     if (!argCount || !NPVARIANT_IS_STRING(args[0]))
488         return false;
489 
490     NPObject* windowScriptObject;
491     browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
492 
493     NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
494     NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
495     free(callbackString);
496 
497     NPVariant browserResult;
498     if (browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, 0, 0, &browserResult))
499         browser->releasevariantvalue(&browserResult);
500 
501     browser->releaseobject(windowScriptObject);
502 
503     VOID_TO_NPVARIANT(*result);
504     return true;
505 }
506 
testCallbackReturn(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)507 static bool testCallbackReturn(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
508 {
509     if (argCount != 1 || !NPVARIANT_IS_STRING(args[0]))
510         return false;
511 
512     NPObject* windowScriptObject;
513     browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
514 
515     NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
516     NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
517     free(callbackString);
518 
519     NPVariant callbackArgs[1];
520     OBJECT_TO_NPVARIANT(windowScriptObject, callbackArgs[0]);
521 
522     NPVariant browserResult;
523     browser->invoke(obj->npp, windowScriptObject, callbackIdentifier,
524                     callbackArgs, 1, &browserResult);
525 
526     if (NPVARIANT_IS_OBJECT(browserResult))
527         OBJECT_TO_NPVARIANT(NPVARIANT_TO_OBJECT(browserResult), *result);
528     else {
529         browser->releasevariantvalue(&browserResult);
530         VOID_TO_NPVARIANT(*result);
531     }
532 
533     return true;
534 }
535 
getURL(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)536 static bool getURL(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
537 {
538     if (argCount == 2 && NPVARIANT_IS_STRING(args[0]) && NPVARIANT_IS_STRING(args[1])) {
539         NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
540         NPUTF8* targetString = createCStringFromNPVariant(&args[1]);
541         NPError npErr = browser->geturl(obj->npp, urlString, targetString);
542         free(urlString);
543         free(targetString);
544 
545         INT32_TO_NPVARIANT(npErr, *result);
546         return true;
547     }
548     if (argCount == 1 && NPVARIANT_IS_STRING(args[0])) {
549         NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
550         NPError npErr = browser->geturl(obj->npp, urlString, 0);
551         free(urlString);
552 
553         INT32_TO_NPVARIANT(npErr, *result);
554         return true;
555     }
556     return false;
557 }
558 
getURLNotify(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)559 static bool getURLNotify(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
560 {
561     if (argCount != 3 || !NPVARIANT_IS_STRING(args[0])
562         || (!NPVARIANT_IS_STRING(args[1]) && !NPVARIANT_IS_NULL(args[1]))
563         || !NPVARIANT_IS_STRING(args[2]))
564         return false;
565 
566     NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
567     NPUTF8* targetString = (NPVARIANT_IS_STRING(args[1]) ? createCStringFromNPVariant(&args[1]) : 0);
568     NPUTF8* callbackString = createCStringFromNPVariant(&args[2]);
569 
570     NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
571     browser->geturlnotify(obj->npp, urlString, targetString, callbackIdentifier);
572 
573     free(urlString);
574     free(targetString);
575     free(callbackString);
576 
577     VOID_TO_NPVARIANT(*result);
578     return true;
579 }
580 
testInvokeDefault(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)581 static bool testInvokeDefault(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
582 {
583     if (!NPVARIANT_IS_OBJECT(args[0]))
584         return false;
585 
586     NPObject* callback = NPVARIANT_TO_OBJECT(args[0]);
587 
588     NPVariant invokeArgs[1];
589     NPVariant browserResult;
590 
591     STRINGZ_TO_NPVARIANT("test", invokeArgs[0]);
592     bool retval = browser->invokeDefault(obj->npp, callback, invokeArgs, 1, &browserResult);
593 
594     if (retval)
595         browser->releasevariantvalue(&browserResult);
596 
597     BOOLEAN_TO_NPVARIANT(retval, *result);
598     return true;
599 }
600 
destroyStream(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)601 static bool destroyStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
602 {
603     NPError npError = browser->destroystream(obj->npp, obj->stream, NPRES_USER_BREAK);
604     INT32_TO_NPVARIANT(npError, *result);
605     return true;
606 }
607 
destroyNullStream(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)608 static bool destroyNullStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
609 {
610     NPError npError = browser->destroystream(obj->npp, 0, NPRES_USER_BREAK);
611     INT32_TO_NPVARIANT(npError, *result);
612     return true;
613 }
614 
testEnumerate(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)615 static bool testEnumerate(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
616 {
617     if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_OBJECT(args[1]))
618         return false;
619 
620     uint32_t count;
621     NPIdentifier* identifiers;
622     if (browser->enumerate(obj->npp, NPVARIANT_TO_OBJECT(args[0]), &identifiers, &count)) {
623         NPObject* outArray = NPVARIANT_TO_OBJECT(args[1]);
624         NPIdentifier pushIdentifier = browser->getstringidentifier("push");
625 
626         for (uint32_t i = 0; i < count; i++) {
627             NPUTF8* string = browser->utf8fromidentifier(identifiers[i]);
628 
629             if (!string)
630                 continue;
631 
632             NPVariant args[1];
633             STRINGZ_TO_NPVARIANT(string, args[0]);
634             NPVariant browserResult;
635             if (browser->invoke(obj->npp, outArray, pushIdentifier, args, 1, &browserResult))
636                 browser->releasevariantvalue(&browserResult);
637             browser->memfree(string);
638         }
639 
640         browser->memfree(identifiers);
641     }
642 
643     VOID_TO_NPVARIANT(*result);
644     return true;
645 }
646 
testGetIntIdentifier(PluginObject *,const NPVariant * args,uint32_t argCount,NPVariant * result)647 static bool testGetIntIdentifier(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
648 {
649     if (argCount != 1 || !NPVARIANT_IS_DOUBLE(args[0]))
650         return false;
651 
652     NPIdentifier identifier = browser->getintidentifier((int)NPVARIANT_TO_DOUBLE(args[0]));
653     INT32_TO_NPVARIANT((int32_t)(long long)identifier, *result);
654     return true;
655 }
656 
testGetProperty(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)657 static bool testGetProperty(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
658 {
659     if (!argCount)
660         return false;
661 
662     NPObject* object;
663     browser->getvalue(obj->npp, NPNVWindowNPObject, &object);
664 
665     for (uint32_t i = 0; i < argCount; i++) {
666         assert(NPVARIANT_IS_STRING(args[i]));
667         NPUTF8* propertyString = createCStringFromNPVariant(&args[i]);
668         NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
669         free(propertyString);
670 
671         NPVariant variant;
672         bool retval = browser->getproperty(obj->npp, object, propertyIdentifier, &variant);
673         browser->releaseobject(object);
674 
675         if (!retval)
676             break;
677 
678         if (i + 1 < argCount) {
679             assert(NPVARIANT_IS_OBJECT(variant));
680             object = NPVARIANT_TO_OBJECT(variant);
681         } else {
682             *result = variant;
683             return true;
684         }
685     }
686 
687     VOID_TO_NPVARIANT(*result);
688     return false;
689 }
690 
testHasProperty(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)691 static bool testHasProperty(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
692 {
693     if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
694         return false;
695 
696     NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
697     NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
698     free(propertyString);
699 
700     bool retval = browser->hasproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier);
701 
702     BOOLEAN_TO_NPVARIANT(retval, *result);
703     return true;
704 }
705 
testHasMethod(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)706 static bool testHasMethod(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
707 {
708     if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
709         return false;
710 
711     NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
712     NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
713     free(propertyString);
714 
715     bool retval = browser->hasmethod(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier);
716 
717     BOOLEAN_TO_NPVARIANT(retval, *result);
718     return true;
719 }
720 
testEvaluate(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)721 static bool testEvaluate(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
722 {
723     if (argCount != 1 || !NPVARIANT_IS_STRING(args[0]))
724         return false;
725     NPObject* windowScriptObject;
726     browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
727 
728     NPString s = NPVARIANT_TO_STRING(args[0]);
729 
730     bool retval = browser->evaluate(obj->npp, windowScriptObject, &s, result);
731     browser->releaseobject(windowScriptObject);
732     return retval;
733 }
734 
testGetPropertyReturnValue(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)735 static bool testGetPropertyReturnValue(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
736 {
737     if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
738         return false;
739 
740     NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
741     NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
742     free(propertyString);
743 
744     NPVariant variant;
745     bool retval = browser->getproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier, &variant);
746     if (retval)
747         browser->releasevariantvalue(&variant);
748 
749     BOOLEAN_TO_NPVARIANT(retval, *result);
750     return true;
751 }
752 
toCString(const NPString & string)753 static char* toCString(const NPString& string)
754 {
755     char* result = static_cast<char*>(malloc(string.UTF8Length + 1));
756     memcpy(result, string.UTF8Characters, string.UTF8Length);
757     result[string.UTF8Length] = '\0';
758 
759     return result;
760 }
761 
testPostURLFile(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)762 static bool testPostURLFile(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
763 {
764     if (argCount != 4 || !NPVARIANT_IS_STRING(args[0]) || !NPVARIANT_IS_STRING(args[1]) || !NPVARIANT_IS_STRING(args[2]) || !NPVARIANT_IS_STRING(args[3]))
765         return false;
766 
767     NPString urlString = NPVARIANT_TO_STRING(args[0]);
768     char* url = toCString(urlString);
769 
770     NPString targetString = NPVARIANT_TO_STRING(args[1]);
771     char* target = toCString(targetString);
772 
773     NPString pathString = NPVARIANT_TO_STRING(args[2]);
774     char* path = toCString(pathString);
775 
776     NPString contentsString = NPVARIANT_TO_STRING(args[3]);
777 
778     FILE* tempFile = fopen(path, "w");
779     if (!tempFile)
780         return false;
781 
782     if (!fwrite(contentsString.UTF8Characters, contentsString.UTF8Length, 1, tempFile))
783         return false;
784 
785     fclose(tempFile);
786 
787     NPError error = browser->posturl(obj->npp, url, target, pathString.UTF8Length, path, TRUE);
788 
789     free(path);
790     free(target);
791     free(url);
792 
793     BOOLEAN_TO_NPVARIANT(error == NPERR_NO_ERROR, *result);
794     return true;
795 }
796 
testConstruct(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)797 static bool testConstruct(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
798 {
799     if (!argCount || !NPVARIANT_IS_OBJECT(args[0]))
800         return false;
801 
802     return browser->construct(obj->npp, NPVARIANT_TO_OBJECT(args[0]), args + 1, argCount - 1, result);
803 }
804 
805 // Invoke a script callback to get a script NPObject. Then call a method on the
806 // script NPObject passing it a freshly created NPObject.
testScriptObjectInvoke(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)807 static bool testScriptObjectInvoke(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
808 {
809     if (argCount != 2 || !NPVARIANT_IS_STRING(args[0]) || !NPVARIANT_IS_STRING(args[1]))
810         return false;
811     NPObject* windowScriptObject;
812     browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
813 
814     // Arg1 is the name of the callback
815     NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
816     NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
817     free(callbackString);
818 
819     // Invoke a callback that returns a script object
820     NPVariant object_result;
821     browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, &args[1], 1, &object_result);
822 
823     // Script object returned
824     NPObject* script_object = object_result.value.objectValue;
825 
826     // Arg2 is the name of the method to be called on the script object
827     NPUTF8* object_mehod_string = createCStringFromNPVariant(&args[1]);
828     NPIdentifier object_method = browser->getstringidentifier(object_mehod_string);
829     free(object_mehod_string);
830 
831     // Create a fresh NPObject to be passed as an argument
832     NPObject* object_arg = browser->createobject(obj->npp, &pluginClass);
833     NPVariant invoke_args[1];
834     OBJECT_TO_NPVARIANT(object_arg, invoke_args[0]);
835 
836     // Invoke the script method
837     NPVariant object_method_result;
838     browser->invoke(obj->npp, script_object, object_method, invoke_args, 1, &object_method_result);
839 
840     browser->releasevariantvalue(&object_result);
841     VOID_TO_NPVARIANT(*result);
842     if (NPVARIANT_IS_OBJECT(object_method_result)) {
843         // Now return the callbacks return value back to our caller.
844         // BUG 897451: This should be the same as the
845         // windowScriptObject, but its not (in Chrome) - or at least, it
846         // has a different refcount. This means Chrome will delete the
847         // object before returning it and the calling JS gets a garbage
848         // value.  Firefox handles it fine.
849         OBJECT_TO_NPVARIANT(NPVARIANT_TO_OBJECT(object_method_result), *result);
850     } else {
851         browser->releasevariantvalue(&object_method_result);
852         VOID_TO_NPVARIANT(*result);
853     }
854 
855     browser->releaseobject(object_arg);
856 
857     return true;
858 }
859 
860 // Helper function to notify the layout test controller that the test completed.
notifyTestCompletion(NPP npp,NPObject * object)861 void notifyTestCompletion(NPP npp, NPObject* object)
862 {
863     NPVariant result;
864     NPString script;
865     script.UTF8Characters = "javascript:window.layoutTestController.notifyDone();";
866     script.UTF8Length = strlen("javascript:window.layoutTestController.notifyDone();");
867     browser->evaluate(npp, object, &script, &result);
868     browser->releasevariantvalue(&result);
869 }
870 
testDocumentOpen(NPP npp)871 bool testDocumentOpen(NPP npp)
872 {
873     NPIdentifier documentId = browser->getstringidentifier("document");
874     NPIdentifier openId = browser->getstringidentifier("open");
875 
876     NPObject* windowObject = 0;
877     browser->getvalue(npp, NPNVWindowNPObject, &windowObject);
878     if (!windowObject)
879         return false;
880 
881     NPVariant docVariant;
882     browser->getproperty(npp, windowObject, documentId, &docVariant);
883     if (docVariant.type != NPVariantType_Object) {
884         browser->releaseobject(windowObject);
885         return false;
886     }
887 
888     NPObject* documentObject = NPVARIANT_TO_OBJECT(docVariant);
889 
890     NPVariant openArgs[2];
891     STRINGZ_TO_NPVARIANT("text/html", openArgs[0]);
892     STRINGZ_TO_NPVARIANT("_blank", openArgs[1]);
893 
894     NPVariant result;
895     if (!browser->invoke(npp, documentObject, openId, openArgs, 2, &result)) {
896         browser->releaseobject(windowObject);
897         browser->releaseobject(documentObject);
898         return false;
899     }
900 
901     browser->releaseobject(documentObject);
902 
903     if (result.type != NPVariantType_Object) {
904         browser->releaseobject(windowObject);
905         browser->releasevariantvalue(&result);
906         return false;
907     }
908 
909     pluginLogWithWindowObjectVariableArgs(windowObject, npp, "DOCUMENT OPEN SUCCESS");
910     notifyTestCompletion(npp, result.value.objectValue);
911     browser->releaseobject(result.value.objectValue);
912     browser->releaseobject(windowObject);
913     return true;
914 }
915 
testWindowOpen(NPP npp)916 bool testWindowOpen(NPP npp)
917 {
918     NPIdentifier openId = browser->getstringidentifier("open");
919 
920     NPObject* windowObject = 0;
921     browser->getvalue(npp, NPNVWindowNPObject, &windowObject);
922     if (!windowObject)
923         return false;
924 
925     NPVariant openArgs[2];
926     STRINGZ_TO_NPVARIANT("about:blank", openArgs[0]);
927     STRINGZ_TO_NPVARIANT("_blank", openArgs[1]);
928 
929     NPVariant result;
930     if (!browser->invoke(npp, windowObject, openId, openArgs, 2, &result)) {
931         browser->releaseobject(windowObject);
932         return false;
933     }
934 
935     if (result.type != NPVariantType_Object) {
936         browser->releaseobject(windowObject);
937         browser->releasevariantvalue(&result);
938         return false;
939     }
940 
941     pluginLogWithWindowObjectVariableArgs(windowObject, npp, "WINDOW OPEN SUCCESS");
942     notifyTestCompletion(npp, result.value.objectValue);
943     browser->releaseobject(result.value.objectValue);
944     browser->releaseobject(windowObject);
945     return true;
946 }
947 
testSetStatus(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)948 static bool testSetStatus(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
949 {
950     char* message = 0;
951     if (argCount && NPVARIANT_IS_STRING(args[0])) {
952         NPString statusString = NPVARIANT_TO_STRING(args[0]);
953         message = toCString(statusString);
954     }
955 
956     browser->status(obj->npp, message);
957 
958     free(message);
959     return true;
960 }
961 
testResizeTo(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)962 static bool testResizeTo(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
963 {
964     VOID_TO_NPVARIANT(*result);
965 
966     NPObject* windowObject;
967     if (NPERR_NO_ERROR != browser->getvalue(obj->npp, NPNVWindowNPObject, &windowObject))
968         return false;
969 
970     NPVariant callResult;
971     if (browser->invoke(obj->npp, windowObject, browser->getstringidentifier("resizePlugin"), args, argCount, &callResult))
972         browser->releasevariantvalue(&callResult);
973 
974     // Force layout.
975     if (browser->getproperty(obj->npp, windowObject, browser->getstringidentifier("pageYOffset"), &callResult))
976         browser->releasevariantvalue(&callResult);
977 
978     return true;
979 }
980 
normalizeOverride(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)981 static bool normalizeOverride(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
982 {
983     VOID_TO_NPVARIANT(*result);
984 
985     NPObject* windowObject;
986     if (NPERR_NO_ERROR != browser->getvalue(obj->npp, NPNVWindowNPObject, &windowObject))
987         return false;
988 
989     NPVariant callResult;
990     if (browser->invoke(obj->npp, windowObject, browser->getstringidentifier("pluginCallback"), args, argCount, &callResult))
991         browser->releasevariantvalue(&callResult);
992 
993     return true;
994 }
995 
invalidateRect(PluginObject * obj,const NPVariant * args,uint32_t argCount,NPVariant * result)996 static bool invalidateRect(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
997 {
998     if (argCount != 4)
999         return false;
1000 
1001     NPRect rect;
1002     rect.left = static_cast<int>(NPVARIANT_TO_DOUBLE(args[0]));
1003     rect.top = static_cast<int>(NPVARIANT_TO_DOUBLE(args[1]));
1004     rect.right = static_cast<int>(NPVARIANT_TO_DOUBLE(args[2]));
1005     rect.bottom = static_cast<int>(NPVARIANT_TO_DOUBLE(args[3]));
1006 
1007     browser->invalidaterect(obj->npp, &rect);
1008     return true;
1009 }
1010 
pluginInvoke(NPObject * header,NPIdentifier name,const NPVariant * args,uint32_t argCount,NPVariant * result)1011 static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)
1012 {
1013     PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
1014     if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD])
1015         return testCallback(plugin, args, argCount, result);
1016     if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD_RETURN])
1017         return testCallbackReturn(plugin, args, argCount, result);
1018     if (name == pluginMethodIdentifiers[ID_TEST_GETURL])
1019         return getURL(plugin, args, argCount, result);
1020     if (name == pluginMethodIdentifiers[ID_TEST_DOM_ACCESS])
1021         return testDOMAccess(plugin, args, argCount, result);
1022     if (name == pluginMethodIdentifiers[ID_TEST_GET_URL_NOTIFY])
1023         return getURLNotify(plugin, args, argCount, result);
1024     if (name == pluginMethodIdentifiers[ID_TEST_INVOKE_DEFAULT])
1025         return testInvokeDefault(plugin, args, argCount, result);
1026     if (name == pluginMethodIdentifiers[ID_TEST_ENUMERATE])
1027         return testEnumerate(plugin, args, argCount, result);
1028     if (name == pluginMethodIdentifiers[ID_DESTROY_STREAM])
1029         return destroyStream(plugin, args, argCount, result);
1030     if (name == pluginMethodIdentifiers[ID_TEST_GETINTIDENTIFIER])
1031         return testGetIntIdentifier(plugin, args, argCount, result);
1032     if (name == pluginMethodIdentifiers[ID_TEST_EVALUATE])
1033         return testEvaluate(plugin, args, argCount, result);
1034     if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY])
1035         return testGetProperty(plugin, args, argCount, result);
1036     if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY_RETURN_VALUE])
1037         return testGetPropertyReturnValue(plugin, args, argCount, result);
1038     if (name == pluginMethodIdentifiers[ID_TEST_HAS_PROPERTY])
1039         return testHasProperty(plugin, args, argCount, result);
1040     if (name == pluginMethodIdentifiers[ID_TEST_HAS_METHOD])
1041         return testHasMethod(plugin, args, argCount, result);
1042     if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_STRING])
1043         return testIdentifierToString(plugin, args, argCount, result);
1044     if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_INT])
1045         return testIdentifierToInt(plugin, args, argCount, result);
1046     if (name == pluginMethodIdentifiers[ID_TEST_PASS_TEST_OBJECT])
1047         return testPassTestObject(plugin, args, argCount, result);
1048     if (name == pluginMethodIdentifiers[ID_TEST_POSTURL_FILE])
1049         return testPostURLFile(plugin, args, argCount, result);
1050     if (name == pluginMethodIdentifiers[ID_TEST_CONSTRUCT])
1051         return testConstruct(plugin, args, argCount, result);
1052     if (name == pluginMethodIdentifiers[ID_TEST_SCRIPT_OBJECT_INVOKE])
1053         return testScriptObjectInvoke(plugin, args, argCount, result);
1054     if (name == pluginMethodIdentifiers[ID_TEST_THROW_EXCEPTION_METHOD]) {
1055         browser->setexception(header, "plugin object testThrowException SUCCESS");
1056         return true;
1057     }
1058     if (name == pluginMethodIdentifiers[ID_TEST_FAIL_METHOD]) {
1059         NPObject* windowScriptObject;
1060         browser->getvalue(plugin->npp, NPNVWindowNPObject, &windowScriptObject);
1061         browser->invoke(plugin->npp, windowScriptObject, name, args, argCount, result);
1062         return false;
1063     }
1064     if (name == pluginMethodIdentifiers[ID_TEST_CLONE_OBJECT]) {
1065         NPObject* new_object = browser->createobject(plugin->npp, &pluginClass);
1066         assert(new_object->referenceCount == 1);
1067         OBJECT_TO_NPVARIANT(new_object, *result);
1068         return true;
1069     }
1070     if (name == pluginMethodIdentifiers[ID_TEST_CREATE_TEST_OBJECT]) {
1071         NPObject* testObject = browser->createobject(plugin->npp, getTestClass());
1072         assert(testObject->referenceCount == 1);
1073         OBJECT_TO_NPVARIANT(testObject, *result);
1074         return true;
1075     }
1076     if (name == pluginMethodIdentifiers[ID_DESTROY_NULL_STREAM])
1077         return destroyNullStream(plugin, args, argCount, result);
1078     if (name == pluginMethodIdentifiers[ID_TEST_RELOAD_PLUGINS_NO_PAGES]) {
1079         browser->reloadplugins(false);
1080         return true;
1081     }
1082     if (name == pluginMethodIdentifiers[ID_TEST_RELOAD_PLUGINS_AND_PAGES]) {
1083         browser->reloadplugins(true);
1084         return true;
1085     }
1086     if (name == pluginMethodIdentifiers[ID_TEST_GET_BROWSER_PROPERTY]) {
1087         browser->getproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVariantToIdentifier(args[1]), result);
1088         return true;
1089     }
1090     if (name == pluginMethodIdentifiers[ID_TEST_SET_BROWSER_PROPERTY]) {
1091         browser->setproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVariantToIdentifier(args[1]), &args[2]);
1092         return true;
1093     }
1094     if (name == pluginMethodIdentifiers[ID_REMEMBER]) {
1095         if (plugin->rememberedObject)
1096             browser->releaseobject(plugin->rememberedObject);
1097         plugin->rememberedObject = NPVARIANT_TO_OBJECT(args[0]);
1098         browser->retainobject(plugin->rememberedObject);
1099         VOID_TO_NPVARIANT(*result);
1100         return true;
1101     }
1102     if (name == pluginMethodIdentifiers[ID_GET_REMEMBERED_OBJECT]) {
1103         assert(plugin->rememberedObject);
1104         browser->retainobject(plugin->rememberedObject);
1105         OBJECT_TO_NPVARIANT(plugin->rememberedObject, *result);
1106         return true;
1107     }
1108     if (name == pluginMethodIdentifiers[ID_GET_AND_FORGET_REMEMBERED_OBJECT]) {
1109         assert(plugin->rememberedObject);
1110         OBJECT_TO_NPVARIANT(plugin->rememberedObject, *result);
1111         plugin->rememberedObject = 0;
1112         return true;
1113     }
1114     if (name == pluginMethodIdentifiers[ID_REF_COUNT]) {
1115         uint32_t refCount = NPVARIANT_TO_OBJECT(args[0])->referenceCount;
1116         INT32_TO_NPVARIANT(refCount, *result);
1117         return true;
1118     }
1119     if (name == pluginMethodIdentifiers[ID_SET_STATUS])
1120         return testSetStatus(plugin, args, argCount, result);
1121     if (name == pluginMethodIdentifiers[ID_RESIZE_TO])
1122         return testResizeTo(plugin, args, argCount, result);
1123     if (name == pluginMethodIdentifiers[ID_NORMALIZE])
1124         return normalizeOverride(plugin, args, argCount, result);
1125     if (name == pluginMethodIdentifiers[ID_INVALIDATE_RECT])
1126         return invalidateRect(plugin, args, argCount, result);
1127 
1128     return false;
1129 }
1130 
pluginInvalidate(NPObject * header)1131 static void pluginInvalidate(NPObject* header)
1132 {
1133     PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
1134     plugin->testObject = 0;
1135     plugin->rememberedObject = 0;
1136 }
1137 
pluginAllocate(NPP npp,NPClass * theClass)1138 static NPObject *pluginAllocate(NPP npp, NPClass *theClass)
1139 {
1140     PluginObject* newInstance = (PluginObject*)malloc(sizeof(PluginObject));
1141 
1142     if (!identifiersInitialized) {
1143         identifiersInitialized = true;
1144         initializeIdentifiers();
1145     }
1146 
1147     newInstance->pluginTest = 0;
1148     newInstance->npp = npp;
1149     newInstance->testObject = browser->createobject(npp, getTestClass());
1150     newInstance->rememberedObject = 0;
1151     newInstance->eventLogging = FALSE;
1152     newInstance->onStreamLoad = 0;
1153     newInstance->onStreamDestroy = 0;
1154     newInstance->onDestroy = 0;
1155     newInstance->onURLNotify = 0;
1156     newInstance->onSetWindow = 0;
1157     newInstance->onPaintEvent = 0;
1158     newInstance->logDestroy = FALSE;
1159     newInstance->logSetWindow = FALSE;
1160     newInstance->returnErrorFromNewStream = FALSE;
1161     newInstance->returnNegativeOneFromWrite = FALSE;
1162     newInstance->stream = 0;
1163 
1164     newInstance->firstUrl = 0;
1165     newInstance->firstHeaders = 0;
1166     newInstance->lastUrl = 0;
1167     newInstance->lastHeaders = 0;
1168 
1169     newInstance->testGetURLOnDestroy = FALSE;
1170     newInstance->testWindowOpen = FALSE;
1171     newInstance->testKeyboardFocusForPlugins = FALSE;
1172 
1173     newInstance->mouseDownForEvaluateScript = FALSE;
1174     newInstance->evaluateScriptOnMouseDownOrKeyDown = 0;
1175 
1176     return (NPObject*)newInstance;
1177 }
1178 
pluginDeallocate(NPObject * header)1179 static void pluginDeallocate(NPObject* header)
1180 {
1181     PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
1182     delete plugin->pluginTest;
1183     if (plugin->testObject)
1184         browser->releaseobject(plugin->testObject);
1185     if (plugin->rememberedObject)
1186         browser->releaseobject(plugin->rememberedObject);
1187 
1188     free(plugin->firstUrl);
1189     free(plugin->firstHeaders);
1190     free(plugin->lastUrl);
1191     free(plugin->lastHeaders);
1192     free(plugin);
1193 }
1194 
handleCallback(PluginObject * object,const char * url,NPReason reason,void * notifyData)1195 void handleCallback(PluginObject* object, const char *url, NPReason reason, void *notifyData)
1196 {
1197     assert(object);
1198 
1199     NPVariant args[2];
1200 
1201     NPObject* windowScriptObject;
1202     browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject);
1203 
1204     NPIdentifier callbackIdentifier = notifyData;
1205 
1206     INT32_TO_NPVARIANT(reason, args[0]);
1207 
1208     char* strHdr = 0;
1209     if (object->firstUrl && object->firstHeaders && object->lastUrl && object->lastHeaders) {
1210         // Format expected by JavaScript validator: four fields separated by \n\n:
1211         // First URL; first header block; last URL; last header block.
1212         // Note that header blocks already end with \n due to how NPStream::headers works.
1213         int len = strlen(object->firstUrl) + 2
1214             + strlen(object->firstHeaders) + 1
1215             + strlen(object->lastUrl) + 2
1216             + strlen(object->lastHeaders) + 1;
1217         strHdr = (char*)malloc(len + 1);
1218         snprintf(strHdr, len + 1, "%s\n\n%s\n%s\n\n%s\n",
1219                  object->firstUrl, object->firstHeaders, object->lastUrl, object->lastHeaders);
1220         STRINGN_TO_NPVARIANT(strHdr, len, args[1]);
1221     } else
1222         NULL_TO_NPVARIANT(args[1]);
1223 
1224     NPVariant browserResult;
1225     if (browser->invoke(object->npp, windowScriptObject, callbackIdentifier, args, 2, &browserResult))
1226         browser->releasevariantvalue(&browserResult);
1227 
1228     free(strHdr);
1229 }
1230 
notifyStream(PluginObject * object,const char * url,const char * headers)1231 void notifyStream(PluginObject* object, const char *url, const char *headers)
1232 {
1233     if (!object->firstUrl) {
1234         if (url)
1235             object->firstUrl = strdup(url);
1236         if (headers)
1237             object->firstHeaders = strdup(headers);
1238     } else {
1239         free(object->lastUrl);
1240         free(object->lastHeaders);
1241         object->lastUrl = (url ? strdup(url) : 0);
1242         object->lastHeaders = (headers ? strdup(headers) : 0);
1243     }
1244 }
1245 
testNPRuntime(NPP npp)1246 void testNPRuntime(NPP npp)
1247 {
1248     NPObject* windowScriptObject;
1249     browser->getvalue(npp, NPNVWindowNPObject, &windowScriptObject);
1250 
1251     // Invoke
1252     NPIdentifier testNPInvoke = browser->getstringidentifier("testNPInvoke");
1253     NPVariant args[7];
1254 
1255     VOID_TO_NPVARIANT(args[0]);
1256     NULL_TO_NPVARIANT(args[1]);
1257     BOOLEAN_TO_NPVARIANT(true, args[2]);
1258     INT32_TO_NPVARIANT(242, args[3]);
1259     DOUBLE_TO_NPVARIANT(242.242, args[4]);
1260     STRINGZ_TO_NPVARIANT("Hello, World", args[5]);
1261     OBJECT_TO_NPVARIANT(windowScriptObject, args[6]);
1262 
1263     NPVariant result;
1264     if (browser->invoke(npp, windowScriptObject, testNPInvoke, args, 7, &result))
1265         browser->releasevariantvalue(&result);
1266 
1267     browser->releaseobject(windowScriptObject);
1268 }
1269