OSDN Git Service

Merge WebKit at r71558: Initial merge by git.
[android-x86/external-webkit.git] / WebKitTools / DumpRenderTree / TestNetscapePlugIn / PluginObject.cpp
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.
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.
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              
76 // Helper function to log to the console object.
77 void pluginLog(NPP instance, const char* format, ...)
78 {
79     va_list args;
80     va_start(args, format);
81     char message[2048] = "PLUGIN: ";
82     vsprintf(message + strlen(message), format, args);
83     va_end(args);
84
85     NPObject* windowObject = 0;
86     NPError error = browser->getvalue(instance, NPNVWindowNPObject, &windowObject);
87     if (error != NPERR_NO_ERROR) {
88         fprintf(stderr, "Failed to retrieve window object while logging: %s\n", message);
89         return;
90     }
91
92     pluginLogWithWindowObject(windowObject, instance, message);
93     browser->releaseobject(windowObject);
94 }
95
96 static void pluginInvalidate(NPObject*);
97 static bool pluginHasProperty(NPObject*, NPIdentifier name);
98 static bool pluginHasMethod(NPObject*, NPIdentifier name);
99 static bool pluginGetProperty(NPObject*, NPIdentifier name, NPVariant*);
100 static bool pluginSetProperty(NPObject*, NPIdentifier name, const NPVariant*);
101 static bool pluginInvoke(NPObject*, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result);
102 static NPObject* pluginAllocate(NPP npp, NPClass*);
103 static void pluginDeallocate(NPObject*);
104
105 NPNetscapeFuncs* browser;
106 NPPluginFuncs* pluginFunctions;
107
108 static NPClass pluginClass = {
109     NP_CLASS_STRUCT_VERSION,
110     pluginAllocate,
111     pluginDeallocate,
112     pluginInvalidate,
113     pluginHasMethod,
114     pluginInvoke,
115     0, // NPClass::invokeDefault,
116     pluginHasProperty,
117     pluginGetProperty,
118     pluginSetProperty,
119     0, // NPClass::removeProperty
120     0, // NPClass::enumerate
121     0, // NPClass::construct
122 };
123
124 NPClass* getPluginClass(void)
125 {
126     return &pluginClass;
127 }
128
129 static bool identifiersInitialized = false;
130
131 enum {
132     ID_PROPERTY_PROPERTY = 0,
133     ID_PROPERTY_EVENT_LOGGING,
134     ID_PROPERTY_HAS_STREAM,
135     ID_PROPERTY_TEST_OBJECT,
136     ID_PROPERTY_LOG_DESTROY,
137     ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM,
138     ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE,
139     ID_PROPERTY_PRIVATE_BROWSING_ENABLED,
140     ID_PROPERTY_CACHED_PRIVATE_BROWSING_ENABLED,
141     ID_PROPERTY_THROW_EXCEPTION_PROPERTY,
142     ID_LAST_SET_WINDOW_ARGUMENTS,
143     ID_PROPERTY_WINDOWED_PLUGIN,
144     NUM_PROPERTY_IDENTIFIERS
145 };
146
147 static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
148 static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
149     "property",
150     "eventLoggingEnabled",
151     "hasStream",
152     "testObject",
153     "logDestroy",
154     "returnErrorFromNewStream",
155     "returnNegativeOneFromWrite",
156     "privateBrowsingEnabled",
157     "cachedPrivateBrowsingEnabled",
158     "testThrowExceptionProperty",
159     "lastSetWindowArguments",
160     "windowedPlugin"
161 };
162
163 enum {
164     ID_TEST_CALLBACK_METHOD = 0,
165     ID_TEST_GETURL,
166     ID_TEST_DOM_ACCESS,
167     ID_TEST_GET_URL_NOTIFY,
168     ID_TEST_INVOKE_DEFAULT,
169     ID_DESTROY_STREAM,
170     ID_TEST_ENUMERATE,
171     ID_TEST_GETINTIDENTIFIER,
172     ID_TEST_GET_PROPERTY,
173     ID_TEST_HAS_PROPERTY,
174     ID_TEST_HAS_METHOD,
175     ID_TEST_EVALUATE,
176     ID_TEST_GET_PROPERTY_RETURN_VALUE,
177     ID_TEST_IDENTIFIER_TO_STRING,
178     ID_TEST_IDENTIFIER_TO_INT,
179     ID_TEST_PASS_TEST_OBJECT,
180     ID_TEST_POSTURL_FILE,
181     ID_TEST_CONSTRUCT,
182     ID_TEST_THROW_EXCEPTION_METHOD,
183     ID_TEST_FAIL_METHOD,
184     ID_DESTROY_NULL_STREAM,
185     ID_TEST_RELOAD_PLUGINS_NO_PAGES,
186     ID_TEST_RELOAD_PLUGINS_AND_PAGES,
187     ID_TEST_GET_BROWSER_PROPERTY,
188     ID_TEST_SET_BROWSER_PROPERTY,
189     ID_REMEMBER,
190     ID_GET_REMEMBERED_OBJECT,
191     ID_GET_AND_FORGET_REMEMBERED_OBJECT,
192     ID_REF_COUNT,
193     ID_SET_STATUS,
194     ID_RESIZE_TO,
195     ID_NORMALIZE,
196     NUM_METHOD_IDENTIFIERS
197 };
198
199 static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
200 static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
201     "testCallback",
202     "getURL",
203     "testDOMAccess",
204     "getURLNotify",
205     "testInvokeDefault",
206     "destroyStream",
207     "testEnumerate",
208     "testGetIntIdentifier",
209     "testGetProperty",
210     "testHasProperty",
211     "testHasMethod",
212     "testEvaluate",
213     "testGetPropertyReturnValue",
214     "testIdentifierToString",
215     "testIdentifierToInt",
216     "testPassTestObject",
217     "testPostURLFile",
218     "testConstruct",
219     "testThrowException",
220     "testFail",
221     "destroyNullStream",
222     "reloadPluginsNoPages",
223     "reloadPluginsAndPages",
224     "testGetBrowserProperty",
225     "testSetBrowserProperty",
226     "remember",
227     "getRememberedObject",
228     "getAndForgetRememberedObject",
229     "refCount",
230     "setStatus",
231     "resizeTo",
232     "normalize"
233 };
234
235 static NPUTF8* createCStringFromNPVariant(const NPVariant* variant)
236 {
237     size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length;
238     NPUTF8* result = (NPUTF8*)malloc(length + 1);
239     memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length);
240     result[length] = '\0';
241     return result;
242 }
243
244 static void initializeIdentifiers(void)
245 {
246     browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, pluginPropertyIdentifiers);
247     browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, pluginMethodIdentifiers);
248 }
249
250 static bool pluginHasProperty(NPObject *obj, NPIdentifier name)
251 {
252     for (int i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++)
253         if (name == pluginPropertyIdentifiers[i])
254             return true;
255     return false;
256 }
257
258 static bool pluginHasMethod(NPObject *obj, NPIdentifier name)
259 {
260     for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++)
261         if (name == pluginMethodIdentifiers[i])
262             return true;
263     return false;
264 }
265
266 static bool pluginGetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)
267 {
268     PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
269     if (name == pluginPropertyIdentifiers[ID_PROPERTY_PROPERTY]) {
270         static const char* originalString = "property";
271         char* buf = static_cast<char*>(browser->memalloc(strlen(originalString) + 1));
272         strcpy(buf, originalString);
273         STRINGZ_TO_NPVARIANT(buf, *result);
274         return true;
275     }
276     if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
277         BOOLEAN_TO_NPVARIANT(plugin->eventLogging, *result);
278         return true;
279     }
280     if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
281         BOOLEAN_TO_NPVARIANT(plugin->logDestroy, *result);
282         return true;
283     }
284     if (name == pluginPropertyIdentifiers[ID_PROPERTY_HAS_STREAM]) {
285         BOOLEAN_TO_NPVARIANT(plugin->stream, *result);
286         return true;
287     }
288     if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT]) {
289         NPObject* testObject = plugin->testObject;
290         browser->retainobject(testObject);
291         OBJECT_TO_NPVARIANT(testObject, *result);
292         return true;
293     }
294     if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) {
295         BOOLEAN_TO_NPVARIANT(plugin->returnErrorFromNewStream, *result);
296         return true;
297     }
298     if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE]) {
299         BOOLEAN_TO_NPVARIANT(plugin->returnNegativeOneFromWrite, *result);
300         return true;
301     }
302     if (name == pluginPropertyIdentifiers[ID_PROPERTY_PRIVATE_BROWSING_ENABLED]) {
303         NPBool privateBrowsingEnabled = FALSE;
304         browser->getvalue(plugin->npp, NPNVprivateModeBool, &privateBrowsingEnabled);
305         BOOLEAN_TO_NPVARIANT(privateBrowsingEnabled, *result);
306         return true;
307     }
308     if (name == pluginPropertyIdentifiers[ID_PROPERTY_CACHED_PRIVATE_BROWSING_ENABLED]) {
309         BOOLEAN_TO_NPVARIANT(plugin->cachedPrivateBrowsingMode, *result);
310         return true;
311     }
312     if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PROPERTY]) {
313         browser->setexception(obj, "plugin object testThrowExceptionProperty SUCCESS");
314         return true;
315     }
316     if (name == pluginPropertyIdentifiers[ID_LAST_SET_WINDOW_ARGUMENTS]) {
317         char* buf = static_cast<char*>(browser->memalloc(256));
318         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,
319             plugin->lastWindow.clipRect.left, plugin->lastWindow.clipRect.top, plugin->lastWindow.clipRect.right - plugin->lastWindow.clipRect.left, plugin->lastWindow.clipRect.bottom - plugin->lastWindow.clipRect.top);
320
321         STRINGZ_TO_NPVARIANT(buf, *result);
322         return true;
323     }
324
325     return false;
326 }
327
328 static bool pluginSetProperty(NPObject* obj, NPIdentifier name, const NPVariant* variant)
329 {
330     PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
331     if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
332         plugin->eventLogging = NPVARIANT_TO_BOOLEAN(*variant);
333         return true;
334     }
335     if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
336         plugin->logDestroy = NPVARIANT_TO_BOOLEAN(*variant);
337         return true;
338     }
339     if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) {
340         plugin->returnErrorFromNewStream = NPVARIANT_TO_BOOLEAN(*variant);
341         return true;
342     }
343     if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE]) {
344         plugin->returnNegativeOneFromWrite = NPVARIANT_TO_BOOLEAN(*variant);
345         return true;
346     }
347     if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PROPERTY]) {
348         browser->setexception(obj, "plugin object testThrowExceptionProperty SUCCESS");
349         return true;
350     }
351     if (name == pluginPropertyIdentifiers[ID_PROPERTY_WINDOWED_PLUGIN]) {
352         browser->setvalue(plugin->npp, NPPVpluginWindowBool, (void *)NPVARIANT_TO_BOOLEAN(*variant));
353         return true;
354     }
355
356     return false;
357 }
358
359 static bool testDOMAccess(PluginObject* obj, const NPVariant*, uint32_t, NPVariant* result)
360 {
361     // Get plug-in's DOM element
362     NPObject* elementObject;
363     if (browser->getvalue(obj->npp, NPNVPluginElementNPObject, &elementObject) == NPERR_NO_ERROR) {
364         // Get style
365         NPVariant styleVariant;
366         NPIdentifier styleIdentifier = browser->getstringidentifier("style");
367         if (browser->getproperty(obj->npp, elementObject, styleIdentifier, &styleVariant) && NPVARIANT_IS_OBJECT(styleVariant)) {
368             // Set style.border
369             NPIdentifier borderIdentifier = browser->getstringidentifier("border");
370             NPVariant borderVariant;
371             STRINGZ_TO_NPVARIANT("3px solid red", borderVariant);
372             browser->setproperty(obj->npp, NPVARIANT_TO_OBJECT(styleVariant), borderIdentifier, &borderVariant);
373             browser->releasevariantvalue(&styleVariant);
374         }
375
376         browser->releaseobject(elementObject);
377     }
378     VOID_TO_NPVARIANT(*result);
379     return true;
380 }
381
382 static NPIdentifier stringVariantToIdentifier(NPVariant variant)
383 {
384     assert(NPVARIANT_IS_STRING(variant));
385     NPUTF8* utf8String = createCStringFromNPVariant(&variant);
386     NPIdentifier identifier = browser->getstringidentifier(utf8String);
387     free(utf8String);
388     return identifier;
389 }
390
391 static NPIdentifier int32VariantToIdentifier(NPVariant variant)
392 {
393     assert(NPVARIANT_IS_INT32(variant));
394     int32_t integer = NPVARIANT_TO_INT32(variant);
395     return browser->getintidentifier(integer);
396 }
397
398 static NPIdentifier doubleVariantToIdentifier(NPVariant variant)
399 {
400     assert(NPVARIANT_IS_DOUBLE(variant));
401     double value = NPVARIANT_TO_DOUBLE(variant);
402     // Sadly there is no "getdoubleidentifier"
403     int32_t integer = static_cast<int32_t>(value);
404     return browser->getintidentifier(integer);
405 }
406
407 static NPIdentifier variantToIdentifier(NPVariant variant)
408 {
409     if (NPVARIANT_IS_STRING(variant))
410         return stringVariantToIdentifier(variant);
411     if (NPVARIANT_IS_INT32(variant))
412         return int32VariantToIdentifier(variant);
413     if (NPVARIANT_IS_DOUBLE(variant))
414         return doubleVariantToIdentifier(variant);
415     return 0;
416 }
417
418 static bool testIdentifierToString(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
419 {
420     if (argCount != 1)
421         return true;
422     NPIdentifier identifier = variantToIdentifier(args[0]);
423     if (!identifier)
424         return true;
425     NPUTF8* utf8String = browser->utf8fromidentifier(identifier);
426     if (!utf8String)
427         return true;
428     STRINGZ_TO_NPVARIANT(utf8String, *result);
429     return true;
430 }
431
432 static bool testIdentifierToInt(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
433 {
434     if (argCount != 1)
435         return false;
436     NPIdentifier identifier = variantToIdentifier(args[0]);
437     if (!identifier)
438         return false;
439     int32_t integer = browser->intfromidentifier(identifier);
440     INT32_TO_NPVARIANT(integer, *result);
441     return true;
442 }
443
444 static bool testPassTestObject(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
445 {
446     if (argCount != 2 || !NPVARIANT_IS_STRING(args[0]))
447         return false;
448
449     NPObject* windowScriptObject;
450     browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
451
452     NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
453     NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
454     free(callbackString);
455
456     NPVariant browserResult;
457     browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, &args[1], 1, &browserResult);
458     browser->releasevariantvalue(&browserResult);
459
460     VOID_TO_NPVARIANT(*result);
461     return true;
462 }
463
464 static bool testCallback(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
465 {
466     if (!argCount || !NPVARIANT_IS_STRING(args[0]))
467         return false;
468
469     NPObject* windowScriptObject;
470     browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
471
472     NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
473     NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
474     free(callbackString);
475
476     NPVariant browserResult;
477     if (browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, 0, 0, &browserResult))
478         browser->releasevariantvalue(&browserResult);
479
480     browser->releaseobject(windowScriptObject);
481     
482     VOID_TO_NPVARIANT(*result);
483     return true;
484 }
485
486 static bool getURL(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
487 {
488     if (argCount == 2 && NPVARIANT_IS_STRING(args[0]) && NPVARIANT_IS_STRING(args[1])) {
489         NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
490         NPUTF8* targetString = createCStringFromNPVariant(&args[1]);
491         NPError npErr = browser->geturl(obj->npp, urlString, targetString);
492         free(urlString);
493         free(targetString);
494
495         INT32_TO_NPVARIANT(npErr, *result);
496         return true;
497     }
498     if (argCount == 1 && NPVARIANT_IS_STRING(args[0])) {
499         NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
500         NPError npErr = browser->geturl(obj->npp, urlString, 0);
501         free(urlString);
502
503         INT32_TO_NPVARIANT(npErr, *result);
504         return true;
505     }
506     return false;
507 }
508
509 static bool getURLNotify(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
510 {
511     if (argCount != 3 || !NPVARIANT_IS_STRING(args[0])
512         || (!NPVARIANT_IS_STRING(args[1]) && !NPVARIANT_IS_NULL(args[1]))
513         || !NPVARIANT_IS_STRING(args[2]))
514         return false;
515
516     NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
517     NPUTF8* targetString = (NPVARIANT_IS_STRING(args[1]) ? createCStringFromNPVariant(&args[1]) : 0);
518     NPUTF8* callbackString = createCStringFromNPVariant(&args[2]);
519
520     NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
521     browser->geturlnotify(obj->npp, urlString, targetString, callbackIdentifier);
522
523     free(urlString);
524     free(targetString);
525     free(callbackString);
526
527     VOID_TO_NPVARIANT(*result);
528     return true;
529 }
530
531 static bool testInvokeDefault(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
532 {
533     if (!NPVARIANT_IS_OBJECT(args[0]))
534         return false;
535
536     NPObject* callback = NPVARIANT_TO_OBJECT(args[0]);
537
538     NPVariant invokeArgs[1];
539     NPVariant browserResult;
540
541     STRINGZ_TO_NPVARIANT("test", invokeArgs[0]);
542     bool retval = browser->invokeDefault(obj->npp, callback, invokeArgs, 1, &browserResult);
543
544     if (retval)
545         browser->releasevariantvalue(&browserResult);
546
547     BOOLEAN_TO_NPVARIANT(retval, *result);
548     return true;
549 }
550
551 static bool destroyStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
552 {
553     NPError npError = browser->destroystream(obj->npp, obj->stream, NPRES_USER_BREAK);
554     INT32_TO_NPVARIANT(npError, *result);
555     return true;
556 }
557
558 static bool destroyNullStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
559 {
560     NPError npError = browser->destroystream(obj->npp, 0, NPRES_USER_BREAK);
561     INT32_TO_NPVARIANT(npError, *result);
562     return true;
563 }
564
565 static bool testEnumerate(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
566 {
567     if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_OBJECT(args[1]))
568         return false;
569
570     uint32_t count;
571     NPIdentifier* identifiers;
572     if (browser->enumerate(obj->npp, NPVARIANT_TO_OBJECT(args[0]), &identifiers, &count)) {
573         NPObject* outArray = NPVARIANT_TO_OBJECT(args[1]);
574         NPIdentifier pushIdentifier = browser->getstringidentifier("push");
575
576         for (uint32_t i = 0; i < count; i++) {
577             NPUTF8* string = browser->utf8fromidentifier(identifiers[i]);
578
579             if (!string)
580                 continue;
581
582             NPVariant args[1];
583             STRINGZ_TO_NPVARIANT(string, args[0]);
584             NPVariant browserResult;
585             if (browser->invoke(obj->npp, outArray, pushIdentifier, args, 1, &browserResult))
586                 browser->releasevariantvalue(&browserResult);
587             browser->memfree(string);
588         }
589
590         browser->memfree(identifiers);
591     }
592
593     VOID_TO_NPVARIANT(*result);
594     return true;
595 }
596
597 static bool testGetIntIdentifier(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
598 {
599     if (argCount != 1 || !NPVARIANT_IS_DOUBLE(args[0]))
600         return false;
601
602     NPIdentifier identifier = browser->getintidentifier((int)NPVARIANT_TO_DOUBLE(args[0]));
603     INT32_TO_NPVARIANT((int32_t)(long long)identifier, *result);
604     return true;
605 }
606
607 static bool testGetProperty(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
608 {
609     if (!argCount)
610         return false;
611
612     NPObject* object;
613     browser->getvalue(obj->npp, NPNVWindowNPObject, &object);
614
615     for (uint32_t i = 0; i < argCount; i++) {
616         assert(NPVARIANT_IS_STRING(args[i]));
617         NPUTF8* propertyString = createCStringFromNPVariant(&args[i]);
618         NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
619         free(propertyString);
620
621         NPVariant variant;
622         bool retval = browser->getproperty(obj->npp, object, propertyIdentifier, &variant);
623         browser->releaseobject(object);
624
625         if (!retval)
626             break;
627
628         if (i + 1 < argCount) {
629             assert(NPVARIANT_IS_OBJECT(variant));
630             object = NPVARIANT_TO_OBJECT(variant);
631         } else {
632             *result = variant;
633             return true;
634         }
635     }
636
637     VOID_TO_NPVARIANT(*result);
638     return false;
639 }
640
641 static bool testHasProperty(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
642 {
643     if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
644         return false;
645
646     NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
647     NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
648     free(propertyString);
649
650     bool retval = browser->hasproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier);
651
652     BOOLEAN_TO_NPVARIANT(retval, *result);
653     return true;
654 }
655
656 static bool testHasMethod(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
657 {
658     if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
659         return false;
660
661     NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
662     NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
663     free(propertyString);
664
665     bool retval = browser->hasmethod(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier);
666
667     BOOLEAN_TO_NPVARIANT(retval, *result);
668     return true;
669 }
670
671 static bool testEvaluate(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
672 {
673     if (argCount != 1 || !NPVARIANT_IS_STRING(args[0]))
674         return false;
675     NPObject* windowScriptObject;
676     browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
677
678     NPString s = NPVARIANT_TO_STRING(args[0]);
679
680     bool retval = browser->evaluate(obj->npp, windowScriptObject, &s, result);
681     browser->releaseobject(windowScriptObject);
682     return retval;
683 }
684
685 static bool testGetPropertyReturnValue(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
686 {
687     if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
688         return false;
689
690     NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
691     NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
692     free(propertyString);
693
694     NPVariant variant;
695     bool retval = browser->getproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier, &variant);
696     if (retval)
697         browser->releasevariantvalue(&variant);
698
699     BOOLEAN_TO_NPVARIANT(retval, *result);
700     return true;
701 }
702
703 static char* toCString(const NPString& string)
704 {
705     char* result = static_cast<char*>(malloc(string.UTF8Length + 1));
706     memcpy(result, string.UTF8Characters, string.UTF8Length);
707     result[string.UTF8Length] = '\0';
708
709     return result;
710 }
711
712 static bool testPostURLFile(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
713 {
714     if (argCount != 4 || !NPVARIANT_IS_STRING(args[0]) || !NPVARIANT_IS_STRING(args[1]) || !NPVARIANT_IS_STRING(args[2]) || !NPVARIANT_IS_STRING(args[3]))
715         return false;
716
717     NPString urlString = NPVARIANT_TO_STRING(args[0]);
718     char* url = toCString(urlString);
719
720     NPString targetString = NPVARIANT_TO_STRING(args[1]);
721     char* target = toCString(targetString);
722
723     NPString pathString = NPVARIANT_TO_STRING(args[2]);
724     char* path = toCString(pathString);
725
726     NPString contentsString = NPVARIANT_TO_STRING(args[3]);
727
728     FILE* tempFile = fopen(path, "w");
729     if (!tempFile)
730         return false;
731
732     if (!fwrite(contentsString.UTF8Characters, contentsString.UTF8Length, 1, tempFile))
733         return false;
734
735     fclose(tempFile);
736
737     NPError error = browser->posturl(obj->npp, url, target, pathString.UTF8Length, path, TRUE);
738
739     free(path);
740     free(target);
741     free(url);
742
743     BOOLEAN_TO_NPVARIANT(error == NPERR_NO_ERROR, *result);
744     return true;
745 }
746
747 static bool testConstruct(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
748 {
749     if (!argCount || !NPVARIANT_IS_OBJECT(args[0]))
750         return false;
751     
752     return browser->construct(obj->npp, NPVARIANT_TO_OBJECT(args[0]), args + 1, argCount - 1, result);
753 }
754
755 // Helper function to notify the layout test controller that the test completed.
756 void notifyTestCompletion(NPP npp, NPObject* object)
757 {
758     NPVariant result;
759     NPString script;
760     script.UTF8Characters = "javascript:window.layoutTestController.notifyDone();";
761     script.UTF8Length = strlen("javascript:window.layoutTestController.notifyDone();");
762     browser->evaluate(npp, object, &script, &result);
763     browser->releasevariantvalue(&result);
764 }
765
766 bool testDocumentOpen(NPP npp)
767 {
768     NPIdentifier documentId = browser->getstringidentifier("document");
769     NPIdentifier openId = browser->getstringidentifier("open");
770
771     NPObject* windowObject = 0;
772     browser->getvalue(npp, NPNVWindowNPObject, &windowObject);
773     if (!windowObject)
774         return false;
775
776     NPVariant docVariant;
777     browser->getproperty(npp, windowObject, documentId, &docVariant);
778     if (docVariant.type != NPVariantType_Object) {
779         browser->releaseobject(windowObject);
780         return false;
781     }
782
783     NPObject* documentObject = NPVARIANT_TO_OBJECT(docVariant);
784
785     NPVariant openArgs[2];
786     STRINGZ_TO_NPVARIANT("text/html", openArgs[0]);
787     STRINGZ_TO_NPVARIANT("_blank", openArgs[1]);
788
789     NPVariant result;
790     if (!browser->invoke(npp, documentObject, openId, openArgs, 2, &result)) {
791         browser->releaseobject(windowObject);
792         browser->releaseobject(documentObject);
793         return false;
794     }
795
796     browser->releaseobject(documentObject);
797
798     if (result.type != NPVariantType_Object) {
799         browser->releaseobject(windowObject);
800         browser->releasevariantvalue(&result);
801         return false;
802     }
803
804     pluginLogWithWindowObjectVariableArgs(windowObject, npp, "DOCUMENT OPEN SUCCESS");
805     notifyTestCompletion(npp, result.value.objectValue);
806     browser->releaseobject(result.value.objectValue);
807     browser->releaseobject(windowObject);
808     return true;
809 }
810
811 bool testWindowOpen(NPP npp)
812 {
813     NPIdentifier openId = browser->getstringidentifier("open");
814
815     NPObject* windowObject = 0;
816     browser->getvalue(npp, NPNVWindowNPObject, &windowObject);
817     if (!windowObject)
818         return false;
819
820     NPVariant openArgs[2];
821     STRINGZ_TO_NPVARIANT("about:blank", openArgs[0]);
822     STRINGZ_TO_NPVARIANT("_blank", openArgs[1]);
823
824     NPVariant result;
825     if (!browser->invoke(npp, windowObject, openId, openArgs, 2, &result)) {
826         browser->releaseobject(windowObject);
827         return false;
828     }
829
830     if (result.type != NPVariantType_Object) {
831         browser->releaseobject(windowObject);
832         browser->releasevariantvalue(&result);
833         return false;
834     }
835
836     pluginLogWithWindowObjectVariableArgs(windowObject, npp, "WINDOW OPEN SUCCESS");
837     notifyTestCompletion(npp, result.value.objectValue);
838     browser->releaseobject(result.value.objectValue);
839     browser->releaseobject(windowObject);
840     return true;
841 }
842
843 static bool testSetStatus(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
844 {
845     char* message = 0;
846     if (argCount && NPVARIANT_IS_STRING(args[0])) {
847         NPString statusString = NPVARIANT_TO_STRING(args[0]);
848         message = toCString(statusString);
849     }
850     
851     browser->status(obj->npp, message);
852
853     free(message);
854     return true;
855 }
856
857 static bool testResizeTo(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
858 {
859     VOID_TO_NPVARIANT(*result);
860
861     NPObject* windowObject;
862     if (NPERR_NO_ERROR != browser->getvalue(obj->npp, NPNVWindowNPObject, &windowObject))
863         return false;
864
865     NPVariant callResult;
866     if (browser->invoke(obj->npp, windowObject, browser->getstringidentifier("resizePlugin"), args, argCount, &callResult))
867         browser->releasevariantvalue(&callResult);
868
869     // Force layout.
870     if (browser->getproperty(obj->npp, windowObject, browser->getstringidentifier("pageYOffset"), &callResult))
871         browser->releasevariantvalue(&callResult);
872
873     return true;
874 }
875
876 static bool normalizeOverride(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
877 {
878     VOID_TO_NPVARIANT(*result);
879
880     NPObject* windowObject;
881     if (NPERR_NO_ERROR != browser->getvalue(obj->npp, NPNVWindowNPObject, &windowObject))
882         return false;
883
884     NPVariant callResult;
885     if (browser->invoke(obj->npp, windowObject, browser->getstringidentifier("pluginCallback"), args, argCount, &callResult))
886         browser->releasevariantvalue(&callResult);
887
888     return true;
889 }
890
891
892 static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)
893 {
894     PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
895     if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD])
896         return testCallback(plugin, args, argCount, result);
897     if (name == pluginMethodIdentifiers[ID_TEST_GETURL])
898         return getURL(plugin, args, argCount, result);
899     if (name == pluginMethodIdentifiers[ID_TEST_DOM_ACCESS])
900         return testDOMAccess(plugin, args, argCount, result);
901     if (name == pluginMethodIdentifiers[ID_TEST_GET_URL_NOTIFY])
902         return getURLNotify(plugin, args, argCount, result);
903     if (name == pluginMethodIdentifiers[ID_TEST_INVOKE_DEFAULT])
904         return testInvokeDefault(plugin, args, argCount, result);
905     if (name == pluginMethodIdentifiers[ID_TEST_ENUMERATE])
906         return testEnumerate(plugin, args, argCount, result);
907     if (name == pluginMethodIdentifiers[ID_DESTROY_STREAM])
908         return destroyStream(plugin, args, argCount, result);
909     if (name == pluginMethodIdentifiers[ID_TEST_GETINTIDENTIFIER])
910         return testGetIntIdentifier(plugin, args, argCount, result);
911     if (name == pluginMethodIdentifiers[ID_TEST_EVALUATE])
912         return testEvaluate(plugin, args, argCount, result);
913     if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY])
914         return testGetProperty(plugin, args, argCount, result);
915     if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY_RETURN_VALUE])
916         return testGetPropertyReturnValue(plugin, args, argCount, result);
917     if (name == pluginMethodIdentifiers[ID_TEST_HAS_PROPERTY])
918         return testHasProperty(plugin, args, argCount, result);
919     if (name == pluginMethodIdentifiers[ID_TEST_HAS_METHOD])
920         return testHasMethod(plugin, args, argCount, result);
921     if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_STRING])
922         return testIdentifierToString(plugin, args, argCount, result);
923     if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_INT])
924         return testIdentifierToInt(plugin, args, argCount, result);
925     if (name == pluginMethodIdentifiers[ID_TEST_PASS_TEST_OBJECT])
926         return testPassTestObject(plugin, args, argCount, result);
927     if (name == pluginMethodIdentifiers[ID_TEST_POSTURL_FILE])
928         return testPostURLFile(plugin, args, argCount, result);
929     if (name == pluginMethodIdentifiers[ID_TEST_CONSTRUCT])
930         return testConstruct(plugin, args, argCount, result);
931     if (name == pluginMethodIdentifiers[ID_TEST_THROW_EXCEPTION_METHOD]) {
932         browser->setexception(header, "plugin object testThrowException SUCCESS");
933         return true;
934     }
935     if (name == pluginMethodIdentifiers[ID_TEST_FAIL_METHOD]) {
936         NPObject* windowScriptObject;
937         browser->getvalue(plugin->npp, NPNVWindowNPObject, &windowScriptObject);
938         browser->invoke(plugin->npp, windowScriptObject, name, args, argCount, result);
939         return false;
940     }
941     if (name == pluginMethodIdentifiers[ID_DESTROY_NULL_STREAM])
942         return destroyNullStream(plugin, args, argCount, result);
943     if (name == pluginMethodIdentifiers[ID_TEST_RELOAD_PLUGINS_NO_PAGES]) {
944         browser->reloadplugins(false);
945         return true;
946     }
947     if (name == pluginMethodIdentifiers[ID_TEST_RELOAD_PLUGINS_AND_PAGES]) {
948         browser->reloadplugins(true);
949         return true;
950     }
951     if (name == pluginMethodIdentifiers[ID_TEST_GET_BROWSER_PROPERTY]) {
952         browser->getproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVariantToIdentifier(args[1]), result);
953         return true;
954     }
955     if (name == pluginMethodIdentifiers[ID_TEST_SET_BROWSER_PROPERTY]) {
956         browser->setproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVariantToIdentifier(args[1]), &args[2]);
957         return true;
958     }
959     if (name == pluginMethodIdentifiers[ID_REMEMBER]) {
960         if (plugin->rememberedObject)
961             browser->releaseobject(plugin->rememberedObject);
962         plugin->rememberedObject = NPVARIANT_TO_OBJECT(args[0]);
963         browser->retainobject(plugin->rememberedObject);
964         VOID_TO_NPVARIANT(*result);
965         return true;
966     }
967     if (name == pluginMethodIdentifiers[ID_GET_REMEMBERED_OBJECT]) {
968         assert(plugin->rememberedObject);
969         browser->retainobject(plugin->rememberedObject);
970         OBJECT_TO_NPVARIANT(plugin->rememberedObject, *result);
971         return true;
972     }
973     if (name == pluginMethodIdentifiers[ID_GET_AND_FORGET_REMEMBERED_OBJECT]) {
974         assert(plugin->rememberedObject);
975         OBJECT_TO_NPVARIANT(plugin->rememberedObject, *result);
976         plugin->rememberedObject = 0;
977         return true;
978     }
979     if (name == pluginMethodIdentifiers[ID_REF_COUNT]) {
980         uint32_t refCount = NPVARIANT_TO_OBJECT(args[0])->referenceCount;
981         INT32_TO_NPVARIANT(refCount, *result);
982         return true;
983     }
984     if (name == pluginMethodIdentifiers[ID_SET_STATUS])
985         return testSetStatus(plugin, args, argCount, result);
986     if (name == pluginMethodIdentifiers[ID_RESIZE_TO])
987         return testResizeTo(plugin, args, argCount, result);
988     if (name == pluginMethodIdentifiers[ID_NORMALIZE])
989         return normalizeOverride(plugin, args, argCount, result);
990
991     return false;
992 }
993
994 static void pluginInvalidate(NPObject* header)
995 {
996     PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
997     plugin->testObject = 0;
998     plugin->rememberedObject = 0;
999 }
1000
1001 static NPObject *pluginAllocate(NPP npp, NPClass *theClass)
1002 {
1003     PluginObject* newInstance = (PluginObject*)malloc(sizeof(PluginObject));
1004
1005     if (!identifiersInitialized) {
1006         identifiersInitialized = true;
1007         initializeIdentifiers();
1008     }
1009
1010     newInstance->pluginTest = 0;
1011     newInstance->npp = npp;
1012     newInstance->testObject = browser->createobject(npp, getTestClass());
1013     newInstance->rememberedObject = 0;
1014     newInstance->eventLogging = FALSE;
1015     newInstance->onStreamLoad = 0;
1016     newInstance->onStreamDestroy = 0;
1017     newInstance->onDestroy = 0;
1018     newInstance->onURLNotify = 0;
1019     newInstance->onSetWindow = 0;
1020     newInstance->logDestroy = FALSE;
1021     newInstance->logSetWindow = FALSE;
1022     newInstance->returnErrorFromNewStream = FALSE;
1023     newInstance->returnNegativeOneFromWrite = FALSE;
1024     newInstance->stream = 0;
1025
1026     newInstance->firstUrl = 0;
1027     newInstance->firstHeaders = 0;
1028     newInstance->lastUrl = 0;
1029     newInstance->lastHeaders = 0;
1030
1031     newInstance->testGetURLOnDestroy = FALSE;
1032     newInstance->testWindowOpen = FALSE;
1033     newInstance->testKeyboardFocusForPlugins = FALSE;
1034
1035     newInstance->mouseDownForEvaluateScript = FALSE;
1036     newInstance->evaluateScriptOnMouseDownOrKeyDown = 0;
1037
1038     return (NPObject*)newInstance;
1039 }
1040
1041 static void pluginDeallocate(NPObject* header)
1042 {
1043     PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
1044     delete plugin->pluginTest;
1045     if (plugin->testObject)
1046         browser->releaseobject(plugin->testObject);
1047     if (plugin->rememberedObject)
1048         browser->releaseobject(plugin->rememberedObject);
1049
1050     free(plugin->firstUrl);
1051     free(plugin->firstHeaders);
1052     free(plugin->lastUrl);
1053     free(plugin->lastHeaders);
1054     free(plugin);
1055 }
1056
1057 void handleCallback(PluginObject* object, const char *url, NPReason reason, void *notifyData)
1058 {
1059     assert(object);
1060
1061     NPVariant args[2];
1062
1063     NPObject* windowScriptObject;
1064     browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject);
1065
1066     NPIdentifier callbackIdentifier = notifyData;
1067
1068     INT32_TO_NPVARIANT(reason, args[0]);
1069
1070     char* strHdr = 0;
1071     if (object->firstUrl && object->firstHeaders && object->lastUrl && object->lastHeaders) {
1072         // Format expected by JavaScript validator: four fields separated by \n\n:
1073         // First URL; first header block; last URL; last header block.
1074         // Note that header blocks already end with \n due to how NPStream::headers works.
1075         int len = strlen(object->firstUrl) + 2
1076             + strlen(object->firstHeaders) + 1
1077             + strlen(object->lastUrl) + 2
1078             + strlen(object->lastHeaders) + 1;
1079         strHdr = (char*)malloc(len + 1);
1080         snprintf(strHdr, len + 1, "%s\n\n%s\n%s\n\n%s\n",
1081                  object->firstUrl, object->firstHeaders, object->lastUrl, object->lastHeaders);
1082         STRINGN_TO_NPVARIANT(strHdr, len, args[1]);
1083     } else
1084         NULL_TO_NPVARIANT(args[1]);
1085
1086     NPVariant browserResult;
1087     if (browser->invoke(object->npp, windowScriptObject, callbackIdentifier, args, 2, &browserResult))
1088         browser->releasevariantvalue(&browserResult);
1089
1090     free(strHdr);
1091 }
1092
1093 void notifyStream(PluginObject* object, const char *url, const char *headers)
1094 {
1095     if (!object->firstUrl) {
1096         if (url)
1097             object->firstUrl = strdup(url);
1098         if (headers)
1099             object->firstHeaders = strdup(headers);
1100     } else {
1101         free(object->lastUrl);
1102         free(object->lastHeaders);
1103         object->lastUrl = (url ? strdup(url) : 0);
1104         object->lastHeaders = (headers ? strdup(headers) : 0);
1105     }
1106 }
1107
1108 void testNPRuntime(NPP npp)
1109 {
1110     NPObject* windowScriptObject;
1111     browser->getvalue(npp, NPNVWindowNPObject, &windowScriptObject);
1112
1113     // Invoke
1114     NPIdentifier testNPInvoke = browser->getstringidentifier("testNPInvoke");
1115     NPVariant args[7];
1116     
1117     VOID_TO_NPVARIANT(args[0]);
1118     NULL_TO_NPVARIANT(args[1]);
1119     BOOLEAN_TO_NPVARIANT(true, args[2]);
1120     INT32_TO_NPVARIANT(242, args[3]);
1121     DOUBLE_TO_NPVARIANT(242.242, args[4]);
1122     STRINGZ_TO_NPVARIANT("Hello, World", args[5]);
1123     OBJECT_TO_NPVARIANT(windowScriptObject, args[6]);
1124     
1125     NPVariant result;
1126     if (browser->invoke(npp, windowScriptObject, testNPInvoke, args, 7, &result))
1127         browser->releasevariantvalue(&result);
1128     
1129     browser->releaseobject(windowScriptObject);
1130 }