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