diff options
author | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-19 23:33:01 +0000 |
---|---|---|
committer | tfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-19 23:33:01 +0000 |
commit | 7eb2cf4ef217ad37cb5ec07c626eef549ceaa964 (patch) | |
tree | 2484d5ab8eae032c82fb7d2358e6192000e6a6ea /content/shell/tools | |
parent | 0443652a79d75dc7bb76eab68c827b20a8b7d30b (diff) | |
download | chromium_src-7eb2cf4ef217ad37cb5ec07c626eef549ceaa964.zip chromium_src-7eb2cf4ef217ad37cb5ec07c626eef549ceaa964.tar.gz chromium_src-7eb2cf4ef217ad37cb5ec07c626eef549ceaa964.tar.bz2 |
content: Copy plugin code from Blink to Chromium.
This just copy the source files, no gyp changes at this moment, this
will come next.
BUG=331302
TEST=None
R=jochen@chromium.org
NOTRY=true
Review URL: https://codereview.chromium.org/135133003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245843 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/shell/tools')
35 files changed, 5240 insertions, 0 deletions
diff --git a/content/shell/tools/plugin/PluginObject.cpp b/content/shell/tools/plugin/PluginObject.cpp new file mode 100644 index 0000000..cb89fe4 --- /dev/null +++ b/content/shell/tools/plugin/PluginObject.cpp @@ -0,0 +1,1478 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2009 Holger Hans Peter Freyther + * Copyright (C) 2010 Collabora Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginObject.h" + +#include "PluginTest.h" +#include "TestObject.h" +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// Helper function which takes in the plugin window object for logging to the +// console object. +static void pluginLogWithWindowObject(NPObject* windowObject, + NPP instance, + const char* message) { + NPVariant consoleVariant; + if (!browser->getproperty(instance, + windowObject, + browser->getstringidentifier("console"), + &consoleVariant)) { + fprintf(stderr, + "Failed to retrieve console object while logging: %s\n", + message); + return; + } + + NPObject* consoleObject = NPVARIANT_TO_OBJECT(consoleVariant); + + NPVariant messageVariant; + STRINGZ_TO_NPVARIANT(message, messageVariant); + + NPVariant result; + if (!browser->invoke(instance, + consoleObject, + browser->getstringidentifier("log"), + &messageVariant, + 1, + &result)) { + fprintf( + stderr, "Failed to invoke console.log while logging: %s\n", message); + browser->releaseobject(consoleObject); + return; + } + + browser->releasevariantvalue(&result); + browser->releaseobject(consoleObject); +} + +void pluginLogWithArguments(NPP instance, const char* format, va_list args) { + const size_t messageBufferSize = 2048; + char message[messageBufferSize] = "PLUGIN: "; + int messageLength = sizeof("PLUGIN: ") - 1; + messageLength += vsnprintf(message + messageLength, + messageBufferSize - 1 - messageLength, + format, + args); + message[messageLength] = '\0'; + + NPObject* windowObject = 0; + NPError error = + browser->getvalue(instance, NPNVWindowNPObject, &windowObject); + if (error != NPERR_NO_ERROR) { + fprintf(stderr, + "Failed to retrieve window object while logging: %s\n", + message); + return; + } + + pluginLogWithWindowObject(windowObject, instance, message); + browser->releaseobject(windowObject); +} + +// Helper function to log to the console object. +void pluginLog(NPP instance, const char* format, ...) { + va_list args; + va_start(args, format); + pluginLogWithArguments(instance, format, args); + va_end(args); +} + +static void pluginInvalidate(NPObject*); +static bool pluginHasProperty(NPObject*, NPIdentifier name); +static bool pluginHasMethod(NPObject*, NPIdentifier name); +static bool pluginGetProperty(NPObject*, NPIdentifier name, NPVariant*); +static bool pluginSetProperty(NPObject*, NPIdentifier name, const NPVariant*); +static bool pluginInvoke(NPObject*, + NPIdentifier name, + const NPVariant* args, + uint32_t argCount, + NPVariant* result); +static NPObject* pluginAllocate(NPP npp, NPClass*); +static void pluginDeallocate(NPObject*); + +NPNetscapeFuncs* browser; +NPPluginFuncs* pluginFunctions; + +static NPClass pluginClass_ = { + NP_CLASS_STRUCT_VERSION, pluginAllocate, pluginDeallocate, + pluginInvalidate, pluginHasMethod, pluginInvoke, + 0, // NPClass::invokeDefault, + pluginHasProperty, pluginGetProperty, pluginSetProperty, + 0, // NPClass::removeProperty + 0, // NPClass::enumerate + 0, // NPClass::construct +}; + +NPClass* createPluginClass(void) { + NPClass* pluginClass = new NPClass; + *pluginClass = pluginClass_; + return pluginClass; +} + +static bool identifiersInitialized = false; + +enum { + ID_PROPERTY_PROPERTY = 0, + ID_PROPERTY_EVENT_LOGGING, + ID_PROPERTY_HAS_STREAM, + ID_PROPERTY_TEST_OBJECT, + ID_PROPERTY_LOG_DESTROY, + ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM, + ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE, + ID_PROPERTY_THROW_EXCEPTION_PROPERTY, + ID_LAST_SET_WINDOW_ARGUMENTS, + ID_PROPERTY_WINDOWED_PLUGIN, + ID_PROPERTY_TEST_OBJECT_COUNT, + ID_PROPERTY_DELETE_IN_GET_PROPERTY, + ID_PROPERTY_DELETE_IN_HAS_PROPERTY_RETURN_TRUE, + ID_PROPERTY_DELETE_IN_SET_PROPERTY, + NUM_PROPERTY_IDENTIFIERS +}; + +static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS]; +static const NPUTF8* pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = { + "property", "eventLoggingEnabled", + "hasStream", "testObject", + "logDestroy", "returnErrorFromNewStream", + "returnNegativeOneFromWrite", "testThrowExceptionProperty", + "lastSetWindowArguments", "windowedPlugin", + "testObjectCount", "deletePluginInGetProperty", + "deletePluginInHasPropertyReturnTrue", "deletePluginInSetProperty"}; + +enum { + ID_TEST_CALLBACK_METHOD = 0, + ID_TEST_CALLBACK_METHOD_RETURN, + ID_TEST_GETURL, + ID_TEST_DOM_ACCESS, + ID_TEST_GET_URL_NOTIFY, + ID_TEST_INVOKE_DEFAULT, + ID_DESTROY_STREAM, + ID_TEST_ENUMERATE, + ID_TEST_GETINTIDENTIFIER, + ID_TEST_GET_PROPERTY, + ID_TEST_HAS_PROPERTY, + ID_TEST_HAS_METHOD, + ID_TEST_EVALUATE, + ID_TEST_GET_PROPERTY_RETURN_VALUE, + ID_TEST_IDENTIFIER_TO_STRING, + ID_TEST_IDENTIFIER_TO_INT, + ID_TEST_PASS_TEST_OBJECT, + ID_TEST_POSTURL_FILE, + ID_TEST_CONSTRUCT, + ID_TEST_THROW_EXCEPTION_METHOD, + ID_TEST_FAIL_METHOD, + ID_TEST_CLONE_OBJECT, + ID_TEST_SCRIPT_OBJECT_INVOKE, + ID_TEST_CREATE_TEST_OBJECT, + ID_DESTROY_NULL_STREAM, + ID_TEST_RELOAD_PLUGINS_NO_PAGES, + ID_TEST_RELOAD_PLUGINS_AND_PAGES, + ID_TEST_GET_BROWSER_PROPERTY, + ID_TEST_SET_BROWSER_PROPERTY, + ID_REMEMBER, + ID_GET_REMEMBERED_OBJECT, + ID_GET_AND_FORGET_REMEMBERED_OBJECT, + ID_REF_COUNT, + ID_SET_STATUS, + ID_RESIZE_TO, + ID_NORMALIZE, + ID_INVALIDATE_RECT, + ID_OBJECTS_ARE_SAME, + ID_TEST_DELETE_WITHIN_INVOKE, + NUM_METHOD_IDENTIFIERS +}; + +static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS]; +static const NPUTF8* pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = { + "testCallback", "testCallbackReturn", + "getURL", "testDOMAccess", + "getURLNotify", "testInvokeDefault", + "destroyStream", "testEnumerate", + "testGetIntIdentifier", "testGetProperty", + "testHasProperty", "testHasMethod", + "testEvaluate", "testGetPropertyReturnValue", + "testIdentifierToString", "testIdentifierToInt", + "testPassTestObject", "testPostURLFile", + "testConstruct", "testThrowException", + "testFail", "testCloneObject", + "testScriptObjectInvoke", "testCreateTestObject", + "destroyNullStream", "reloadPluginsNoPages", + "reloadPluginsAndPages", "testGetBrowserProperty", + "testSetBrowserProperty", "remember", + "getRememberedObject", "getAndForgetRememberedObject", + "refCount", "setStatus", + "resizeTo", "normalize", + "invalidateRect", "objectsAreSame", + "testDeleteWithinInvoke"}; + +static NPUTF8* createCStringFromNPVariant(const NPVariant* variant) { + size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length; + NPUTF8* result = (NPUTF8*)malloc(length + 1); + memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length); + result[length] = '\0'; + return result; +} + +static void initializeIdentifiers(void) { + browser->getstringidentifiers(pluginPropertyIdentifierNames, + NUM_PROPERTY_IDENTIFIERS, + pluginPropertyIdentifiers); + browser->getstringidentifiers(pluginMethodIdentifierNames, + NUM_METHOD_IDENTIFIERS, + pluginMethodIdentifiers); +} + +static bool callDeletePlugin(NPObject* obj, + NPIdentifier name, + NPIdentifier identifierToMatch) { + if (name != identifierToMatch) + return false; + + PluginObject* plugin = reinterpret_cast<PluginObject*>(obj); + NPObject* windowScriptObject; + browser->getvalue(plugin->npp, NPNVWindowNPObject, &windowScriptObject); + + NPIdentifier callbackIdentifier = + browser->getstringidentifier("deletePlugin"); + NPVariant browserResult; + if (browser->invoke(plugin->npp, + windowScriptObject, + callbackIdentifier, + 0, + 0, + &browserResult)) + browser->releasevariantvalue(&browserResult); + return true; +} + +static bool pluginHasProperty(NPObject* obj, NPIdentifier name) { + if (callDeletePlugin( + obj, + name, + browser->getstringidentifier("deletePluginInHasPropertyReturnFalse"))) + return false; + + callDeletePlugin(obj, + name, + pluginPropertyIdentifiers + [ID_PROPERTY_DELETE_IN_HAS_PROPERTY_RETURN_TRUE]); + + for (int i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++) + if (name == pluginPropertyIdentifiers[i]) + return true; + return false; +} + +static bool pluginHasMethod(NPObject* obj, NPIdentifier name) { + if (callDeletePlugin( + obj, name, browser->getstringidentifier("deletePluginInHasMethod"))) + return true; + + for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++) + if (name == pluginMethodIdentifiers[i]) + return true; + return false; +} + +static bool pluginGetProperty(NPObject* obj, + NPIdentifier name, + NPVariant* result) { + PluginObject* plugin = reinterpret_cast<PluginObject*>(obj); + if (name == pluginPropertyIdentifiers[ID_PROPERTY_PROPERTY]) { + static const char* originalString = "property"; + char* buf = + static_cast<char*>(browser->memalloc(strlen(originalString) + 1)); + strcpy(buf, originalString); + STRINGZ_TO_NPVARIANT(buf, *result); + return true; + } + if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) { + BOOLEAN_TO_NPVARIANT(plugin->eventLogging, *result); + return true; + } + if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) { + BOOLEAN_TO_NPVARIANT(plugin->logDestroy, *result); + return true; + } + if (name == pluginPropertyIdentifiers[ID_PROPERTY_HAS_STREAM]) { + BOOLEAN_TO_NPVARIANT(plugin->stream, *result); + return true; + } + if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT]) { + NPObject* testObject = plugin->testObject; + browser->retainobject(testObject); + OBJECT_TO_NPVARIANT(testObject, *result); + return true; + } + if (name == + pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) { + BOOLEAN_TO_NPVARIANT(plugin->returnErrorFromNewStream, *result); + return true; + } + if (name == + pluginPropertyIdentifiers[ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE]) { + BOOLEAN_TO_NPVARIANT(plugin->returnNegativeOneFromWrite, *result); + return true; + } + if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PROPERTY]) { + browser->setexception(obj, + "plugin object testThrowExceptionProperty SUCCESS"); + return true; + } + if (name == pluginPropertyIdentifiers[ID_LAST_SET_WINDOW_ARGUMENTS]) { + char* buf = static_cast<char*>(browser->memalloc(256)); + 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, + plugin->lastWindow.clipRect.left, + plugin->lastWindow.clipRect.top, + plugin->lastWindow.clipRect.right - plugin->lastWindow.clipRect.left, + plugin->lastWindow.clipRect.bottom - plugin->lastWindow.clipRect.top); + + STRINGZ_TO_NPVARIANT(buf, *result); + return true; + } + if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT_COUNT]) { + INT32_TO_NPVARIANT(getTestObjectCount(), *result); + return true; + } + + if (name == pluginPropertyIdentifiers[ID_PROPERTY_DELETE_IN_GET_PROPERTY]) { + browser->retainobject(obj); + callDeletePlugin( + obj, + name, + pluginPropertyIdentifiers[ID_PROPERTY_DELETE_IN_GET_PROPERTY]); + NPObject* testObject = plugin->testObject; + browser->retainobject(testObject); + OBJECT_TO_NPVARIANT(testObject, *result); + browser->releaseobject(obj); + return true; + } + + return false; +} + +static bool pluginSetProperty(NPObject* obj, + NPIdentifier name, + const NPVariant* variant) { + PluginObject* plugin = reinterpret_cast<PluginObject*>(obj); + if (callDeletePlugin( + obj, + name, + pluginPropertyIdentifiers[ID_PROPERTY_DELETE_IN_SET_PROPERTY])) + return true; + + if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) { + plugin->eventLogging = NPVARIANT_TO_BOOLEAN(*variant); + return true; + } + if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) { + plugin->logDestroy = NPVARIANT_TO_BOOLEAN(*variant); + return true; + } + if (name == + pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) { + plugin->returnErrorFromNewStream = NPVARIANT_TO_BOOLEAN(*variant); + return true; + } + if (name == + pluginPropertyIdentifiers[ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE]) { + plugin->returnNegativeOneFromWrite = NPVARIANT_TO_BOOLEAN(*variant); + return true; + } + if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PROPERTY]) { + browser->setexception(obj, + "plugin object testThrowExceptionProperty SUCCESS"); + return true; + } + if (name == pluginPropertyIdentifiers[ID_PROPERTY_WINDOWED_PLUGIN]) { + browser->setvalue(plugin->npp, + NPPVpluginWindowBool, + (void*)NPVARIANT_TO_BOOLEAN(*variant)); + return true; + } + + return false; +} + +static bool testDOMAccess(PluginObject* obj, + const NPVariant*, + uint32_t, + NPVariant* result) { + // Get plug-in's DOM element + NPObject* elementObject; + if (browser->getvalue(obj->npp, NPNVPluginElementNPObject, &elementObject) == + NPERR_NO_ERROR) { + // Get style + NPVariant styleVariant; + NPIdentifier styleIdentifier = browser->getstringidentifier("style"); + if (browser->getproperty( + obj->npp, elementObject, styleIdentifier, &styleVariant) && + NPVARIANT_IS_OBJECT(styleVariant)) { + // Set style.border + NPIdentifier borderIdentifier = browser->getstringidentifier("border"); + NPVariant borderVariant; + STRINGZ_TO_NPVARIANT("3px solid red", borderVariant); + browser->setproperty(obj->npp, + NPVARIANT_TO_OBJECT(styleVariant), + borderIdentifier, + &borderVariant); + browser->releasevariantvalue(&styleVariant); + } + + browser->releaseobject(elementObject); + } + VOID_TO_NPVARIANT(*result); + return true; +} + +static NPIdentifier stringVariantToIdentifier(NPVariant variant) { + assert(NPVARIANT_IS_STRING(variant)); + NPUTF8* utf8String = createCStringFromNPVariant(&variant); + NPIdentifier identifier = browser->getstringidentifier(utf8String); + free(utf8String); + return identifier; +} + +static NPIdentifier int32VariantToIdentifier(NPVariant variant) { + assert(NPVARIANT_IS_INT32(variant)); + int32_t integer = NPVARIANT_TO_INT32(variant); + return browser->getintidentifier(integer); +} + +static NPIdentifier doubleVariantToIdentifier(NPVariant variant) { + assert(NPVARIANT_IS_DOUBLE(variant)); + double value = NPVARIANT_TO_DOUBLE(variant); + // Sadly there is no "getdoubleidentifier" + int32_t integer = static_cast<int32_t>(value); + return browser->getintidentifier(integer); +} + +static NPIdentifier variantToIdentifier(NPVariant variant) { + if (NPVARIANT_IS_STRING(variant)) + return stringVariantToIdentifier(variant); + if (NPVARIANT_IS_INT32(variant)) + return int32VariantToIdentifier(variant); + if (NPVARIANT_IS_DOUBLE(variant)) + return doubleVariantToIdentifier(variant); + return 0; +} + +static bool testIdentifierToString(PluginObject*, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 1) + return true; + NPIdentifier identifier = variantToIdentifier(args[0]); + if (!identifier) + return true; + NPUTF8* utf8String = browser->utf8fromidentifier(identifier); + if (!utf8String) + return true; + STRINGZ_TO_NPVARIANT(utf8String, *result); + return true; +} + +static bool testIdentifierToInt(PluginObject*, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 1) + return false; + NPIdentifier identifier = variantToIdentifier(args[0]); + if (!identifier) + return false; + int32_t integer = browser->intfromidentifier(identifier); + INT32_TO_NPVARIANT(integer, *result); + return true; +} + +static bool testPassTestObject(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 2 || !NPVARIANT_IS_STRING(args[0])) + return false; + + NPObject* windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + NPUTF8* callbackString = createCStringFromNPVariant(&args[0]); + NPIdentifier callbackIdentifier = + browser->getstringidentifier(callbackString); + free(callbackString); + + NPVariant browserResult; + browser->invoke(obj->npp, + windowScriptObject, + callbackIdentifier, + &args[1], + 1, + &browserResult); + browser->releasevariantvalue(&browserResult); + + VOID_TO_NPVARIANT(*result); + return true; +} + +static bool testCallback(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (!argCount || !NPVARIANT_IS_STRING(args[0])) + return false; + + NPObject* windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + NPUTF8* callbackString = createCStringFromNPVariant(&args[0]); + NPIdentifier callbackIdentifier = + browser->getstringidentifier(callbackString); + free(callbackString); + + NPVariant browserResult; + if (browser->invoke(obj->npp, + windowScriptObject, + callbackIdentifier, + 0, + 0, + &browserResult)) + browser->releasevariantvalue(&browserResult); + + browser->releaseobject(windowScriptObject); + + VOID_TO_NPVARIANT(*result); + return true; +} + +static bool testCallbackReturn(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 1 || !NPVARIANT_IS_STRING(args[0])) + return false; + + NPObject* windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + NPUTF8* callbackString = createCStringFromNPVariant(&args[0]); + NPIdentifier callbackIdentifier = + browser->getstringidentifier(callbackString); + free(callbackString); + + NPVariant callbackArgs[1]; + OBJECT_TO_NPVARIANT(windowScriptObject, callbackArgs[0]); + + NPVariant browserResult; + browser->invoke(obj->npp, + windowScriptObject, + callbackIdentifier, + callbackArgs, + 1, + &browserResult); + + if (NPVARIANT_IS_OBJECT(browserResult)) + OBJECT_TO_NPVARIANT(NPVARIANT_TO_OBJECT(browserResult), *result); + else { + browser->releasevariantvalue(&browserResult); + VOID_TO_NPVARIANT(*result); + } + + return true; +} + +static bool getURL(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount == 2 && NPVARIANT_IS_STRING(args[0]) && + NPVARIANT_IS_STRING(args[1])) { + NPUTF8* urlString = createCStringFromNPVariant(&args[0]); + NPUTF8* targetString = createCStringFromNPVariant(&args[1]); + NPError npErr = browser->geturl(obj->npp, urlString, targetString); + free(urlString); + free(targetString); + + INT32_TO_NPVARIANT(npErr, *result); + return true; + } + if (argCount == 1 && NPVARIANT_IS_STRING(args[0])) { + NPUTF8* urlString = createCStringFromNPVariant(&args[0]); + NPError npErr = browser->geturl(obj->npp, urlString, 0); + free(urlString); + + INT32_TO_NPVARIANT(npErr, *result); + return true; + } + return false; +} + +static bool getURLNotify(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 3 || !NPVARIANT_IS_STRING(args[0]) || + (!NPVARIANT_IS_STRING(args[1]) && !NPVARIANT_IS_NULL(args[1])) || + !NPVARIANT_IS_STRING(args[2])) + return false; + + NPUTF8* urlString = createCStringFromNPVariant(&args[0]); + NPUTF8* targetString = + (NPVARIANT_IS_STRING(args[1]) ? createCStringFromNPVariant(&args[1]) : 0); + NPUTF8* callbackString = createCStringFromNPVariant(&args[2]); + + NPIdentifier callbackIdentifier = + browser->getstringidentifier(callbackString); + browser->geturlnotify(obj->npp, urlString, targetString, callbackIdentifier); + + free(urlString); + free(targetString); + free(callbackString); + + VOID_TO_NPVARIANT(*result); + return true; +} + +static bool testInvokeDefault(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (!NPVARIANT_IS_OBJECT(args[0])) + return false; + + NPObject* callback = NPVARIANT_TO_OBJECT(args[0]); + + NPVariant invokeArgs[1]; + NPVariant browserResult; + + STRINGZ_TO_NPVARIANT("test", invokeArgs[0]); + bool retval = + browser->invokeDefault(obj->npp, callback, invokeArgs, 1, &browserResult); + + if (retval) + browser->releasevariantvalue(&browserResult); + + BOOLEAN_TO_NPVARIANT(retval, *result); + return true; +} + +static bool destroyStream(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + NPError npError = + browser->destroystream(obj->npp, obj->stream, NPRES_USER_BREAK); + INT32_TO_NPVARIANT(npError, *result); + return true; +} + +static bool destroyNullStream(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + NPError npError = browser->destroystream(obj->npp, 0, NPRES_USER_BREAK); + INT32_TO_NPVARIANT(npError, *result); + return true; +} + +static bool testEnumerate(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || + !NPVARIANT_IS_OBJECT(args[1])) + return false; + + uint32_t count; + NPIdentifier* identifiers; + if (browser->enumerate( + obj->npp, NPVARIANT_TO_OBJECT(args[0]), &identifiers, &count)) { + NPObject* outArray = NPVARIANT_TO_OBJECT(args[1]); + NPIdentifier pushIdentifier = browser->getstringidentifier("push"); + + for (uint32_t i = 0; i < count; i++) { + NPUTF8* string = browser->utf8fromidentifier(identifiers[i]); + + if (!string) + continue; + + NPVariant args[1]; + STRINGZ_TO_NPVARIANT(string, args[0]); + NPVariant browserResult; + if (browser->invoke( + obj->npp, outArray, pushIdentifier, args, 1, &browserResult)) + browser->releasevariantvalue(&browserResult); + browser->memfree(string); + } + + browser->memfree(identifiers); + } + + VOID_TO_NPVARIANT(*result); + return true; +} + +static bool testGetIntIdentifier(PluginObject*, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 1 || !NPVARIANT_IS_DOUBLE(args[0])) + return false; + + NPIdentifier identifier = + browser->getintidentifier((int)NPVARIANT_TO_DOUBLE(args[0])); + INT32_TO_NPVARIANT((int32_t)(long long)identifier, *result); + return true; +} + +static bool testGetProperty(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (!argCount) + return false; + + NPObject* object; + browser->getvalue(obj->npp, NPNVWindowNPObject, &object); + + for (uint32_t i = 0; i < argCount; i++) { + assert(NPVARIANT_IS_STRING(args[i])); + NPUTF8* propertyString = createCStringFromNPVariant(&args[i]); + NPIdentifier propertyIdentifier = + browser->getstringidentifier(propertyString); + free(propertyString); + + NPVariant variant; + bool retval = + browser->getproperty(obj->npp, object, propertyIdentifier, &variant); + browser->releaseobject(object); + + if (!retval) + break; + + if (i + 1 < argCount) { + assert(NPVARIANT_IS_OBJECT(variant)); + object = NPVARIANT_TO_OBJECT(variant); + } else { + *result = variant; + return true; + } + } + + VOID_TO_NPVARIANT(*result); + return false; +} + +static bool testHasProperty(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || + !NPVARIANT_IS_STRING(args[1])) + return false; + + NPUTF8* propertyString = createCStringFromNPVariant(&args[1]); + NPIdentifier propertyIdentifier = + browser->getstringidentifier(propertyString); + free(propertyString); + + bool retval = browser->hasproperty( + obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier); + + BOOLEAN_TO_NPVARIANT(retval, *result); + return true; +} + +static bool testHasMethod(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || + !NPVARIANT_IS_STRING(args[1])) + return false; + + NPUTF8* propertyString = createCStringFromNPVariant(&args[1]); + NPIdentifier propertyIdentifier = + browser->getstringidentifier(propertyString); + free(propertyString); + + bool retval = browser->hasmethod( + obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier); + + BOOLEAN_TO_NPVARIANT(retval, *result); + return true; +} + +static bool testEvaluate(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 1 || !NPVARIANT_IS_STRING(args[0])) + return false; + NPObject* windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + NPString s = NPVARIANT_TO_STRING(args[0]); + + bool retval = browser->evaluate(obj->npp, windowScriptObject, &s, result); + browser->releaseobject(windowScriptObject); + return retval; +} + +static bool testGetPropertyReturnValue(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || + !NPVARIANT_IS_STRING(args[1])) + return false; + + NPUTF8* propertyString = createCStringFromNPVariant(&args[1]); + NPIdentifier propertyIdentifier = + browser->getstringidentifier(propertyString); + free(propertyString); + + NPVariant variant; + bool retval = browser->getproperty( + obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier, &variant); + if (retval) + browser->releasevariantvalue(&variant); + + BOOLEAN_TO_NPVARIANT(retval, *result); + return true; +} + +static char* toCString(const NPString& string) { + char* result = static_cast<char*>(malloc(string.UTF8Length + 1)); + memcpy(result, string.UTF8Characters, string.UTF8Length); + result[string.UTF8Length] = '\0'; + + return result; +} + +static bool testPostURLFile(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 4 || !NPVARIANT_IS_STRING(args[0]) || + !NPVARIANT_IS_STRING(args[1]) || !NPVARIANT_IS_STRING(args[2]) || + !NPVARIANT_IS_STRING(args[3])) + return false; + + NPString urlString = NPVARIANT_TO_STRING(args[0]); + char* url = toCString(urlString); + + NPString targetString = NPVARIANT_TO_STRING(args[1]); + char* target = toCString(targetString); + + NPString pathString = NPVARIANT_TO_STRING(args[2]); + char* path = toCString(pathString); + + NPString contentsString = NPVARIANT_TO_STRING(args[3]); + + FILE* tempFile = fopen(path, "w"); + if (!tempFile) + return false; + + size_t written = fwrite( + contentsString.UTF8Characters, contentsString.UTF8Length, 1, tempFile); + fclose(tempFile); + if (!written) + return false; + + NPError error = browser->posturl( + obj->npp, url, target, pathString.UTF8Length, path, true); + + free(path); + free(target); + free(url); + + BOOLEAN_TO_NPVARIANT(error == NPERR_NO_ERROR, *result); + return true; +} + +static bool testConstruct(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (!argCount || !NPVARIANT_IS_OBJECT(args[0])) + return false; + + return browser->construct( + obj->npp, NPVARIANT_TO_OBJECT(args[0]), args + 1, argCount - 1, result); +} + +// Invoke a script callback to get a script NPObject. Then call a method on the +// script NPObject passing it a freshly created NPObject. +static bool testScriptObjectInvoke(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 2 || !NPVARIANT_IS_STRING(args[0]) || + !NPVARIANT_IS_STRING(args[1])) + return false; + NPObject* windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + // Arg1 is the name of the callback + NPUTF8* callbackString = createCStringFromNPVariant(&args[0]); + NPIdentifier callbackIdentifier = + browser->getstringidentifier(callbackString); + free(callbackString); + + // Invoke a callback that returns a script object + NPVariant object_result; + browser->invoke(obj->npp, + windowScriptObject, + callbackIdentifier, + &args[1], + 1, + &object_result); + + // Script object returned + NPObject* script_object = object_result.value.objectValue; + + // Arg2 is the name of the method to be called on the script object + NPUTF8* object_mehod_string = createCStringFromNPVariant(&args[1]); + NPIdentifier object_method = + browser->getstringidentifier(object_mehod_string); + free(object_mehod_string); + + // Create a fresh NPObject to be passed as an argument + NPObject* object_arg = browser->createobject(obj->npp, obj->header._class); + + NPVariant invoke_args[1]; + OBJECT_TO_NPVARIANT(object_arg, invoke_args[0]); + + // Invoke the script method + NPVariant object_method_result; + browser->invoke(obj->npp, + script_object, + object_method, + invoke_args, + 1, + &object_method_result); + + browser->releasevariantvalue(&object_result); + VOID_TO_NPVARIANT(*result); + if (NPVARIANT_IS_OBJECT(object_method_result)) { + // Now return the callbacks return value back to our caller. + // BUG 897451: This should be the same as the + // windowScriptObject, but its not (in Chrome) - or at least, it + // has a different refcount. This means Chrome will delete the + // object before returning it and the calling JS gets a garbage + // value. Firefox handles it fine. + OBJECT_TO_NPVARIANT(NPVARIANT_TO_OBJECT(object_method_result), *result); + } else { + browser->releasevariantvalue(&object_method_result); + VOID_TO_NPVARIANT(*result); + } + + browser->releaseobject(object_arg); + + return true; +} + +// Helper function to notify the layout test controller that the test completed. +void notifyTestCompletion(NPP npp, NPObject* object) { + NPVariant result; + NPString script; + script.UTF8Characters = "javascript:window.testRunner.notifyDone();"; + script.UTF8Length = strlen("javascript:window.testRunner.notifyDone();"); + browser->evaluate(npp, object, &script, &result); + browser->releasevariantvalue(&result); +} + +bool testDocumentOpen(NPP npp) { + NPIdentifier documentId = browser->getstringidentifier("document"); + NPIdentifier openId = browser->getstringidentifier("open"); + + NPObject* windowObject = 0; + browser->getvalue(npp, NPNVWindowNPObject, &windowObject); + if (!windowObject) + return false; + + NPVariant docVariant; + browser->getproperty(npp, windowObject, documentId, &docVariant); + if (docVariant.type != NPVariantType_Object) { + browser->releaseobject(windowObject); + return false; + } + + NPObject* documentObject = NPVARIANT_TO_OBJECT(docVariant); + + NPVariant openArgs[2]; + STRINGZ_TO_NPVARIANT("text/html", openArgs[0]); + STRINGZ_TO_NPVARIANT("_blank", openArgs[1]); + + NPVariant result; + if (!browser->invoke(npp, documentObject, openId, openArgs, 2, &result)) { + browser->releaseobject(windowObject); + browser->releaseobject(documentObject); + return false; + } + + browser->releaseobject(documentObject); + + if (result.type != NPVariantType_Object) { + browser->releaseobject(windowObject); + browser->releasevariantvalue(&result); + return false; + } + + pluginLogWithWindowObject(windowObject, npp, "PLUGIN: DOCUMENT OPEN SUCCESS"); + notifyTestCompletion(npp, result.value.objectValue); + browser->releaseobject(result.value.objectValue); + browser->releaseobject(windowObject); + return true; +} + +bool testWindowOpen(NPP npp) { + NPIdentifier openId = browser->getstringidentifier("open"); + + NPObject* windowObject = 0; + browser->getvalue(npp, NPNVWindowNPObject, &windowObject); + if (!windowObject) + return false; + + NPVariant openArgs[2]; + STRINGZ_TO_NPVARIANT("about:blank", openArgs[0]); + STRINGZ_TO_NPVARIANT("_blank", openArgs[1]); + + NPVariant result; + if (!browser->invoke(npp, windowObject, openId, openArgs, 2, &result)) { + browser->releaseobject(windowObject); + return false; + } + + if (result.type != NPVariantType_Object) { + browser->releaseobject(windowObject); + browser->releasevariantvalue(&result); + return false; + } + + pluginLogWithWindowObject(windowObject, npp, "PLUGIN: WINDOW OPEN SUCCESS"); + notifyTestCompletion(npp, result.value.objectValue); + browser->releaseobject(result.value.objectValue); + browser->releaseobject(windowObject); + return true; +} + +static bool testSetStatus(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + char* message = 0; + if (argCount && NPVARIANT_IS_STRING(args[0])) { + NPString statusString = NPVARIANT_TO_STRING(args[0]); + message = toCString(statusString); + } + + browser->status(obj->npp, message); + + free(message); + return true; +} + +static bool testResizeTo(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + VOID_TO_NPVARIANT(*result); + + NPObject* windowObject; + if (NPERR_NO_ERROR != + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowObject)) + return false; + + NPVariant callResult; + if (browser->invoke(obj->npp, + windowObject, + browser->getstringidentifier("resizePlugin"), + args, + argCount, + &callResult)) + browser->releasevariantvalue(&callResult); + + // Force layout. + if (browser->getproperty(obj->npp, + windowObject, + browser->getstringidentifier("pageYOffset"), + &callResult)) + browser->releasevariantvalue(&callResult); + + return true; +} + +static bool normalizeOverride(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + VOID_TO_NPVARIANT(*result); + + NPObject* windowObject; + if (NPERR_NO_ERROR != + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowObject)) + return false; + + NPVariant callResult; + if (browser->invoke(obj->npp, + windowObject, + browser->getstringidentifier("pluginCallback"), + args, + argCount, + &callResult)) + browser->releasevariantvalue(&callResult); + + return true; +} + +static bool invalidateRect(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 4) + return false; + + NPRect rect; + rect.left = static_cast<int>(NPVARIANT_TO_DOUBLE(args[0])); + rect.top = static_cast<int>(NPVARIANT_TO_DOUBLE(args[1])); + rect.right = static_cast<int>(NPVARIANT_TO_DOUBLE(args[2])); + rect.bottom = static_cast<int>(NPVARIANT_TO_DOUBLE(args[3])); + + browser->invalidaterect(obj->npp, &rect); + return true; +} + +static bool objectsAreSame(PluginObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || + !NPVARIANT_IS_OBJECT(args[1])) + return false; + + BOOLEAN_TO_NPVARIANT( + NPVARIANT_TO_OBJECT(args[0]) == NPVARIANT_TO_OBJECT(args[1]), *result); + return true; +} + +static bool pluginInvoke(NPObject* header, + NPIdentifier name, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + PluginObject* plugin = reinterpret_cast<PluginObject*>(header); + if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD]) + return testCallback(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD_RETURN]) + return testCallbackReturn(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_GETURL]) + return getURL(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_DOM_ACCESS]) + return testDOMAccess(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_GET_URL_NOTIFY]) + return getURLNotify(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_INVOKE_DEFAULT]) + return testInvokeDefault(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_ENUMERATE]) + return testEnumerate(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_DESTROY_STREAM]) + return destroyStream(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_GETINTIDENTIFIER]) + return testGetIntIdentifier(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_EVALUATE]) + return testEvaluate(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY]) + return testGetProperty(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY_RETURN_VALUE]) + return testGetPropertyReturnValue(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_HAS_PROPERTY]) + return testHasProperty(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_HAS_METHOD]) + return testHasMethod(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_STRING]) + return testIdentifierToString(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_INT]) + return testIdentifierToInt(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_PASS_TEST_OBJECT]) + return testPassTestObject(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_POSTURL_FILE]) + return testPostURLFile(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_CONSTRUCT]) + return testConstruct(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_SCRIPT_OBJECT_INVOKE]) + return testScriptObjectInvoke(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_THROW_EXCEPTION_METHOD]) { + browser->setexception(header, "plugin object testThrowException SUCCESS"); + return true; + } + if (name == pluginMethodIdentifiers[ID_TEST_FAIL_METHOD]) { + NPObject* windowScriptObject; + browser->getvalue(plugin->npp, NPNVWindowNPObject, &windowScriptObject); + browser->invoke( + plugin->npp, windowScriptObject, name, args, argCount, result); + return false; + } + if (name == pluginMethodIdentifiers[ID_TEST_CLONE_OBJECT]) { + NPObject* new_object = + browser->createobject(plugin->npp, plugin->header._class); + assert(new_object->referenceCount == 1); + OBJECT_TO_NPVARIANT(new_object, *result); + return true; + } + if (name == pluginMethodIdentifiers[ID_TEST_CREATE_TEST_OBJECT]) { + NPObject* testObject = browser->createobject(plugin->npp, getTestClass()); + assert(testObject->referenceCount == 1); + OBJECT_TO_NPVARIANT(testObject, *result); + return true; + } + if (name == pluginMethodIdentifiers[ID_DESTROY_NULL_STREAM]) + return destroyNullStream(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_RELOAD_PLUGINS_NO_PAGES]) { + browser->reloadplugins(false); + return true; + } + if (name == pluginMethodIdentifiers[ID_TEST_RELOAD_PLUGINS_AND_PAGES]) { + browser->reloadplugins(true); + return true; + } + if (name == pluginMethodIdentifiers[ID_TEST_GET_BROWSER_PROPERTY]) { + browser->getproperty(plugin->npp, + NPVARIANT_TO_OBJECT(args[0]), + stringVariantToIdentifier(args[1]), + result); + return true; + } + if (name == pluginMethodIdentifiers[ID_TEST_SET_BROWSER_PROPERTY]) { + browser->setproperty(plugin->npp, + NPVARIANT_TO_OBJECT(args[0]), + stringVariantToIdentifier(args[1]), + &args[2]); + return true; + } + if (name == pluginMethodIdentifiers[ID_REMEMBER]) { + if (plugin->rememberedObject) + browser->releaseobject(plugin->rememberedObject); + plugin->rememberedObject = NPVARIANT_TO_OBJECT(args[0]); + browser->retainobject(plugin->rememberedObject); + VOID_TO_NPVARIANT(*result); + return true; + } + if (name == pluginMethodIdentifiers[ID_GET_REMEMBERED_OBJECT]) { + assert(plugin->rememberedObject); + browser->retainobject(plugin->rememberedObject); + OBJECT_TO_NPVARIANT(plugin->rememberedObject, *result); + return true; + } + if (name == pluginMethodIdentifiers[ID_GET_AND_FORGET_REMEMBERED_OBJECT]) { + assert(plugin->rememberedObject); + OBJECT_TO_NPVARIANT(plugin->rememberedObject, *result); + plugin->rememberedObject = 0; + return true; + } + if (name == pluginMethodIdentifiers[ID_REF_COUNT]) { + uint32_t refCount = NPVARIANT_TO_OBJECT(args[0])->referenceCount; + INT32_TO_NPVARIANT(refCount, *result); + return true; + } + if (name == pluginMethodIdentifiers[ID_SET_STATUS]) + return testSetStatus(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_RESIZE_TO]) + return testResizeTo(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_NORMALIZE]) + return normalizeOverride(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_INVALIDATE_RECT]) + return invalidateRect(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_OBJECTS_ARE_SAME]) + return objectsAreSame(plugin, args, argCount, result); + if (name == pluginMethodIdentifiers[ID_TEST_DELETE_WITHIN_INVOKE]) { + NPObject* newObject = + browser->createobject(plugin->npp, plugin->header._class); + OBJECT_TO_NPVARIANT(newObject, *result); + callDeletePlugin( + header, name, pluginMethodIdentifiers[ID_TEST_DELETE_WITHIN_INVOKE]); + return true; + } + return false; +} + +static void pluginInvalidate(NPObject* header) { + PluginObject* plugin = reinterpret_cast<PluginObject*>(header); + plugin->testObject = 0; + plugin->rememberedObject = 0; +} + +static NPObject* pluginAllocate(NPP npp, NPClass* theClass) { + PluginObject* newInstance = (PluginObject*)malloc(sizeof(PluginObject)); + + if (!identifiersInitialized) { + identifiersInitialized = true; + initializeIdentifiers(); + } + + newInstance->pluginTest = 0; + newInstance->npp = npp; + newInstance->testObject = browser->createobject(npp, getTestClass()); + newInstance->rememberedObject = 0; + newInstance->eventLogging = false; + newInstance->onStreamLoad = 0; + newInstance->onStreamDestroy = 0; + newInstance->onDestroy = 0; + newInstance->onURLNotify = 0; + newInstance->onSetWindow = 0; + newInstance->onPaintEvent = 0; + newInstance->logDestroy = false; + newInstance->logSetWindow = false; + newInstance->returnErrorFromNewStream = false; + newInstance->returnNegativeOneFromWrite = false; + newInstance->stream = 0; + + newInstance->firstUrl = 0; + newInstance->firstHeaders = 0; + newInstance->lastUrl = 0; + newInstance->lastHeaders = 0; + + newInstance->testGetURLOnDestroy = false; + newInstance->testWindowOpen = false; + newInstance->testKeyboardFocusForPlugins = false; + + newInstance->mouseDownForEvaluateScript = false; + newInstance->evaluateScriptOnMouseDownOrKeyDown = 0; + + return (NPObject*)newInstance; +} + +static void pluginDeallocate(NPObject* header) { + PluginObject* plugin = reinterpret_cast<PluginObject*>(header); + delete plugin->pluginTest; + if (plugin->testObject) + browser->releaseobject(plugin->testObject); + if (plugin->rememberedObject) + browser->releaseobject(plugin->rememberedObject); + + free(plugin->firstUrl); + free(plugin->firstHeaders); + free(plugin->lastUrl); + free(plugin->lastHeaders); + free(plugin); +} + +void handleCallback(PluginObject* object, + const char* url, + NPReason reason, + void* notifyData) { + assert(object); + + NPVariant args[2]; + + NPObject* windowScriptObject; + browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject); + + NPIdentifier callbackIdentifier = notifyData; + + INT32_TO_NPVARIANT(reason, args[0]); + + char* strHdr = 0; + if (object->firstUrl && object->firstHeaders && object->lastUrl && + object->lastHeaders) { + // Format expected by JavaScript validator: four fields separated by \n\n: + // First URL; first header block; last URL; last header block. + // Note that header blocks already end with \n due to how NPStream::headers + // works. + int len = strlen(object->firstUrl) + 2 + strlen(object->firstHeaders) + 1 + + strlen(object->lastUrl) + 2 + strlen(object->lastHeaders) + 1; + strHdr = (char*)malloc(len + 1); + snprintf(strHdr, + len + 1, + "%s\n\n%s\n%s\n\n%s\n", + object->firstUrl, + object->firstHeaders, + object->lastUrl, + object->lastHeaders); + STRINGN_TO_NPVARIANT(strHdr, len, args[1]); + } else + NULL_TO_NPVARIANT(args[1]); + + NPVariant browserResult; + if (browser->invoke(object->npp, + windowScriptObject, + callbackIdentifier, + args, + 2, + &browserResult)) + browser->releasevariantvalue(&browserResult); + + free(strHdr); +} + +void notifyStream(PluginObject* object, const char* url, const char* headers) { + if (!object->firstUrl) { + if (url) + object->firstUrl = strdup(url); + if (headers) + object->firstHeaders = strdup(headers); + } else { + free(object->lastUrl); + free(object->lastHeaders); + object->lastUrl = (url ? strdup(url) : 0); + object->lastHeaders = (headers ? strdup(headers) : 0); + } +} + +void testNPRuntime(NPP npp) { + NPObject* windowScriptObject; + browser->getvalue(npp, NPNVWindowNPObject, &windowScriptObject); + + // Invoke + NPIdentifier testNPInvoke = browser->getstringidentifier("testNPInvoke"); + NPVariant args[7]; + + VOID_TO_NPVARIANT(args[0]); + NULL_TO_NPVARIANT(args[1]); + BOOLEAN_TO_NPVARIANT(true, args[2]); + INT32_TO_NPVARIANT(242, args[3]); + DOUBLE_TO_NPVARIANT(242.242, args[4]); + STRINGZ_TO_NPVARIANT("Hello, World", args[5]); + OBJECT_TO_NPVARIANT(windowScriptObject, args[6]); + + NPVariant result; + if (browser->invoke(npp, windowScriptObject, testNPInvoke, args, 7, &result)) + browser->releasevariantvalue(&result); + + browser->releaseobject(windowScriptObject); +} diff --git a/content/shell/tools/plugin/PluginObject.h b/content/shell/tools/plugin/PluginObject.h new file mode 100644 index 0000000..2d53c24 --- /dev/null +++ b/content/shell/tools/plugin/PluginObject.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PluginObject_h +#define PluginObject_h + +#include <bindings/npfunctions.h> +#include <stdarg.h> + +class PluginTest; + +extern NPNetscapeFuncs *browser; +extern NPPluginFuncs* pluginFunctions; + +typedef struct { + NPObject header; + + PluginTest* pluginTest; + + NPP npp; + NPBool eventLogging; + NPBool logSetWindow; + NPBool logDestroy; + NPBool returnNegativeOneFromWrite; + NPBool returnErrorFromNewStream; + NPObject* testObject; + NPObject* rememberedObject; + NPStream* stream; + NPBool testGetURLOnDestroy; + NPBool testWindowOpen; + NPBool testKeyboardFocusForPlugins; + NPBool mouseDownForEvaluateScript; + char* onStreamLoad; + char* onStreamDestroy; + char* onDestroy; + char* onURLNotify; + char* onSetWindow; + char* onPaintEvent; + char* firstUrl; + char* firstHeaders; + char* lastUrl; + char* lastHeaders; + char* evaluateScriptOnMouseDownOrKeyDown; +#ifdef XP_MACOSX + NPEventModel eventModel; +#endif +#ifdef XP_MACOSX + void* coreAnimationLayer; +#endif + NPWindow lastWindow; +} PluginObject; + +extern NPClass* createPluginClass(void); + +extern void handleCallback(PluginObject* object, + const char* url, + NPReason reason, + void* notifyData); +extern void notifyStream(PluginObject* object, + const char* url, + const char* headers); +extern void testNPRuntime(NPP npp); +extern void pluginLog(NPP instance, const char* format, ...); +extern void pluginLogWithArguments(NPP instance, + const char* format, + va_list args); +extern bool testDocumentOpen(NPP npp); +extern bool testWindowOpen(NPP npp); + +#ifdef XP_MACOSX +extern void* createCoreAnimationLayer(); +#endif + +#endif // PluginObject_h diff --git a/content/shell/tools/plugin/PluginObjectMac.mm b/content/shell/tools/plugin/PluginObjectMac.mm new file mode 100644 index 0000000..90af3dd --- /dev/null +++ b/content/shell/tools/plugin/PluginObjectMac.mm @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginObject.h" + + +#include <QuartzCore/QuartzCore.h> + +@interface TestPluginLayer : CALayer +@end + +@implementation TestPluginLayer + +- (void)drawInContext:(CGContextRef)context +{ + CGRect bounds = [self bounds]; + const char* text = "Test Plug-in"; + CGContextSelectFont(context, "Helvetica", 24, kCGEncodingMacRoman); + CGContextShowTextAtPoint(context, + bounds.origin.x + 3.0f, + bounds.origin.y + bounds.size.height - 30.0f, + text, + strlen(text)); +} + +@end + +void* createCoreAnimationLayer() +{ + CALayer *caLayer = [[TestPluginLayer alloc] init]; + + NSNull *nullValue = [NSNull null]; + NSDictionary *actions = [NSDictionary dictionaryWithObjectsAndKeys: + nullValue, @"anchorPoint", + nullValue, @"bounds", + nullValue, @"contents", + nullValue, @"contentsRect", + nullValue, @"opacity", + nullValue, @"position", + nullValue, @"shadowColor", + nullValue, @"sublayerTransform", + nullValue, @"sublayers", + nullValue, @"transform", + nullValue, @"zPosition", + nil]; + // Turn off default animations. + [caLayer + setStyle:[NSDictionary dictionaryWithObject:actions forKey:@"actions"]]; + [caLayer setNeedsDisplayOnBoundsChange:YES]; + + [caLayer setBounds:CGRectMake(0, 0, 200, 100)]; + [caLayer setAnchorPoint:CGPointZero]; + + CGColorRef color = CGColorCreateGenericRGB(0.5, 0.5, 1, 1); + [caLayer setBackgroundColor:color]; + CGColorRelease(color); + + [caLayer setLayoutManager:[CAConstraintLayoutManager layoutManager]]; + + CALayer *sublayer = [CALayer layer]; + // Turn off default animations. + [sublayer + setStyle:[NSDictionary dictionaryWithObject:actions forKey:@"actions"]]; + + color = CGColorCreateGenericRGB(0, 0, 0, 0.75); + [sublayer setBackgroundColor:color]; + CGColorRelease(color); + [sublayer setBounds:CGRectMake(0, 0, 180, 20)]; + + [sublayer + addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinY + relativeTo:@"superlayer" + attribute:kCAConstraintMinY]]; + [sublayer + addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMinX + relativeTo:@"superlayer" + attribute:kCAConstraintMinX]]; + [sublayer + addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMaxX + relativeTo:@"superlayer" + attribute:kCAConstraintMaxX]]; + + [caLayer addSublayer:sublayer]; + return caLayer; +} diff --git a/content/shell/tools/plugin/PluginTest.cpp b/content/shell/tools/plugin/PluginTest.cpp new file mode 100644 index 0000000..ddf0672 --- /dev/null +++ b/content/shell/tools/plugin/PluginTest.cpp @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include "PluginObject.h" +#include <string.h> + +#if defined(XP_UNIX) || defined(ANDROID) +#include <unistd.h> +#endif + +using namespace std; +extern NPNetscapeFuncs *browser; + +static void (*shutdownFunction)(); + +PluginTest* PluginTest::create(NPP npp, const string& identifier) { + if (identifier.empty()) + return new PluginTest(npp, identifier); + + CreateTestFunction createTestFunction = createTestFunctions()[identifier]; + if (createTestFunction) + return createTestFunction(npp, identifier); + + return 0; +} + +PluginTest::PluginTest(NPP npp, const string& identifier) + : m_npp(npp), m_identifier(identifier) { + // Reset the shutdown function. + shutdownFunction = 0; +} + +PluginTest::~PluginTest() {} + +void PluginTest::NP_Shutdown() { + if (shutdownFunction) + shutdownFunction(); +} + +void PluginTest::registerNPShutdownFunction(void (*func)()) { + assert(!shutdownFunction); + shutdownFunction = func; +} + +void PluginTest::indicateTestFailure() { +// This should really be an assert, but there's no way for the test framework +// to know that the plug-in process crashed, so we'll just sleep for a while +// to ensure that the test times out. +#if defined(XP_WIN) + ::Sleep(100000); +#else + sleep(1000); +#endif +} + +NPError PluginTest::NPP_New(NPMIMEType pluginType, + uint16_t mode, + int16_t argc, + char* argn[], + char* argv[], + NPSavedData* saved) { + return NPERR_NO_ERROR; +} + +NPError PluginTest::NPP_Destroy(NPSavedData**) { return NPERR_NO_ERROR; } + +NPError PluginTest::NPP_SetWindow(NPWindow*) { return NPERR_NO_ERROR; } + +NPError PluginTest::NPP_NewStream(NPMIMEType type, + NPStream* stream, + NPBool seekable, + uint16_t* stype) { + return NPERR_NO_ERROR; +} + +NPError PluginTest::NPP_DestroyStream(NPStream* stream, NPReason reason) { + return NPERR_NO_ERROR; +} + +int32_t PluginTest::NPP_WriteReady(NPStream*) { return 4096; } + +int32_t PluginTest::NPP_Write(NPStream*, + int32_t offset, + int32_t len, + void* buffer) { + return len; +} + +int16_t PluginTest::NPP_HandleEvent(void*) { return 0; } + +bool PluginTest::NPP_URLNotify(const char* url, NPReason, void* notifyData) { + // FIXME: Port the code from NPP_URLNotify in main.cpp over to always using + // PluginTest, so we don't have to use a return value to indicate whether the + // "default" NPP_URLNotify implementation should be invoked. + return false; +} + +NPError PluginTest::NPP_GetValue(NPPVariable variable, void* value) { + // We don't know anything about plug-in values so just return + // NPERR_GENERIC_ERROR. + return NPERR_GENERIC_ERROR; +} + +NPError PluginTest::NPP_SetValue(NPNVariable, void* value) { + return NPERR_GENERIC_ERROR; +} + +// NPN functions. + +NPError PluginTest::NPN_GetURL(const char* url, const char* target) { + return browser->geturl(m_npp, url, target); +} + +NPError PluginTest::NPN_GetURLNotify(const char* url, + const char* target, + void* notifyData) { + return browser->geturlnotify(m_npp, url, target, notifyData); +} + +NPError PluginTest::NPN_GetValue(NPNVariable variable, void* value) { + return browser->getvalue(m_npp, variable, value); +} + +void PluginTest::NPN_InvalidateRect(NPRect* invalidRect) { + browser->invalidaterect(m_npp, invalidRect); +} + +bool PluginTest::NPN_Invoke(NPObject* npobj, + NPIdentifier methodName, + const NPVariant* args, + uint32_t argCount, + NPVariant* result) { + return browser->invoke(m_npp, npobj, methodName, args, argCount, result); +} + +void* PluginTest::NPN_MemAlloc(uint32_t size) { + return browser->memalloc(size); +} + +// NPRuntime NPN functions. + +NPIdentifier PluginTest::NPN_GetStringIdentifier(const NPUTF8* name) { + return browser->getstringidentifier(name); +} + +NPIdentifier PluginTest::NPN_GetIntIdentifier(int32_t intid) { + return browser->getintidentifier(intid); +} + +bool PluginTest::NPN_IdentifierIsString(NPIdentifier npIdentifier) { + return browser->identifierisstring(npIdentifier); +} + +NPUTF8* PluginTest::NPN_UTF8FromIdentifier(NPIdentifier npIdentifier) { + return browser->utf8fromidentifier(npIdentifier); +} + +int32_t PluginTest::NPN_IntFromIdentifier(NPIdentifier npIdentifier) { + return browser->intfromidentifier(npIdentifier); +} + +NPObject* PluginTest::NPN_CreateObject(NPClass* npClass) { + return browser->createobject(m_npp, npClass); +} + +NPObject* PluginTest::NPN_RetainObject(NPObject* npObject) { + return browser->retainobject(npObject); +} + +void PluginTest::NPN_ReleaseObject(NPObject* npObject) { + browser->releaseobject(npObject); +} + +bool PluginTest::NPN_GetProperty(NPObject* npObject, + NPIdentifier propertyName, + NPVariant* value) { + return browser->getproperty(m_npp, npObject, propertyName, value); +} + +bool PluginTest::NPN_RemoveProperty(NPObject* npObject, + NPIdentifier propertyName) { + return browser->removeproperty(m_npp, npObject, propertyName); +} + +void PluginTest::NPN_ReleaseVariantValue(NPVariant* variant) { + browser->releasevariantvalue(variant); +} + +#ifdef XP_MACOSX +bool PluginTest::NPN_ConvertPoint(double sourceX, + double sourceY, + NPCoordinateSpace sourceSpace, + double* destX, + double* destY, + NPCoordinateSpace destSpace) { + return browser->convertpoint( + m_npp, sourceX, sourceY, sourceSpace, destX, destY, destSpace); +} +#endif + +bool PluginTest::executeScript(const NPString* script, NPVariant* result) { + NPObject* windowScriptObject; + browser->getvalue(m_npp, NPNVWindowNPObject, &windowScriptObject); + + return browser->evaluate( + m_npp, windowScriptObject, const_cast<NPString*>(script), result); +} + +void PluginTest::executeScript(const char* script) { + NPString npScript; + npScript.UTF8Characters = script; + npScript.UTF8Length = strlen(script); + + NPVariant browserResult; + executeScript(&npScript, &browserResult); + browser->releasevariantvalue(&browserResult); +} + +void PluginTest::log(const char* format, ...) { + va_list args; + va_start(args, format); + pluginLogWithArguments(m_npp, format, args); + va_end(args); +} + +NPNetscapeFuncs* PluginTest::netscapeFuncs() { return browser; } + +void PluginTest::waitUntilDone() { + executeScript("testRunner.waitUntilDone()"); +} + +void PluginTest::notifyDone() { executeScript("testRunner.notifyDone()"); } + +void PluginTest::registerCreateTestFunction( + const string& identifier, + CreateTestFunction createTestFunction) { + assert(!createTestFunctions().count(identifier)); + + createTestFunctions()[identifier] = createTestFunction; +} + +std::map<std::string, PluginTest::CreateTestFunction>& +PluginTest::createTestFunctions() { + static std::map<std::string, CreateTestFunction> testFunctions; + + return testFunctions; +} diff --git a/content/shell/tools/plugin/PluginTest.h b/content/shell/tools/plugin/PluginTest.h new file mode 100644 index 0000000..dec9900 --- /dev/null +++ b/content/shell/tools/plugin/PluginTest.h @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PluginTest_h +#define PluginTest_h + +#include <assert.h> +#include <bindings/npfunctions.h> +#include <map> +#include <string> + +// Helper classes for implementing has_member +typedef char (&no_tag)[1]; +typedef char (&yes_tag)[2]; + +#define DEFINE_HAS_MEMBER_CHECK(member, returnType, argumentTypes) \ + template <typename T, returnType(T::*member) argumentTypes> \ + struct pmf_##member##_helper {}; \ + template <typename T> \ + no_tag has_member_##member##_helper(...); \ + template <typename T> \ + yes_tag has_member_##member##_helper(pmf_##member##_helper<T, &T::member>*); \ + template <typename T> \ + struct has_member_##member { \ + static const bool value = \ + sizeof(has_member_##member##_helper<T>(0)) == sizeof(yes_tag); \ + }; + +DEFINE_HAS_MEMBER_CHECK(hasMethod, bool, (NPIdentifier methodName)); +DEFINE_HAS_MEMBER_CHECK( + invoke, + bool, + (NPIdentifier methodName, const NPVariant*, uint32_t, NPVariant* result)); +DEFINE_HAS_MEMBER_CHECK(invokeDefault, + bool, + (const NPVariant*, uint32_t, NPVariant* result)); +DEFINE_HAS_MEMBER_CHECK(hasProperty, bool, (NPIdentifier propertyName)); +DEFINE_HAS_MEMBER_CHECK(getProperty, + bool, + (NPIdentifier propertyName, NPVariant* result)); +DEFINE_HAS_MEMBER_CHECK(removeProperty, bool, (NPIdentifier propertyName)); + +class PluginTest { + public: + static PluginTest* create(NPP, const std::string& identifier); + virtual ~PluginTest(); + + static void NP_Shutdown(); + + // NPP functions. + virtual NPError NPP_New(NPMIMEType pluginType, + uint16_t mode, + int16_t argc, + char* argn[], + char* argv[], + NPSavedData* saved); + virtual NPError NPP_Destroy(NPSavedData**); + virtual NPError NPP_SetWindow(NPWindow*); + virtual NPError NPP_NewStream(NPMIMEType, + NPStream*, + NPBool seekable, + uint16_t* stype); + virtual NPError NPP_DestroyStream(NPStream*, NPReason); + virtual int32_t NPP_WriteReady(NPStream*); + virtual int32_t NPP_Write(NPStream*, + int32_t offset, + int32_t len, + void* buffer); + virtual int16_t NPP_HandleEvent(void* event); + virtual bool NPP_URLNotify(const char* url, NPReason, void* notifyData); + virtual NPError NPP_GetValue(NPPVariable, void* value); + virtual NPError NPP_SetValue(NPNVariable, void* value); + + // NPN functions. + NPError NPN_GetURL(const char* url, const char* target); + NPError NPN_GetURLNotify(const char* url, + const char* target, + void* notifyData); + NPError NPN_GetValue(NPNVariable, void* value); + void NPN_InvalidateRect(NPRect* invalidRect); + bool NPN_Invoke(NPObject*, + NPIdentifier methodName, + const NPVariant* args, + uint32_t argCount, + NPVariant* result); + void* NPN_MemAlloc(uint32_t size); + + // NPRuntime NPN functions. + NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name); + NPIdentifier NPN_GetIntIdentifier(int32_t intid); + bool NPN_IdentifierIsString(NPIdentifier); + NPUTF8* NPN_UTF8FromIdentifier(NPIdentifier); + int32_t NPN_IntFromIdentifier(NPIdentifier); + + NPObject* NPN_CreateObject(NPClass*); + NPObject* NPN_RetainObject(NPObject*); + void NPN_ReleaseObject(NPObject*); + bool NPN_GetProperty(NPObject*, NPIdentifier propertyName, NPVariant* value); + bool NPN_RemoveProperty(NPObject*, NPIdentifier propertyName); + void NPN_ReleaseVariantValue(NPVariant*); + +#ifdef XP_MACOSX + bool NPN_ConvertPoint(double sourceX, + double sourceY, + NPCoordinateSpace sourceSpace, + double* destX, + double* destY, + NPCoordinateSpace destSpace); +#endif + + bool executeScript(const NPString*, NPVariant* result); + void executeScript(const char*); + void log(const char* format, ...); + + void registerNPShutdownFunction(void (*)()); + + static void indicateTestFailure(); + + template <typename TestClassTy> + class Register { + public: + Register(const std::string& identifier) { + registerCreateTestFunction(identifier, Register::create); + } + + private: + static PluginTest* create(NPP npp, const std::string& identifier) { + return new TestClassTy(npp, identifier); + } + }; + + protected: + PluginTest(NPP npp, const std::string& identifier); + + // FIXME: A plug-in test shouldn't need to know about it's NPP. Make this + // private. + NPP m_npp; + + const std::string& identifier() const { return m_identifier; } + + static NPNetscapeFuncs* netscapeFuncs(); + + void waitUntilDone(); + void notifyDone(); + + // NPObject helper template. + template <typename T> + struct Object : NPObject { + public: + static NPObject* create(PluginTest* pluginTest) { + Object* object = + static_cast<Object*>(pluginTest->NPN_CreateObject(npClass())); + + object->m_pluginTest = pluginTest; + return object; + } + + // These should never be called. + bool hasMethod(NPIdentifier methodName) { + assert(false); + return false; + } + + bool invoke(NPIdentifier methodName, + const NPVariant*, + uint32_t, + NPVariant* result) { + assert(false); + return false; + } + + bool invokeDefault(const NPVariant*, uint32_t, NPVariant* result) { + assert(false); + return false; + } + + bool hasProperty(NPIdentifier propertyName) { + assert(false); + return false; + } + + bool getProperty(NPIdentifier propertyName, NPVariant* result) { + assert(false); + return false; + } + + bool removeProperty(NPIdentifier propertyName) { + assert(false); + return false; + } + + // Helper functions. + bool identifierIs(NPIdentifier identifier, const char* value) { + return pluginTest()->NPN_GetStringIdentifier(value) == identifier; + } + + protected: + Object() : m_pluginTest(0) {} + + virtual ~Object() {} + + PluginTest* pluginTest() const { return m_pluginTest; } + + private: + static NPObject* NP_Allocate(NPP npp, NPClass* aClass) { return new T; } + + static void NP_Deallocate(NPObject* npObject) { + delete static_cast<T*>(npObject); + } + + static bool NP_HasMethod(NPObject* npObject, NPIdentifier methodName) { + return static_cast<T*>(npObject)->hasMethod(methodName); + } + + static bool NP_Invoke(NPObject* npObject, + NPIdentifier methodName, + const NPVariant* arguments, + uint32_t argumentCount, + NPVariant* result) { + return static_cast<T*>(npObject) + ->invoke(methodName, arguments, argumentCount, result); + } + + static bool NP_InvokeDefault(NPObject* npObject, + const NPVariant* arguments, + uint32_t argumentCount, + NPVariant* result) { + return static_cast<T*>(npObject) + ->invokeDefault(arguments, argumentCount, result); + } + + static bool NP_HasProperty(NPObject* npObject, NPIdentifier propertyName) { + return static_cast<T*>(npObject)->hasProperty(propertyName); + } + + static bool NP_GetProperty(NPObject* npObject, + NPIdentifier propertyName, + NPVariant* result) { + return static_cast<T*>(npObject)->getProperty(propertyName, result); + } + + static bool NP_RemoveProperty(NPObject* npObject, + NPIdentifier propertyName) { + return static_cast<T*>(npObject)->removeProperty(propertyName); + } + + static NPClass* npClass() { + static NPClass npClass = { + NP_CLASS_STRUCT_VERSION, NP_Allocate, NP_Deallocate, + 0, // NPClass::invalidate + has_member_hasMethod<T>::value ? NP_HasMethod : 0, + has_member_invoke<T>::value ? NP_Invoke : 0, + has_member_invokeDefault<T>::value ? NP_InvokeDefault : 0, + has_member_hasProperty<T>::value ? NP_HasProperty : 0, + has_member_getProperty<T>::value ? NP_GetProperty : 0, + 0, // NPClass::setProperty + has_member_removeProperty<T>::value ? NP_RemoveProperty : 0, + 0, // NPClass::enumerate + 0 // NPClass::construct + }; + + return &npClass; + }; + + PluginTest* m_pluginTest; + }; + + private: + typedef PluginTest* (*CreateTestFunction)(NPP, const std::string&); + + static void registerCreateTestFunction(const std::string&, + CreateTestFunction); + static std::map<std::string, CreateTestFunction>& createTestFunctions(); + + std::string m_identifier; +}; + +#endif // PluginTest_h diff --git a/content/shell/tools/plugin/TestObject.cpp b/content/shell/tools/plugin/TestObject.cpp new file mode 100644 index 0000000..7d9ae3e --- /dev/null +++ b/content/shell/tools/plugin/TestObject.cpp @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "TestObject.h" +#include "PluginObject.h" + +#include <string.h> +#include <stdlib.h> + +static bool testEnumerate(NPObject* npobj, + NPIdentifier** value, + uint32_t* count); +static bool testHasMethod(NPObject*, NPIdentifier name); +static bool testInvoke(NPObject*, + NPIdentifier name, + const NPVariant* args, + uint32_t argCount, + NPVariant* result); +static bool testHasProperty(NPObject*, NPIdentifier name); +static bool testGetProperty(NPObject*, NPIdentifier name, NPVariant*); +static NPObject* testAllocate(NPP npp, NPClass* theClass); +static void testDeallocate(NPObject* obj); +static bool testConstruct(NPObject* obj, + const NPVariant* args, + uint32_t argCount, + NPVariant* result); + +static NPClass testClass = { + NP_CLASS_STRUCT_VERSION, testAllocate, testDeallocate, 0, + testHasMethod, testInvoke, 0, testHasProperty, + testGetProperty, 0, 0, testEnumerate, + testConstruct}; + +NPClass* getTestClass(void) { return &testClass; } + +static int testObjectCount = 0; + +int getTestObjectCount() { return testObjectCount; } + +typedef struct { + NPObject header; + NPObject* testObject; +} TestObject; + +static bool identifiersInitialized = false; + +#define NUM_ENUMERATABLE_TEST_IDENTIFIERS 2 + +enum { + ID_PROPERTY_FOO = 0, + ID_PROPERTY_BAR, + ID_PROPERTY_OBJECT_POINTER, + ID_PROPERTY_TEST_OBJECT, + ID_PROPERTY_REF_COUNT, + NUM_TEST_IDENTIFIERS, +}; + +static NPIdentifier testIdentifiers[NUM_TEST_IDENTIFIERS]; +static const NPUTF8* testIdentifierNames[NUM_TEST_IDENTIFIERS] = { + "foo", "bar", "objectPointer", "testObject", "refCount", }; + +#define ID_THROW_EXCEPTION_METHOD 0 +#define NUM_METHOD_IDENTIFIERS 1 + +static NPIdentifier testMethodIdentifiers[NUM_METHOD_IDENTIFIERS]; +static const NPUTF8* testMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = { + "throwException", }; + +static void initializeIdentifiers(void) { + browser->getstringidentifiers( + testIdentifierNames, NUM_TEST_IDENTIFIERS, testIdentifiers); + browser->getstringidentifiers( + testMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, testMethodIdentifiers); +} + +static NPObject* testAllocate(NPP npp, NPClass* /*theClass*/) { + TestObject* newInstance = + static_cast<TestObject*>(malloc(sizeof(TestObject))); + newInstance->testObject = 0; + ++testObjectCount; + + if (!identifiersInitialized) { + identifiersInitialized = true; + initializeIdentifiers(); + } + + return reinterpret_cast<NPObject*>(newInstance); +} + +static void testDeallocate(NPObject* obj) { + TestObject* testObject = reinterpret_cast<TestObject*>(obj); + if (testObject->testObject) + browser->releaseobject(testObject->testObject); + + --testObjectCount; + free(obj); +} + +static bool testHasMethod(NPObject*, NPIdentifier name) { + for (unsigned i = 0; i < NUM_METHOD_IDENTIFIERS; i++) { + if (testMethodIdentifiers[i] == name) + return true; + } + return false; +} + +static bool testInvoke(NPObject* header, + NPIdentifier name, + const NPVariant* /*args*/, + uint32_t /*argCount*/, + NPVariant* /*result*/) { + if (name == testMethodIdentifiers[ID_THROW_EXCEPTION_METHOD]) { + browser->setexception(header, "test object throwException SUCCESS"); + return true; + } + return false; +} + +static bool testHasProperty(NPObject*, NPIdentifier name) { + for (unsigned i = 0; i < NUM_TEST_IDENTIFIERS; i++) { + if (testIdentifiers[i] == name) + return true; + } + + return false; +} + +static bool testGetProperty(NPObject* npobj, + NPIdentifier name, + NPVariant* result) { + if (name == testIdentifiers[ID_PROPERTY_FOO]) { + char* mem = static_cast<char*>(browser->memalloc(4)); + strcpy(mem, "foo"); + STRINGZ_TO_NPVARIANT(mem, *result); + return true; + } + if (name == testIdentifiers[ID_PROPERTY_OBJECT_POINTER]) { + int32_t objectPointer = + static_cast<int32_t>(reinterpret_cast<long long>(npobj)); + + INT32_TO_NPVARIANT(objectPointer, *result); + return true; + } + if (name == testIdentifiers[ID_PROPERTY_TEST_OBJECT]) { + TestObject* testObject = reinterpret_cast<TestObject*>(npobj); + if (!testObject->testObject) + testObject->testObject = browser->createobject(0, &testClass); + browser->retainobject(testObject->testObject); + OBJECT_TO_NPVARIANT(testObject->testObject, *result); + return true; + } + if (name == testIdentifiers[ID_PROPERTY_REF_COUNT]) { + INT32_TO_NPVARIANT(npobj->referenceCount, *result); + return true; + } + + return false; +} + +static bool testEnumerate(NPObject* /*npobj*/, + NPIdentifier** value, + uint32_t* count) { + *count = NUM_ENUMERATABLE_TEST_IDENTIFIERS; + + *value = (NPIdentifier*)browser->memalloc(NUM_ENUMERATABLE_TEST_IDENTIFIERS * + sizeof(NPIdentifier)); + memcpy(*value, + testIdentifiers, + sizeof(NPIdentifier) * NUM_ENUMERATABLE_TEST_IDENTIFIERS); + + return true; +} + +static bool testConstruct(NPObject* npobj, + const NPVariant* /*args*/, + uint32_t /*argCount*/, + NPVariant* result) { + browser->retainobject(npobj); + + // Just return the same object. + OBJECT_TO_NPVARIANT(npobj, *result); + return true; +} diff --git a/content/shell/tools/plugin/TestObject.h b/content/shell/tools/plugin/TestObject.h new file mode 100644 index 0000000..aa4c587 --- /dev/null +++ b/content/shell/tools/plugin/TestObject.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <bindings/npapi.h> +#include <bindings/npruntime.h> + +NPClass* getTestClass(void); +int getTestObjectCount(); diff --git a/content/shell/tools/plugin/Tests/DocumentOpenInDestroyStream.cpp b/content/shell/tools/plugin/Tests/DocumentOpenInDestroyStream.cpp new file mode 100644 index 0000000..36fb4b9b --- /dev/null +++ b/content/shell/tools/plugin/Tests/DocumentOpenInDestroyStream.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +using namespace std; + +extern bool testDocumentOpen(NPP npp); + +// Call document.open from NPP_DestroyStream. + +class DocumentOpenInDestroyStream : public PluginTest { +public: + DocumentOpenInDestroyStream(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + , m_shouldOpen(true) + { + } + +private: + virtual NPError NPP_DestroyStream(NPStream*, NPReason) + { + if (m_shouldOpen) { + testDocumentOpen(m_npp); + m_shouldOpen = false; + } + + return NPERR_NO_ERROR; + } + + bool m_shouldOpen; +}; + +static PluginTest::Register<DocumentOpenInDestroyStream> documentOpenInDestroyStream("document-open-in-destroy-stream"); diff --git a/content/shell/tools/plugin/Tests/EvaluateJSAfterRemovingPluginElement.cpp b/content/shell/tools/plugin/Tests/EvaluateJSAfterRemovingPluginElement.cpp new file mode 100644 index 0000000..4b5d3e01 --- /dev/null +++ b/content/shell/tools/plugin/Tests/EvaluateJSAfterRemovingPluginElement.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include "PluginObject.h" + +using namespace std; + +// Executing JS after removing the plugin element from the document should not crash. + +class EvaluateJSAfterRemovingPluginElement : public PluginTest { +public: + EvaluateJSAfterRemovingPluginElement(NPP, const string& identifier); + +private: + virtual NPError NPP_DestroyStream(NPStream*, NPReason); + + bool m_didExecuteScript; +}; + +static PluginTest::Register<EvaluateJSAfterRemovingPluginElement> registrar("evaluate-js-after-removing-plugin-element"); + +EvaluateJSAfterRemovingPluginElement::EvaluateJSAfterRemovingPluginElement(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + , m_didExecuteScript(false) +{ + waitUntilDone(); +} + +NPError EvaluateJSAfterRemovingPluginElement::NPP_DestroyStream(NPStream*, NPReason) +{ + if (m_didExecuteScript) + return NPERR_NO_ERROR; + m_didExecuteScript = true; + + executeScript("var plugin = document.getElementsByTagName('embed')[0]; plugin.parentElement.removeChild(plugin);"); + executeScript("document.body.appendChild(document.createTextNode('Executing script after removing the plugin element from the document succeeded.'));"); + notifyDone(); + + return NPERR_NO_ERROR; +} diff --git a/content/shell/tools/plugin/Tests/EvaluateJSWithinNPP_New.cpp b/content/shell/tools/plugin/Tests/EvaluateJSWithinNPP_New.cpp new file mode 100644 index 0000000..c066db5 --- /dev/null +++ b/content/shell/tools/plugin/Tests/EvaluateJSWithinNPP_New.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include "PluginObject.h" + +using namespace std; + +// Executing JS within NPP_New when initializing asynchronously should not be able to deadlock with the WebProcess + +class EvaluteJSWithinNPP_New : public PluginTest { +public: + EvaluteJSWithinNPP_New(NPP, const string& identifier); + +private: + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *); + +}; + +EvaluteJSWithinNPP_New::EvaluteJSWithinNPP_New(NPP npp, const string& identifier) + : PluginTest(npp, identifier) +{ +} + +NPError EvaluteJSWithinNPP_New::NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved) +{ + // Give the WebProcess enough time to be deadlocked waiting for the PluginProcess. + usleep(15000); + executeScript("var theLocation = window.location;"); + return NPERR_NO_ERROR; +} + +static PluginTest::Register<EvaluteJSWithinNPP_New> registrar("evalute-js-within-npp-new"); diff --git a/content/shell/tools/plugin/Tests/FormValue.cpp b/content/shell/tools/plugin/Tests/FormValue.cpp new file mode 100644 index 0000000..738e192 --- /dev/null +++ b/content/shell/tools/plugin/Tests/FormValue.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2011 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" +#include <string.h> + +extern NPNetscapeFuncs *browser; + +class FormValue : public PluginTest { +public: + FormValue(NPP npp, const std::string& identifier) + : PluginTest(npp, identifier) + { + } + virtual NPError NPP_GetValue(NPPVariable, void*); +}; + +NPError FormValue::NPP_GetValue(NPPVariable variable, void *value) +{ + if (variable == NPPVformValue) { + static const char formValueText[] = "Plugin form value"; + *((void**)value) = browser->memalloc(sizeof(formValueText)); + if (!*((void**)value)) + return NPERR_OUT_OF_MEMORY_ERROR; + strncpy(*((char**)value), formValueText, sizeof(formValueText)); + return NPERR_NO_ERROR; + } + return NPERR_GENERIC_ERROR; +} + +static PluginTest::Register<FormValue> formValue("form-value"); diff --git a/content/shell/tools/plugin/Tests/GetURLNotifyWithURLThatFailsToLoad.cpp b/content/shell/tools/plugin/Tests/GetURLNotifyWithURLThatFailsToLoad.cpp new file mode 100644 index 0000000..f6f39ab --- /dev/null +++ b/content/shell/tools/plugin/Tests/GetURLNotifyWithURLThatFailsToLoad.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include <string.h> + +using namespace std; + +// From NPP_New, call NPN_GetURLNotify with a URL that fails to load (NPP_NewStream won't be called). +// The plug-in should still get a NPP_URLNotify indicating that the load failed. +static const char *urlThatFailsToLoad = "foo://bar/"; + +class GetURLNotifyWithURLThatFailsToLoad : public PluginTest { +public: + GetURLNotifyWithURLThatFailsToLoad(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved) + { + NPN_GetURLNotify(urlThatFailsToLoad, 0, reinterpret_cast<void*>(0x12345678)); + return NPERR_NO_ERROR; + } + + bool NPP_URLNotify(const char* url, NPReason reason, void* notifyData) + { + bool didFail = false; + + if (strcmp(url, urlThatFailsToLoad)) + didFail = true; + + if (reason != NPRES_NETWORK_ERR) + didFail = true; + + if (notifyData != reinterpret_cast<void*>(0x12345678)) + didFail = true; + + if (!didFail) + executeScript("testSucceeded()"); + else + executeScript("notifyDone()"); + return true; + } +}; + +static PluginTest::Register<GetURLNotifyWithURLThatFailsToLoad> getURLWithJavaScriptURLDestroyingPlugin("get-url-notify-with-url-that-fails-to-load"); diff --git a/content/shell/tools/plugin/Tests/GetURLWithJavaScriptURL.cpp b/content/shell/tools/plugin/Tests/GetURLWithJavaScriptURL.cpp new file mode 100644 index 0000000..64a69a3 --- /dev/null +++ b/content/shell/tools/plugin/Tests/GetURLWithJavaScriptURL.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include <string.h> +#include <vector> + +using namespace std; + +const char *javaScriptURL = "javascript:'Hello, ' + 'World!'"; +const char *javaScriptResult = "Hello, World!"; + +// Test that evaluating a javascript: URL will send a stream with the result of the evaluation. +// Test that evaluating JavaScript using NPN_GetURL will a stream with result of the evaluation. +class GetURLWithJavaScriptURL : public PluginTest { +public: + GetURLWithJavaScriptURL(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + , m_didFail(false) + { + } + +private: + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved) + { + NPN_GetURL(javaScriptURL, 0); + return NPERR_NO_ERROR; + } + + NPError NPP_NewStream(NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype) + { + stream->pdata = this; + + if (strcmp(stream->url, javaScriptURL)) + m_didFail = true; + + if (stream->end != strlen(javaScriptResult)) + m_didFail = true; + + *stype = NP_NORMAL; + return NPERR_NO_ERROR; + } + + NPError NPP_DestroyStream(NPStream* stream, NPReason reason) + { + if (stream->pdata != this) + m_didFail = true; + + if (reason != NPRES_DONE) + m_didFail = true; + + if (m_data.size() != stream->end) + m_didFail = true; + + m_data.push_back('\0'); + + if (strcmp(&m_data[0], javaScriptResult)) + m_didFail = true; + + if (!m_didFail) + executeScript("testSucceeded()"); + else + executeScript("notifyDone()"); + + return NPERR_NO_ERROR; + } + + int32_t NPP_WriteReady(NPStream* stream) + { + if (stream->pdata != this) + m_didFail = true; + + return 2; + } + + int32_t NPP_Write(NPStream* stream, int32_t offset, int32_t len, void* buffer) + { + if (stream->pdata != this) + m_didFail = true; + + m_data.insert(m_data.end(), static_cast<char*>(buffer), static_cast<char*>(buffer) + len); + return len; + } + + vector<char> m_data; + bool m_didFail; +}; + +static PluginTest::Register<GetURLWithJavaScriptURL> getURLWithJavaScriptURLDestroyingPlugin("get-url-with-javascript-url"); diff --git a/content/shell/tools/plugin/Tests/GetURLWithJavaScriptURLDestroyingPlugin.cpp b/content/shell/tools/plugin/Tests/GetURLWithJavaScriptURLDestroyingPlugin.cpp new file mode 100644 index 0000000..aa1fc11 --- /dev/null +++ b/content/shell/tools/plugin/Tests/GetURLWithJavaScriptURLDestroyingPlugin.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +using namespace std; + +// From NPP_New, call NPN_GetURL to evaluate JavaScript that destroys the plug-in. + +class GetURLWithJavaScriptURLDestroyingPlugin : public PluginTest { +public: + GetURLWithJavaScriptURLDestroyingPlugin(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved) + { + NPN_GetURL("javascript:removePlugin()", 0); + return NPERR_NO_ERROR; + } +}; + +static PluginTest::Register<GetURLWithJavaScriptURLDestroyingPlugin> getURLWithJavaScriptURLDestroyingPlugin("get-url-with-javascript-url-destroying-plugin"); diff --git a/content/shell/tools/plugin/Tests/GetUserAgentWithNullNPPFromNPPNew.cpp b/content/shell/tools/plugin/Tests/GetUserAgentWithNullNPPFromNPPNew.cpp new file mode 100644 index 0000000..887e152 --- /dev/null +++ b/content/shell/tools/plugin/Tests/GetUserAgentWithNullNPPFromNPPNew.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include "PluginObject.h" + +using namespace std; + +// Trying to get the user agent with a null instance from NPP_New. + +class GetUserAgentWithNullNPPFromNPPNew : public PluginTest { +public: + GetUserAgentWithNullNPPFromNPPNew(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved) + { + if (!browser->uagent(0)) + pluginLog(m_npp, "FAILURE: Null user agent returned."); + else + pluginLog(m_npp, "SUCCESS!"); + + return NPERR_NO_ERROR; + } + +}; + +static PluginTest::Register<GetUserAgentWithNullNPPFromNPPNew> getUserAgentWithNullNPPFromNPPNew("get-user-agent-with-null-npp-from-npp-new"); diff --git a/content/shell/tools/plugin/Tests/InvokeDestroysPluginWithinNPP_New.cpp b/content/shell/tools/plugin/Tests/InvokeDestroysPluginWithinNPP_New.cpp new file mode 100644 index 0000000..a9a9b8f --- /dev/null +++ b/content/shell/tools/plugin/Tests/InvokeDestroysPluginWithinNPP_New.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include "PluginObject.h" + +using namespace std; + +// Executing JS within NPP_New when initializing asynchronously should not be able to deadlock with the WebProcess + +class InvokeDestroysPluginWithinNPP_New : public PluginTest { +public: + InvokeDestroysPluginWithinNPP_New(NPP, const string& identifier); + +private: + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *); + +}; + +InvokeDestroysPluginWithinNPP_New::InvokeDestroysPluginWithinNPP_New(NPP npp, const string& identifier) + : PluginTest(npp, identifier) +{ +} + +NPError InvokeDestroysPluginWithinNPP_New::NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved) +{ + // Give the WebProcess enough time to be deadlocked waiting for the PluginProcess if things aren't working correctly. + usleep(15000); + + NPObject* windowObject = 0; + if (NPN_GetValue(NPNVWindowNPObject, &windowObject) != NPERR_NO_ERROR) + return NPERR_GENERIC_ERROR; + + if (!windowObject) + return NPERR_GENERIC_ERROR; + + NPVariant result; + if (!NPN_Invoke(windowObject, NPN_GetStringIdentifier("removePluginElement"), 0, 0, &result)) + return NPERR_GENERIC_ERROR; + + return NPERR_NO_ERROR; +} + +static PluginTest::Register<InvokeDestroysPluginWithinNPP_New> registrar("invoke-destroys-plugin-within-npp-new"); diff --git a/content/shell/tools/plugin/Tests/LeakWindowScriptableObject.cpp b/content/shell/tools/plugin/Tests/LeakWindowScriptableObject.cpp new file mode 100644 index 0000000..93f52a2 --- /dev/null +++ b/content/shell/tools/plugin/Tests/LeakWindowScriptableObject.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2012 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +using namespace std; + +class LeakWindowScriptableObject : public PluginTest { +public: + LeakWindowScriptableObject(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved) + { + // Get a new reference to the window script object. + NPObject* window; + if (NPN_GetValue(NPNVWindowNPObject, &window) != NPERR_NO_ERROR) { + log("Fail: Cannot fetch window script object"); + return NPERR_NO_ERROR; + } + + // Get another reference to the same object via window.self. + NPIdentifier self_name = NPN_GetStringIdentifier("self"); + NPVariant window_self_variant; + if (!NPN_GetProperty(window, self_name, &window_self_variant)) { + log("Fail: Cannot query window.self"); + return NPERR_NO_ERROR; + } + if (!NPVARIANT_IS_OBJECT(window_self_variant)) { + log("Fail: window.self is not an object"); + return NPERR_NO_ERROR; + } + + // Leak both references to the window script object. + return NPERR_NO_ERROR; + } +}; + +static PluginTest::Register<LeakWindowScriptableObject> leakWindowScriptableObject("leak-window-scriptable-object"); diff --git a/content/shell/tools/plugin/Tests/LogNPPSetWindow.cpp b/content/shell/tools/plugin/Tests/LogNPPSetWindow.cpp new file mode 100644 index 0000000..90481e2 --- /dev/null +++ b/content/shell/tools/plugin/Tests/LogNPPSetWindow.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include <stdio.h> + +using namespace std; + +class LogNPPSetWindow : public PluginTest { +public: + LogNPPSetWindow(NPP, const string& identifier); + +private: + virtual NPError NPP_SetWindow(NPWindow*); +}; + +LogNPPSetWindow::LogNPPSetWindow(NPP npp, const string& identifier) + : PluginTest(npp, identifier) +{ +} + +NPError LogNPPSetWindow::NPP_SetWindow(NPWindow* window) +{ + char message[1024]; + snprintf(message, 1024, "NPP_SetWindow: %s window, Rect {%i, %i, %i, %i}, Clip Rect {%i, %i, %i, %i}, Type %i", + window->window ? "non-NULL" : "NULL", window->x, window->y, window->width, window->height, + window->clipRect.left, window->clipRect.top, window->clipRect.right, window->clipRect.bottom, + window->type); + + char script[1536]; + snprintf(script, 1536, "window.setTimeout('windowWasSet(\"%s\");', 0);", message); + + executeScript(script); + + return NPERR_NO_ERROR; +} + +static PluginTest::Register<LogNPPSetWindow> registrar("log-npp-set-window"); diff --git a/content/shell/tools/plugin/Tests/NPDeallocateCalledBeforeNPShutdown.cpp b/content/shell/tools/plugin/Tests/NPDeallocateCalledBeforeNPShutdown.cpp new file mode 100644 index 0000000..fb0f2c4 --- /dev/null +++ b/content/shell/tools/plugin/Tests/NPDeallocateCalledBeforeNPShutdown.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +using namespace std; + +static bool wasShutdownCalled = false; + +class NPDeallocateCalledBeforeNPShutdown : public PluginTest { +public: + NPDeallocateCalledBeforeNPShutdown(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + // This is the test object. + class TestObject : public Object<TestObject> { + public: + ~TestObject() + { + if (wasShutdownCalled) + indicateTestFailure(); + } + }; + + // This is the scriptable object. It has a single "testObject" property. + class ScriptableObject : public Object<ScriptableObject> { + public: + bool hasProperty(NPIdentifier propertyName) + { + return propertyName == pluginTest()->NPN_GetStringIdentifier("testObject"); + } + + bool getProperty(NPIdentifier propertyName, NPVariant* result) + { + if (propertyName != pluginTest()->NPN_GetStringIdentifier("testObject")) + return false; + + NPObject* testObject = TestObject::create(pluginTest()); + OBJECT_TO_NPVARIANT(testObject, *result); + return true; + } + }; + + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved) + { + registerNPShutdownFunction(shutdown); + + return NPERR_NO_ERROR; + } + + virtual NPError NPP_GetValue(NPPVariable variable, void *value) + { + if (variable != NPPVpluginScriptableNPObject) + return NPERR_GENERIC_ERROR; + + *(NPObject**)value = ScriptableObject::create(this); + + return NPERR_NO_ERROR; + } + + static void shutdown() + { + wasShutdownCalled = true; + } + +}; + +static PluginTest::Register<NPDeallocateCalledBeforeNPShutdown> npRuntimeObjectFromDestroyedPlugin("np-deallocate-called-before-np-shutdown"); + diff --git a/content/shell/tools/plugin/Tests/NPPNewFails.cpp b/content/shell/tools/plugin/Tests/NPPNewFails.cpp new file mode 100644 index 0000000..afe344a --- /dev/null +++ b/content/shell/tools/plugin/Tests/NPPNewFails.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include <string.h> + +using namespace std; + +class NPPNewFails : public PluginTest { +public: + NPPNewFails(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved) + { + return NPERR_GENERIC_ERROR; + } +}; + +static PluginTest::Register<NPPNewFails> nppNewFails("npp-new-fails"); diff --git a/content/shell/tools/plugin/Tests/NPPSetWindowCalledDuringDestruction.cpp b/content/shell/tools/plugin/Tests/NPPSetWindowCalledDuringDestruction.cpp new file mode 100644 index 0000000..50af9590 --- /dev/null +++ b/content/shell/tools/plugin/Tests/NPPSetWindowCalledDuringDestruction.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include "PluginObject.h" + +using namespace std; + +// NPP_SetWindow should be called with a null window handle as destruction begins on non-Mac platforms. + +class NPPSetWindowCalledDuringDestruction : public PluginTest { +public: + NPPSetWindowCalledDuringDestruction(NPP, const string& identifier); + + void setWillBeDestroyed() { m_willBeDestroyed = true; } + +private: + struct ScriptObject : Object<ScriptObject> { + bool hasMethod(NPIdentifier); + bool invoke(NPIdentifier, const NPVariant*, uint32_t, NPVariant*); + }; + + virtual NPError NPP_GetValue(NPPVariable, void*); + virtual NPError NPP_SetWindow(NPWindow*); + virtual NPError NPP_Destroy(NPSavedData**); + + bool m_willBeDestroyed; + bool m_setWindowCalledBeforeDestruction; + bool m_setWindowCalledDuringDestruction; +}; + +static PluginTest::Register<NPPSetWindowCalledDuringDestruction> registrar("npp-set-window-called-during-destruction"); + +NPPSetWindowCalledDuringDestruction::NPPSetWindowCalledDuringDestruction(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + , m_willBeDestroyed(false) + , m_setWindowCalledBeforeDestruction(false) + , m_setWindowCalledDuringDestruction(false) +{ +} + +NPError NPPSetWindowCalledDuringDestruction::NPP_GetValue(NPPVariable variable, void* value) +{ + if (variable != NPPVpluginScriptableNPObject) + return NPERR_GENERIC_ERROR; + + *static_cast<NPObject**>(value) = ScriptObject::create(this); + + return NPERR_NO_ERROR; +} + +NPError NPPSetWindowCalledDuringDestruction::NPP_SetWindow(NPWindow* window) +{ + if (m_willBeDestroyed) { + m_setWindowCalledDuringDestruction = true; + if (!m_setWindowCalledBeforeDestruction) { + log("Fail: setWillBeDestroyed() was called before the initial NPP_SetWindow call"); + return NPERR_NO_ERROR; + } +#ifndef XP_MACOSX + if (window->window) + log("Fail: NPP_SetWindow passed a non-null window during plugin destruction"); +#endif + return NPERR_NO_ERROR; + } + + if (m_setWindowCalledBeforeDestruction) { + log("Fail: NPP_SetWindow called more than once before plugin destruction"); + return NPERR_NO_ERROR; + } + + m_setWindowCalledBeforeDestruction = true; + return NPERR_NO_ERROR; +} + +NPError NPPSetWindowCalledDuringDestruction::NPP_Destroy(NPSavedData**) +{ +#ifdef XP_MACOSX + bool shouldHaveBeenCalledDuringDestruction = false; +#else + bool shouldHaveBeenCalledDuringDestruction = true; +#endif + + if (m_setWindowCalledDuringDestruction == shouldHaveBeenCalledDuringDestruction) + log("Success: NPP_SetWindow %s called during plugin destruction", shouldHaveBeenCalledDuringDestruction ? "was" : "was not"); + else + log("Fail: NPP_SetWindow %s called during plugin destruction", shouldHaveBeenCalledDuringDestruction ? "was not" : "was"); + + return NPERR_NO_ERROR; +} + +bool NPPSetWindowCalledDuringDestruction::ScriptObject::hasMethod(NPIdentifier methodName) +{ + return methodName == pluginTest()->NPN_GetStringIdentifier("setWillBeDestroyed"); +} + +bool NPPSetWindowCalledDuringDestruction::ScriptObject::invoke(NPIdentifier identifier, const NPVariant*, uint32_t, NPVariant*) +{ + assert(identifier == pluginTest()->NPN_GetStringIdentifier("setWillBeDestroyed")); + static_cast<NPPSetWindowCalledDuringDestruction*>(pluginTest())->setWillBeDestroyed(); + return true; +} diff --git a/content/shell/tools/plugin/Tests/NPRuntimeCallsWithNullNPP.cpp b/content/shell/tools/plugin/Tests/NPRuntimeCallsWithNullNPP.cpp new file mode 100644 index 0000000..84e9714 --- /dev/null +++ b/content/shell/tools/plugin/Tests/NPRuntimeCallsWithNullNPP.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +class NPRuntimeCallsWithNullNPP : public PluginTest { +public: + NPRuntimeCallsWithNullNPP(NPP npp, const std::string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved) + { + NPObject* windowObject = 0; + if (NPN_GetValue(NPNVWindowNPObject, &windowObject) != NPERR_NO_ERROR || !windowObject) + return NPERR_GENERIC_ERROR; + + NPIdentifier alertIdentifier = NPN_GetStringIdentifier("alert"); + if (!PluginTest::netscapeFuncs()->hasmethod(0, windowObject, alertIdentifier)) { + NPN_ReleaseObject(windowObject); + return NPERR_GENERIC_ERROR; + } + + NPIdentifier documentIdentifier = NPN_GetStringIdentifier("document"); + NPVariant variant; + if (!PluginTest::netscapeFuncs()->getproperty(0, windowObject, documentIdentifier, &variant)) { + NPN_ReleaseObject(windowObject); + return NPERR_GENERIC_ERROR; + } + NPN_ReleaseVariantValue(&variant); + + NPN_ReleaseObject(windowObject); + + executeScript("document.getElementById('result').innerHTML = 'SUCCESS!'"); + notifyDone(); + return NPERR_NO_ERROR; + } +}; + +static PluginTest::Register<NPRuntimeCallsWithNullNPP> npRuntimeCallsWithNullNPP("npruntime-calls-with-null-npp"); + + diff --git a/content/shell/tools/plugin/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp b/content/shell/tools/plugin/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp new file mode 100644 index 0000000..96e9d83 --- /dev/null +++ b/content/shell/tools/plugin/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +using namespace std; + +class NPRuntimeObjectFromDestroyedPlugin : public PluginTest { +public: + NPRuntimeObjectFromDestroyedPlugin(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + // This is the test object. + class TestObject : public Object<TestObject> { }; + + // This is the scriptable object. It has a single "testObject" property and an "evaluate" function. + class ScriptableObject : public Object<ScriptableObject> { + public: + bool hasMethod(NPIdentifier methodName) + { + return identifierIs(methodName, "evaluate"); + } + + bool invoke(NPIdentifier methodName, const NPVariant* args, uint32_t argCount, NPVariant* result) + { + if (!identifierIs(methodName, "evaluate")) + return false; + + if (argCount != 1 || !NPVARIANT_IS_STRING(args[0])) + return false; + + return pluginTest()->executeScript(&NPVARIANT_TO_STRING(args[0]), result); + } + + bool hasProperty(NPIdentifier propertyName) + { + return identifierIs(propertyName, "testObject"); + } + + bool getProperty(NPIdentifier propertyName, NPVariant* result) + { + if (propertyName != pluginTest()->NPN_GetStringIdentifier("testObject")) + return false; + + NPObject* testObject = TestObject::create(pluginTest()); + OBJECT_TO_NPVARIANT(testObject, *result); + return true; + } + }; + + virtual NPError NPP_GetValue(NPPVariable variable, void *value) + { + if (variable != NPPVpluginScriptableNPObject) + return NPERR_GENERIC_ERROR; + + *(NPObject**)value = ScriptableObject::create(this); + + return NPERR_NO_ERROR; + } +}; + +static PluginTest::Register<NPRuntimeObjectFromDestroyedPlugin> npRuntimeObjectFromDestroyedPlugin("npruntime-object-from-destroyed-plugin"); + diff --git a/content/shell/tools/plugin/Tests/NPRuntimeRemoveProperty.cpp b/content/shell/tools/plugin/Tests/NPRuntimeRemoveProperty.cpp new file mode 100644 index 0000000..f817dcb --- /dev/null +++ b/content/shell/tools/plugin/Tests/NPRuntimeRemoveProperty.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include <string.h> + +using namespace std; + +class NPRuntimeRemoveProperty : public PluginTest { +public: + NPRuntimeRemoveProperty(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + struct TestObject : Object<TestObject> { + public: + TestObject() + : m_lastRemovedProperty(0) + { + } + + bool hasProperty(NPIdentifier propertyName) + { + if (identifierIs(propertyName, "lastRemovedProperty")) + return true; + + return false; + } + + bool getProperty(NPIdentifier propertyName, NPVariant* result) + { + assert(identifierIs(propertyName, "lastRemovedProperty")); + + if (!m_lastRemovedProperty) + return false; + + if (pluginTest()->NPN_IdentifierIsString(m_lastRemovedProperty)) { + char* lastRemovedPropertyName = pluginTest()->NPN_UTF8FromIdentifier(m_lastRemovedProperty); + + STRINGZ_TO_NPVARIANT(lastRemovedPropertyName, *result); + return true; + } + + int intIdentifier = pluginTest()->NPN_IntFromIdentifier(m_lastRemovedProperty); + DOUBLE_TO_NPVARIANT(intIdentifier, *result); + return true; + } + + bool removeProperty(NPIdentifier propertyName) + { + m_lastRemovedProperty = propertyName; + return true; + } + + private: + NPIdentifier m_lastRemovedProperty; + }; + + struct PluginObject : Object<PluginObject> { + public: + PluginObject() + : m_testObject(0) + { + } + + ~PluginObject() + { + if (m_testObject) + pluginTest()->NPN_ReleaseObject(m_testObject); + } + + bool hasMethod(NPIdentifier methodName) + { + if (identifierIs(methodName, "testRemoveProperty")) + return true; + + return false; + } + + bool invoke(NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) + { + assert(identifierIs(methodName, "testRemoveProperty")); + + if (argumentCount != 2) + return false; + + if (!NPVARIANT_IS_OBJECT(arguments[0])) + return false; + + if (!NPVARIANT_IS_STRING(arguments[1]) && !NPVARIANT_IS_DOUBLE(arguments[1])) + return false; + + NPIdentifier propertyName; + if (NPVARIANT_IS_STRING(arguments[1])) { + string propertyNameString(arguments[1].value.stringValue.UTF8Characters, + arguments[1].value.stringValue.UTF8Length); + + propertyName = pluginTest()->NPN_GetStringIdentifier(propertyNameString.c_str()); + } else { + int32_t number = static_cast<int32_t>(arguments[1].value.doubleValue); + propertyName = pluginTest()->NPN_GetIntIdentifier(number); + } + + pluginTest()->NPN_RemoveProperty(NPVARIANT_TO_OBJECT(arguments[0]), propertyName); + + VOID_TO_NPVARIANT(*result); + return true; + } + + bool hasProperty(NPIdentifier propertyName) + { + if (identifierIs(propertyName, "testObject")) + return true; + + return false; + } + + bool getProperty(NPIdentifier propertyName, NPVariant* result) + { + assert(identifierIs(propertyName, "testObject")); + + if (!m_testObject) + m_testObject = TestObject::create(pluginTest()); + + OBJECT_TO_NPVARIANT(pluginTest()->NPN_RetainObject(m_testObject), *result); + return true; + } + + private: + NPObject* m_testObject; + }; + + virtual NPError NPP_GetValue(NPPVariable variable, void *value) + { + if (variable != NPPVpluginScriptableNPObject) + return NPERR_GENERIC_ERROR; + + *(NPObject**)value = PluginObject::create(this); + + return NPERR_NO_ERROR; + } + +}; + +static PluginTest::Register<NPRuntimeRemoveProperty> npRuntimeRemoveProperty("npruntime-remove-property"); diff --git a/content/shell/tools/plugin/Tests/NullNPPGetValuePointer.cpp b/content/shell/tools/plugin/Tests/NullNPPGetValuePointer.cpp new file mode 100644 index 0000000..9e4e976 --- /dev/null +++ b/content/shell/tools/plugin/Tests/NullNPPGetValuePointer.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include "PluginObject.h" + +using namespace std; + +// Passing null for our NPP_GetValue function pointer should not crash. + +class NullNPPGetValuePointer : public PluginTest { +public: + NullNPPGetValuePointer(NPP, const string& identifier); + +private: + virtual NPError NPP_Destroy(NPSavedData**); + virtual NPError NPP_GetValue(NPPVariable, void* value); + + NPP_GetValueProcPtr m_originalNPPGetValuePointer; +}; + +static PluginTest::Register<NullNPPGetValuePointer> registrar("null-npp-getvalue-pointer"); + +NullNPPGetValuePointer::NullNPPGetValuePointer(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + , m_originalNPPGetValuePointer(pluginFunctions->getvalue) +{ + // Be sneaky and null out the getvalue pointer the browser is holding. This simulates a plugin + // that doesn't implement NPP_GetValue (like Shockwave Director 10.3 on Windows). Note that if + // WebKit copies the NPPluginFuncs struct this technique will have no effect and WebKit will + // call into our NPP_GetValue implementation. + pluginFunctions->getvalue = 0; +} + +NPError NullNPPGetValuePointer::NPP_Destroy(NPSavedData**) +{ + // Set the NPP_GetValue pointer back the way it was before we mucked with it so we don't mess + // up future uses of the plugin module. + pluginFunctions->getvalue = m_originalNPPGetValuePointer; + return NPERR_NO_ERROR; +} + +NPError NullNPPGetValuePointer::NPP_GetValue(NPPVariable, void*) +{ + pluginLog(m_npp, "NPP_GetValue was called but should not have been. Maybe WebKit copied the NPPluginFuncs struct, which would invalidate this test."); + return NPERR_GENERIC_ERROR; +} diff --git a/content/shell/tools/plugin/Tests/PassDifferentNPPStruct.cpp b/content/shell/tools/plugin/Tests/PassDifferentNPPStruct.cpp new file mode 100644 index 0000000..d78a29b --- /dev/null +++ b/content/shell/tools/plugin/Tests/PassDifferentNPPStruct.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include "PluginObject.h" + +using namespace std; + +// Passing a different NPP struct that has the same ndata value as the one passed to NPP_New should +// not trigger an assertion failure. + +class PassDifferentNPPStruct : public PluginTest { +public: + PassDifferentNPPStruct(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + , m_didReceiveInitialSetWindowCall(false) + { + } + +private: + virtual NPError NPP_SetWindow(NPWindow* window) + { + if (m_didReceiveInitialSetWindowCall) + return NPERR_NO_ERROR; + m_didReceiveInitialSetWindowCall = true; + + NPP oldNPP = m_npp; + NPP_t differentNPP = *m_npp; + m_npp = &differentNPP; + + NPBool privateMode; + NPError error = NPN_GetValue(NPNVprivateModeBool, &privateMode); + + m_npp = oldNPP; + + if (error != NPERR_NO_ERROR) { + log("NPN_GetValue(NPNVprivateModeBool) with a different NPP struct failed with error %d", error); + notifyDone(); + return NPERR_GENERIC_ERROR; + } + log("NPN_GetValue(NPNVprivateModeBool) with a different NPP struct succeeded"); + notifyDone(); + return NPERR_NO_ERROR; + } + + bool m_didReceiveInitialSetWindowCall; +}; + +static PluginTest::Register<PassDifferentNPPStruct> getValueNetscapeWindow("pass-different-npp-struct"); diff --git a/content/shell/tools/plugin/Tests/PluginScriptableNPObjectInvokeDefault.cpp b/content/shell/tools/plugin/Tests/PluginScriptableNPObjectInvokeDefault.cpp new file mode 100644 index 0000000..34d209b --- /dev/null +++ b/content/shell/tools/plugin/Tests/PluginScriptableNPObjectInvokeDefault.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +using namespace std; + +// A test where the plug-ins scriptable object either has or doesn't have an invokeDefault function. +class PluginScriptableNPObjectInvokeDefault : public PluginTest { +public: + PluginScriptableNPObjectInvokeDefault(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + struct NPObjectWithoutInvokeDefault : Object<NPObjectWithoutInvokeDefault> { }; + + struct NPObjectWithInvokeDefault : Object<NPObjectWithInvokeDefault> { + public: + bool invokeDefault(const NPVariant*, uint32_t, NPVariant* result) + { + INT32_TO_NPVARIANT(1, *result); + return true; + } + }; + + virtual NPError NPP_GetValue(NPPVariable variable, void *value) + { + if (variable != NPPVpluginScriptableNPObject) + return NPERR_GENERIC_ERROR; + + NPObject* object; + if (identifier() == "plugin-scriptable-npobject-invoke-default") + object = NPObjectWithInvokeDefault::create(this); + else + object = NPObjectWithoutInvokeDefault::create(this); + + *(NPObject**)value = object; + + return NPERR_NO_ERROR; + } +}; + +static PluginTest::Register<PluginScriptableNPObjectInvokeDefault> pluginScriptableNPObjectInvokeDefault("plugin-scriptable-npobject-invoke-default"); +static PluginTest::Register<PluginScriptableNPObjectInvokeDefault> pluginScriptableNPObjectNoInvokeDefault("plugin-scriptable-npobject-no-invoke-default"); diff --git a/content/shell/tools/plugin/Tests/PluginScriptableObjectOverridesAllProperties.cpp b/content/shell/tools/plugin/Tests/PluginScriptableObjectOverridesAllProperties.cpp new file mode 100644 index 0000000..a70d47b --- /dev/null +++ b/content/shell/tools/plugin/Tests/PluginScriptableObjectOverridesAllProperties.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include <stdio.h> +#include <string.h> + +using namespace std; + +class PluginScriptableObjectOverridesAllProperties : public PluginTest { +public: + PluginScriptableObjectOverridesAllProperties(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + class PluginObject : public Object<PluginObject> { + public: + PluginObject() + { + } + + ~PluginObject() + { + } + + bool hasProperty(NPIdentifier propertyName) + { + return true; + } + + bool getProperty(NPIdentifier propertyName, NPVariant* result) + { + static const char* message = "My name is "; + char* propertyString = pluginTest()->NPN_UTF8FromIdentifier(propertyName); + + int bufferLength = strlen(propertyString) + strlen(message) + 1; + char* resultBuffer = static_cast<char*>(pluginTest()->NPN_MemAlloc(bufferLength)); + snprintf(resultBuffer, bufferLength, "%s%s", message, propertyString); + + STRINGZ_TO_NPVARIANT(resultBuffer, *result); + + return true; + } + }; + + virtual NPError NPP_GetValue(NPPVariable variable, void *value) + { + if (variable != NPPVpluginScriptableNPObject) + return NPERR_GENERIC_ERROR; + + *(NPObject**)value = PluginObject::create(this); + + return NPERR_NO_ERROR; + } + +}; + +static PluginTest::Register<PluginScriptableObjectOverridesAllProperties> pluginScriptableObjectOverridesAllProperties("plugin-scriptable-object-overrides-all-properties"); diff --git a/content/shell/tools/plugin/Tests/SlowNPPNew.cpp b/content/shell/tools/plugin/Tests/SlowNPPNew.cpp new file mode 100644 index 0000000..8638c78 --- /dev/null +++ b/content/shell/tools/plugin/Tests/SlowNPPNew.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginTest.h" + +#include <string.h> + +using namespace std; + +class SlowNPPNew : public PluginTest { +public: + SlowNPPNew(NPP npp, const string& identifier) + : PluginTest(npp, identifier) + { + } + +private: + class PluginObject : public Object<PluginObject> { + public: + PluginObject() + { + } + + ~PluginObject() + { + } + + bool hasProperty(NPIdentifier propertyName) + { + return true; + } + + bool getProperty(NPIdentifier propertyName, NPVariant* result) + { + static const char* message = "My name is "; + char* propertyString = pluginTest()->NPN_UTF8FromIdentifier(propertyName); + + int bufferLength = strlen(propertyString) + strlen(message) + 1; + char* resultBuffer = static_cast<char*>(pluginTest()->NPN_MemAlloc(bufferLength)); + snprintf(resultBuffer, bufferLength, "%s%s", message, propertyString); + + STRINGZ_TO_NPVARIANT(resultBuffer, *result); + + return true; + } + }; + + virtual NPError NPP_GetValue(NPPVariable variable, void *value) + { + if (variable != NPPVpluginScriptableNPObject) + return NPERR_GENERIC_ERROR; + + *(NPObject**)value = PluginObject::create(this); + + return NPERR_NO_ERROR; + } + + virtual NPError NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData *saved) + { + usleep(550000); + return NPERR_NO_ERROR; + } +}; + +static PluginTest::Register<SlowNPPNew> slowNPPNew("slow-npp-new"); diff --git a/content/shell/tools/plugin/mac/Info.plist b/content/shell/tools/plugin/mac/Info.plist new file mode 100644 index 0000000..ef45e66 --- /dev/null +++ b/content/shell/tools/plugin/mac/Info.plist @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>TestNetscapePlugIn</string> + <key>CFBundleGetInfoString</key> + <string>420+, Copyright 2006-2009 Apple Inc.</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>com.apple.testnetscapeplugin</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>BRPL</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>CFPlugInDynamicRegisterFunction</key> + <string></string> + <key>CFPlugInDynamicRegistration</key> + <string>NO</string> + <key>CFPlugInFactories</key> + <dict> + <key>00000000-0000-0000-0000-000000000000</key> + <string>MyFactoryFunction</string> + </dict> + <key>CFPlugInTypes</key> + <dict> + <key>00000000-0000-0000-0000-000000000000</key> + <array> + <string>00000000-0000-0000-0000-000000000000</string> + </array> + </dict> + <key>CFPlugInUnloadFunction</key> + <string></string> + <key>WebPluginDescription</key> + <string>Simple Netscape plug-in that handles test content for WebKit</string> + <key>WebPluginMIMETypes</key> + <dict> + <key>image/png</key> + <dict> + <key>WebPluginExtensions</key> + <array> + <string>png</string> + </array> + <key>WebPluginTypeDescription</key> + <string>PNG image</string> + </dict> + <key>application/x-webkit-test-netscape</key> + <dict> + <key>WebPluginExtensions</key> + <array> + <string>testnetscape</string> + </array> + <key>WebPluginTypeDescription</key> + <string>test netscape content</string> + </dict> + </dict> + <key>WebPluginName</key> + <string>WebKit Test PlugIn</string> +</dict> +</plist> diff --git a/content/shell/tools/plugin/main.cpp b/content/shell/tools/plugin/main.cpp new file mode 100644 index 0000000..2ff58a2 --- /dev/null +++ b/content/shell/tools/plugin/main.cpp @@ -0,0 +1,879 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PluginObject.h" + +#include "PluginTest.h" +#include <cstdlib> +#include <cstring> +#include <string> + +#ifdef XP_UNIX +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#endif + +#if !defined(NP_NO_CARBON) && defined(QD_HEADERS_ARE_PRIVATE) && QD_HEADERS_ARE_PRIVATE +extern "C" void GlobalToLocal(Point*); +#endif + +using namespace std; + +#define CRASH() do { \ + *(int *)(uintptr_t)0xbbadbeef = 0; \ + ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \ +} while(false) + +static bool getEntryPointsWasCalled = false; +static bool initializeWasCalled = false; +static NPClass* pluginObjectClass = 0; + +#if defined(XP_WIN) +#define STDCALL __stdcall + +static inline int strcasecmp(const char* s1, const char* s2) +{ + return _stricmp(s1, s2); +} + +#else +#define STDCALL +#endif + +extern "C" { +NPError STDCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs); +} + +// Entry points +extern "C" +NPError STDCALL NP_Initialize(NPNetscapeFuncs *browserFuncs +#ifdef XP_UNIX + , NPPluginFuncs *pluginFuncs +#endif + ) +{ + // Create a copy of the PluginObject NPClass that we can trash on shutdown. + pluginObjectClass = createPluginClass(); + + initializeWasCalled = true; + +#if defined(XP_WIN) + // Simulate Flash and QuickTime's behavior of crashing when NP_Initialize is called before NP_GetEntryPoints. + if (!getEntryPointsWasCalled) + CRASH(); +#endif + + browser = browserFuncs; + +#ifdef XP_UNIX + return NP_GetEntryPoints(pluginFuncs); +#else + return NPERR_NO_ERROR; +#endif +} + +extern "C" +NPError STDCALL NP_GetEntryPoints(NPPluginFuncs *pluginFuncs) +{ + getEntryPointsWasCalled = true; + +#ifdef XP_MACOSX + // Simulate Silverlight's behavior of crashing when NP_GetEntryPoints is called before NP_Initialize. + if (!initializeWasCalled) + CRASH(); +#endif + + pluginFunctions = pluginFuncs; + + pluginFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; + pluginFuncs->size = sizeof(pluginFuncs); + pluginFuncs->newp = NPP_New; + pluginFuncs->destroy = NPP_Destroy; + pluginFuncs->setwindow = NPP_SetWindow; + pluginFuncs->newstream = NPP_NewStream; + pluginFuncs->destroystream = NPP_DestroyStream; + pluginFuncs->asfile = NPP_StreamAsFile; + pluginFuncs->writeready = NPP_WriteReady; + pluginFuncs->write = (NPP_WriteProcPtr)NPP_Write; + pluginFuncs->print = NPP_Print; + pluginFuncs->event = NPP_HandleEvent; + pluginFuncs->urlnotify = NPP_URLNotify; + pluginFuncs->getvalue = NPP_GetValue; + pluginFuncs->setvalue = NPP_SetValue; + + return NPERR_NO_ERROR; +} + +extern "C" +void STDCALL NP_Shutdown(void) +{ + // Trash the PluginObject NPClass so that the process will deterministically + // crash if Blink tries to call into the plugin's NPObjects after unloading + // it, rather than relying on OS-specific DLL unload behaviour. + // Note that we leak the NPClass copy, to act as a guard for the lifetime of + // the process. + memset(pluginObjectClass, 0xf00dbeef, sizeof(NPClass)); + + PluginTest::NP_Shutdown(); +} + +static void executeScript(const PluginObject* obj, const char* script); + +NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc, char *argn[], char *argv[], NPSavedData *saved) +{ +#ifdef XP_MACOSX + NPEventModel eventModel; + + // Always turn on the CG model + NPBool supportsCoreGraphics; + if (browser->getvalue(instance, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics) != NPERR_NO_ERROR) + supportsCoreGraphics = false; + + if (!supportsCoreGraphics) + return NPERR_INCOMPATIBLE_VERSION_ERROR; + + NPDrawingModel drawingModelToUse = NPDrawingModelCoreGraphics; + + NPBool supportsCoreAnimation; + if (browser->getvalue(instance, NPNVsupportsCoreAnimationBool, &supportsCoreAnimation) != NPERR_NO_ERROR) + supportsCoreAnimation = false; + +#ifndef NP_NO_CARBON + NPBool supportsCarbon = false; +#endif + NPBool supportsCocoa = false; + +#ifndef NP_NO_CARBON + // A browser that doesn't know about NPNVsupportsCarbonBool is one that only supports Carbon event model. + if (browser->getvalue(instance, NPNVsupportsCarbonBool, &supportsCarbon) != NPERR_NO_ERROR) + supportsCarbon = true; +#endif + + if (browser->getvalue(instance, NPNVsupportsCocoaBool, &supportsCocoa) != NPERR_NO_ERROR) + supportsCocoa = false; + + if (supportsCocoa) { + eventModel = NPEventModelCocoa; +#ifndef NP_NO_CARBON + } else if (supportsCarbon) { + eventModel = NPEventModelCarbon; +#endif + } else { + return NPERR_INCOMPATIBLE_VERSION_ERROR; + } + + browser->setvalue(instance, NPPVpluginEventModel, (void *)eventModel); +#endif // XP_MACOSX + + PluginObject* obj = (PluginObject*)browser->createobject(instance, pluginObjectClass); + instance->pdata = obj; + +#ifdef XP_MACOSX + obj->eventModel = eventModel; + obj->coreAnimationLayer = 0; +#endif // XP_MACOSX + + string testIdentifier; + const char* onNewScript = 0; + + for (int i = 0; i < argc; i++) { + if (strcasecmp(argn[i], "test") == 0) + testIdentifier = argv[i]; + if (strcasecmp(argn[i], "onstreamload") == 0 && !obj->onStreamLoad) + obj->onStreamLoad = strdup(argv[i]); + else if (strcasecmp(argn[i], "onStreamDestroy") == 0 && !obj->onStreamDestroy) + obj->onStreamDestroy = strdup(argv[i]); + else if (strcasecmp(argn[i], "onURLNotify") == 0 && !obj->onURLNotify) + obj->onURLNotify = strdup(argv[i]); + else if (strcasecmp(argn[i], "src") == 0 && + strcasecmp(argv[i], "data:application/x-webkit-test-netscape,returnerrorfromnewstream") == 0) + obj->returnErrorFromNewStream = true; + else if (strcasecmp(argn[i], "src") == 0 && + strcasecmp(argv[i], "data:application/x-webkit-test-netscape,alertwhenloaded") == 0) + executeScript(obj, "alert('Plugin Loaded!')"); + else if (strcasecmp(argn[i], "src") == 0 && + strcasecmp(argv[i], "data:application/x-webkit-test-netscape,logifloaded") == 0) { + for (int j = 0; j < argc; j++) { + if (strcasecmp(argn[j], "log") == 0) { + int length = 26 + strlen(argv[j]) + 1; + char* buffer = (char*) malloc(length); + snprintf(buffer, length, "xWebkitTestNetscapeLog('%s')", argv[j]); + executeScript(obj, buffer); + free(buffer); + } + } + } else if (strcasecmp(argn[i], "onSetWindow") == 0 && !obj->onSetWindow) + obj->onSetWindow = strdup(argv[i]); + else if (strcasecmp(argn[i], "onNew") == 0 && !onNewScript) + onNewScript = argv[i]; + else if (strcasecmp(argn[i], "onPaintEvent") == 0 && !obj->onPaintEvent) + obj->onPaintEvent = strdup(argv[i]); + else if (strcasecmp(argn[i], "logfirstsetwindow") == 0) + obj->logSetWindow = true; + else if (strcasecmp(argn[i], "testnpruntime") == 0) + testNPRuntime(instance); + else if (strcasecmp(argn[i], "logSrc") == 0) { + for (int i = 0; i < argc; i++) + if (strcasecmp(argn[i], "src") == 0) + pluginLog(instance, "src: %s", argv[i]); + } else if (strcasecmp(argn[i], "cleardocumentduringnew") == 0) + executeScript(obj, "document.body.innerHTML = ''"); + else if (!strcasecmp(argn[i], "ondestroy")) + obj->onDestroy = strdup(argv[i]); + else if (strcasecmp(argn[i], "testwindowopen") == 0) + obj->testWindowOpen = true; + else if (strcasecmp(argn[i], "drawingmodel") == 0) { +#ifdef XP_MACOSX + const char* value = argv[i]; + if (strcasecmp(value, "coreanimation") == 0) { + if (supportsCoreAnimation) + drawingModelToUse = NPDrawingModelCoreAnimation; + else + return NPERR_INCOMPATIBLE_VERSION_ERROR; + } else if (strcasecmp(value, "coregraphics") == 0) { + if (supportsCoreGraphics) + drawingModelToUse = NPDrawingModelCoreGraphics; + else + return NPERR_INCOMPATIBLE_VERSION_ERROR; + } else + return NPERR_INCOMPATIBLE_VERSION_ERROR; +#endif + } else if (strcasecmp(argn[i], "testGetURLOnDestroy") == 0) { +#if defined(XP_WIN) + // FIXME: When https://bugs.webkit.org/show_bug.cgi?id=41831 is fixed, this #ifdef can be removed. + obj->testGetURLOnDestroy = TRUE; +#endif + } else if (!strcasecmp(argn[i], "src") && strstr(argv[i], "plugin-document-has-focus.pl")) + obj->testKeyboardFocusForPlugins = true; + else if (!strcasecmp(argn[i], "evaluatescript")) { + char* script = argv[i]; + if (script == strstr(script, "mouse::")) { + obj->mouseDownForEvaluateScript = true; + obj->evaluateScriptOnMouseDownOrKeyDown = strdup(script + sizeof("mouse::") - 1); + } else if (script == strstr(script, "key::")) { + obj->evaluateScriptOnMouseDownOrKeyDown = strdup(script + sizeof("key::") - 1); + } + // When testing evaluate script on mouse-down or key-down, allow event logging to handle events. + if (obj->evaluateScriptOnMouseDownOrKeyDown) + obj->eventLogging = true; + } else if (!strcasecmp(argn[i], "windowedPlugin")) { + void* windowed = 0; + if (!strcasecmp(argv[i], "false") || !strcasecmp(argv[i], "0")) + windowed = 0; + else if (!strcasecmp(argv[i], "true") || !strcasecmp(argv[i], "1")) + windowed = reinterpret_cast<void*>(1); + else + assert(false); + browser->setvalue(instance, NPPVpluginWindowBool, windowed); + } + } + +#ifdef XP_MACOSX + browser->setvalue(instance, NPPVpluginDrawingModel, (void *)drawingModelToUse); + if (drawingModelToUse == NPDrawingModelCoreAnimation) + obj->coreAnimationLayer = createCoreAnimationLayer(); +#endif + + obj->pluginTest = PluginTest::create(instance, testIdentifier); + + if (!obj->pluginTest) { + pluginLog(instance, "NPP_New: Could not find a test named \"%s\", maybe its .cpp file wasn't added to the build system?", testIdentifier.c_str()); + return NPERR_GENERIC_ERROR; + } + + if (onNewScript) + executeScript(obj, onNewScript); + + return obj->pluginTest->NPP_New(pluginType, mode, argc, argn, argv, saved); +} + +NPError NPP_Destroy(NPP instance, NPSavedData **save) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + + if (obj) { + if (obj->testGetURLOnDestroy) + browser->geturlnotify(obj->npp, "about:blank", "", 0); + + if (obj->onDestroy) { + executeScript(obj, obj->onDestroy); + free(obj->onDestroy); + } + + if (obj->onStreamLoad) + free(obj->onStreamLoad); + + if (obj->onStreamDestroy) + free(obj->onStreamDestroy); + + if (obj->onURLNotify) + free(obj->onURLNotify); + + if (obj->onSetWindow) + free(obj->onSetWindow); + + if (obj->onPaintEvent) + free(obj->onPaintEvent); + + if (obj->evaluateScriptOnMouseDownOrKeyDown) + free(obj->evaluateScriptOnMouseDownOrKeyDown); + + if (obj->logDestroy) + pluginLog(instance, "NPP_Destroy"); + +#ifdef XP_MACOSX + if (obj->coreAnimationLayer) + CFRelease(obj->coreAnimationLayer); +#endif + + if (obj->pluginTest) + obj->pluginTest->NPP_Destroy(save); + + browser->releaseobject(&obj->header); + } + return NPERR_NO_ERROR; +} + +NPError NPP_SetWindow(NPP instance, NPWindow *window) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + + if (obj) { + obj->lastWindow = *window; + + if (obj->logSetWindow) { + pluginLog(instance, "NPP_SetWindow: %d %d", (int)window->width, (int)window->height); + obj->logSetWindow = false; + executeScript(obj, "testRunner.notifyDone();"); + } + + if (obj->onSetWindow) + executeScript(obj, obj->onSetWindow); + + if (obj->testWindowOpen) { + testWindowOpen(instance); + obj->testWindowOpen = false; + } + + if (obj->testKeyboardFocusForPlugins) { + obj->eventLogging = true; + executeScript(obj, "eventSender.keyDown('A');"); + } + } + + return obj->pluginTest->NPP_SetWindow(window); +} + +static void executeScript(const PluginObject* obj, const char* script) +{ + NPObject *windowScriptObject; + browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); + + NPString npScript; + npScript.UTF8Characters = script; + npScript.UTF8Length = strlen(script); + + NPVariant browserResult; + browser->evaluate(obj->npp, windowScriptObject, &npScript, &browserResult); + browser->releasevariantvalue(&browserResult); +} + +NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream *stream, NPBool seekable, uint16_t *stype) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + obj->stream = stream; + *stype = NP_NORMAL; + + if (obj->returnErrorFromNewStream) + return NPERR_GENERIC_ERROR; + + if (browser->version >= NPVERS_HAS_RESPONSE_HEADERS) + notifyStream(obj, stream->url, stream->headers); + + if (obj->onStreamLoad) + executeScript(obj, obj->onStreamLoad); + + return obj->pluginTest->NPP_NewStream(type, stream, seekable, stype); +} + +NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) +{ + PluginObject* obj = (PluginObject*)instance->pdata; + + if (obj->onStreamDestroy) { + NPObject* windowObject = 0; + NPError error = browser->getvalue(instance, NPNVWindowNPObject, &windowObject); + + if (error == NPERR_NO_ERROR) { + NPVariant onStreamDestroyVariant; + if (browser->getproperty(instance, windowObject, browser->getstringidentifier(obj->onStreamDestroy), &onStreamDestroyVariant)) { + if (NPVARIANT_IS_OBJECT(onStreamDestroyVariant)) { + NPObject* onStreamDestroyFunction = NPVARIANT_TO_OBJECT(onStreamDestroyVariant); + + NPVariant reasonVariant; + INT32_TO_NPVARIANT(reason, reasonVariant); + + NPVariant result; + browser->invokeDefault(instance, onStreamDestroyFunction, &reasonVariant, 1, &result); + browser->releasevariantvalue(&result); + } + browser->releasevariantvalue(&onStreamDestroyVariant); + } + browser->releaseobject(windowObject); + } + } + + return obj->pluginTest->NPP_DestroyStream(stream, reason); +} + +int32_t NPP_WriteReady(NPP instance, NPStream *stream) +{ + PluginObject* obj = (PluginObject*)instance->pdata; + return obj->pluginTest->NPP_WriteReady(stream); +} + +int32_t NPP_Write(NPP instance, NPStream *stream, int32_t offset, int32_t len, void *buffer) +{ + PluginObject* obj = (PluginObject*)instance->pdata; + + if (obj->returnNegativeOneFromWrite) + return -1; + + return obj->pluginTest->NPP_Write(stream, offset, len, buffer); +} + +void NPP_StreamAsFile(NPP instance, NPStream *stream, const char *fname) +{ +} + +void NPP_Print(NPP instance, NPPrint *platformPrint) +{ +} + +#ifdef XP_MACOSX +#ifndef NP_NO_CARBON +static int16_t handleEventCarbon(NPP instance, PluginObject* obj, EventRecord* event) +{ + Point pt = { event->where.v, event->where.h }; + + switch (event->what) { + case nullEvent: + // these are delivered non-deterministically, don't log. + break; + case mouseDown: + if (obj->eventLogging) { +#if __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + GlobalToLocal(&pt); +#if __clang__ +#pragma clang diagnostic pop +#endif + pluginLog(instance, "mouseDown at (%d, %d)", pt.h, pt.v); + } + if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); + break; + case mouseUp: + if (obj->eventLogging) { +#if __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + GlobalToLocal(&pt); +#if __clang__ +#pragma clang diagnostic pop +#endif + pluginLog(instance, "mouseUp at (%d, %d)", pt.h, pt.v); + } + break; + case keyDown: + if (obj->eventLogging) + pluginLog(instance, "keyDown '%c'", (char)(event->message & 0xFF)); + if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); + break; + case keyUp: + if (obj->eventLogging) + pluginLog(instance, "keyUp '%c'", (char)(event->message & 0xFF)); + if (obj->testKeyboardFocusForPlugins) { + obj->eventLogging = false; + obj->testKeyboardFocusForPlugins = FALSE; + executeScript(obj, "testRunner.notifyDone();"); + } + break; + case autoKey: + if (obj->eventLogging) + pluginLog(instance, "autoKey '%c'", (char)(event->message & 0xFF)); + break; + case updateEvt: + if (obj->eventLogging) + pluginLog(instance, "updateEvt"); + break; + case diskEvt: + if (obj->eventLogging) + pluginLog(instance, "diskEvt"); + break; + case activateEvt: + if (obj->eventLogging) + pluginLog(instance, "activateEvt"); + break; + case osEvt: + if (!obj->eventLogging) + break; + printf("PLUGIN: osEvt - "); + switch ((event->message & 0xFF000000) >> 24) { + case suspendResumeMessage: + printf("%s\n", (event->message & 0x1) ? "resume" : "suspend"); + break; + case mouseMovedMessage: + printf("mouseMoved\n"); + break; + default: + printf("%08lX\n", event->message); + } + break; + case kHighLevelEvent: + if (obj->eventLogging) + pluginLog(instance, "kHighLevelEvent"); + break; + // NPAPI events + case NPEventType_GetFocusEvent: + if (obj->eventLogging) + pluginLog(instance, "getFocusEvent"); + break; + case NPEventType_LoseFocusEvent: + if (obj->eventLogging) + pluginLog(instance, "loseFocusEvent"); + break; + case NPEventType_AdjustCursorEvent: + if (obj->eventLogging) + pluginLog(instance, "adjustCursorEvent"); + break; + default: + if (obj->eventLogging) + pluginLog(instance, "event %d", event->what); + } + + return 0; +} +#endif + +static int16_t handleEventCocoa(NPP instance, PluginObject* obj, NPCocoaEvent* event) +{ + switch (event->type) { + case NPCocoaEventWindowFocusChanged: + + case NPCocoaEventFocusChanged: + if (obj->eventLogging) { + if (event->data.focus.hasFocus) + pluginLog(instance, "getFocusEvent"); + else + pluginLog(instance, "loseFocusEvent"); + } + return 1; + + case NPCocoaEventDrawRect: { + if (obj->onPaintEvent) + executeScript(obj, obj->onPaintEvent); + return 1; + } + + case NPCocoaEventKeyDown: + if (obj->eventLogging && event->data.key.characters) + pluginLog(instance, "keyDown '%c'", CFStringGetCharacterAtIndex(reinterpret_cast<CFStringRef>(event->data.key.characters), 0)); + if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); + return 1; + + case NPCocoaEventKeyUp: + if (obj->eventLogging && event->data.key.characters) { + pluginLog(instance, "keyUp '%c'", CFStringGetCharacterAtIndex(reinterpret_cast<CFStringRef>(event->data.key.characters), 0)); + if (obj->testKeyboardFocusForPlugins) { + obj->eventLogging = false; + obj->testKeyboardFocusForPlugins = FALSE; + executeScript(obj, "testRunner.notifyDone();"); + } + } + return 1; + + case NPCocoaEventFlagsChanged: + return 1; + + case NPCocoaEventMouseDown: + if (obj->eventLogging) { + pluginLog(instance, "mouseDown at (%d, %d)", + (int)event->data.mouse.pluginX, + (int)event->data.mouse.pluginY); + } + if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); + return 1; + case NPCocoaEventMouseUp: + if (obj->eventLogging) { + pluginLog(instance, "mouseUp at (%d, %d)", + (int)event->data.mouse.pluginX, + (int)event->data.mouse.pluginY); + } + return 1; + + case NPCocoaEventMouseMoved: + case NPCocoaEventMouseEntered: + case NPCocoaEventMouseExited: + case NPCocoaEventMouseDragged: + case NPCocoaEventScrollWheel: + case NPCocoaEventTextInput: + return 1; + } + + return 0; +} + +#endif // XP_MACOSX + +#ifdef XP_UNIX + +static char keyEventToChar(XKeyEvent* event) +{ + char c = ' '; + XLookupString(event, &c, sizeof(c), 0, 0); + return c; +} + +static int16_t handleEventX11(NPP instance, PluginObject* obj, XEvent* event) +{ + switch (event->type) { + case ButtonPress: + if (obj->eventLogging) + pluginLog(instance, "mouseDown at (%d, %d)", event->xbutton.x, event->xbutton.y); + if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); + break; + case ButtonRelease: + if (obj->eventLogging) + pluginLog(instance, "mouseUp at (%d, %d)", event->xbutton.x, event->xbutton.y); + break; + case KeyPress: + // FIXME: extract key code + if (obj->eventLogging) + pluginLog(instance, "keyDown '%c'", keyEventToChar(&event->xkey)); + if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); + break; + case KeyRelease: + // FIXME: extract key code + if (obj->eventLogging) + pluginLog(instance, "keyUp '%c'", keyEventToChar(&event->xkey)); + if (obj->testKeyboardFocusForPlugins) { + obj->eventLogging = false; + obj->testKeyboardFocusForPlugins = false; + executeScript(obj, "testRunner.notifyDone();"); + } + break; + case GraphicsExpose: + if (obj->eventLogging) + pluginLog(instance, "updateEvt"); + if (obj->onPaintEvent) + executeScript(obj, obj->onPaintEvent); + break; + // NPAPI events + case FocusIn: + if (obj->eventLogging) + pluginLog(instance, "getFocusEvent"); + break; + case FocusOut: + if (obj->eventLogging) + pluginLog(instance, "loseFocusEvent"); + break; + case EnterNotify: + case LeaveNotify: + case MotionNotify: + break; + default: + if (obj->eventLogging) + pluginLog(instance, "event %d", event->type); + } + + fflush(stdout); + return 0; +} +#endif // XP_UNIX + +#ifdef XP_WIN +static int16_t handleEventWin(NPP instance, PluginObject* obj, NPEvent* event) +{ + switch (event->event) { + case WM_PAINT: + if (obj->onPaintEvent) + executeScript(obj, obj->onPaintEvent); + break; + case WM_KEYDOWN: + if (obj->eventLogging) + pluginLog(instance, "keyDown '%c'", event->wParam); + if (obj->evaluateScriptOnMouseDownOrKeyDown && !obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); + break; + case WM_CHAR: + break; + case WM_KEYUP: + if (obj->eventLogging) + pluginLog(instance, "keyUp '%c'", event->wParam); + if (obj->testKeyboardFocusForPlugins) { + obj->eventLogging = false; + obj->testKeyboardFocusForPlugins = FALSE; + executeScript(obj, "testRunner.notifyDone();"); + } + break; + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + if (obj->eventLogging) + pluginLog(instance, "mouseDown at (%d, %d)", LOWORD(event->lParam), HIWORD(event->lParam)); + if (obj->evaluateScriptOnMouseDownOrKeyDown && obj->mouseDownForEvaluateScript) + executeScript(obj, obj->evaluateScriptOnMouseDownOrKeyDown); + break; + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + if (obj->eventLogging) + pluginLog(instance, "mouseUp at (%d, %d)", LOWORD(event->lParam), HIWORD(event->lParam)); + break; + case WM_SETFOCUS: + if (obj->eventLogging) + pluginLog(instance, "getFocusEvent"); + break; + case WM_KILLFOCUS: + if (obj->eventLogging) + pluginLog(instance, "loseFocusEvent"); + break; + } + return 0; +} +#endif // XP_WIN + +int16_t NPP_HandleEvent(NPP instance, void *event) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + + if (obj->pluginTest->NPP_HandleEvent(event) == 1) + return 1; + +#ifdef XP_MACOSX +#ifndef NP_NO_CARBON + if (obj->eventModel == NPEventModelCarbon) + return handleEventCarbon(instance, obj, static_cast<EventRecord*>(event)); +#endif + + assert(obj->eventModel == NPEventModelCocoa); + return handleEventCocoa(instance, obj, static_cast<NPCocoaEvent*>(event)); +#elif defined(XP_UNIX) + return handleEventX11(instance, obj, static_cast<XEvent*>(event)); +#elif defined(XP_WIN) + return handleEventWin(instance, obj, static_cast<NPEvent*>(event)); +#else + // FIXME: Implement for other platforms. + return 0; +#endif // XP_MACOSX +} + +void NPP_URLNotify(NPP instance, const char *url, NPReason reason, void *notifyData) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + if (obj->pluginTest->NPP_URLNotify(url, reason, notifyData)) + return; + + if (obj->onURLNotify) + executeScript(obj, obj->onURLNotify); + + handleCallback(obj, url, reason, notifyData); +} + +NPError NPP_GetValue(NPP instance, NPPVariable variable, void *value) +{ +#ifdef XP_UNIX + if (variable == NPPVpluginNameString) { + *((char **)value) = const_cast<char*>("WebKit Test PlugIn"); + return NPERR_NO_ERROR; + } + if (variable == NPPVpluginDescriptionString) { + *((char **)value) = const_cast<char*>("Simple Netscape® plug-in that handles test content for WebKit"); + return NPERR_NO_ERROR; + } + if (variable == NPPVpluginNeedsXEmbed) { + *((NPBool *)value) = true; + return NPERR_NO_ERROR; + } +#endif + + if (!instance) + return NPERR_GENERIC_ERROR; + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + + // First, check if the PluginTest object supports getting this value. + if (obj->pluginTest->NPP_GetValue(variable, value) == NPERR_NO_ERROR) + return NPERR_NO_ERROR; + + if (variable == NPPVpluginScriptableNPObject) { + void **v = (void **)value; + // Return value is expected to be retained + browser->retainobject((NPObject *)obj); + *v = obj; + return NPERR_NO_ERROR; + } + +#ifdef XP_MACOSX + if (variable == NPPVpluginCoreAnimationLayer) { + if (!obj->coreAnimationLayer) + return NPERR_GENERIC_ERROR; + + void **v = (void **)value; + *v = (void*)CFRetain(obj->coreAnimationLayer); + return NPERR_NO_ERROR; + } +#endif + + return NPERR_GENERIC_ERROR; +} + +NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) +{ + PluginObject* obj = static_cast<PluginObject*>(instance->pdata); + return obj->pluginTest->NPP_SetValue(variable, value); +} + +#ifdef XP_UNIX +extern "C" +const char* NP_GetMIMEDescription(void) +{ + return "application/x-webkit-test-netscape:testnetscape:test netscape content;image/png:png:PNG image"; +} + +extern "C" +NPError NP_GetValue(NPP instance, NPPVariable variable, void* value) +{ + return NPP_GetValue(instance, variable, value); +} +#endif diff --git a/content/shell/tools/plugin/win/TestNetscapePlugin.def b/content/shell/tools/plugin/win/TestNetscapePlugin.def new file mode 100644 index 0000000..313aea9 --- /dev/null +++ b/content/shell/tools/plugin/win/TestNetscapePlugin.def @@ -0,0 +1,6 @@ +LIBRARY "npTestNetscapePlugin" + +EXPORTS + NP_GetEntryPoints @1 + NP_Initialize @2 + NP_Shutdown @3 diff --git a/content/shell/tools/plugin/win/TestNetscapePlugin.rc b/content/shell/tools/plugin/win/TestNetscapePlugin.rc new file mode 100644 index 0000000..a9446c9 --- /dev/null +++ b/content/shell/tools/plugin/win/TestNetscapePlugin.rc @@ -0,0 +1,102 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "windows.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""windows.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "Apple Inc." + VALUE "FileDescription", "Simple Netscape plug-in that handles test content for WebKit" + VALUE "FileExtents", "testnetscape|png" + VALUE "FileOpenName", "test netscape content|PNG image" + VALUE "LegalCopyright", "Copyright Apple Inc. 2007-2009" + VALUE "MIMEType", "application/x-webkit-test-netscape|image/png" + VALUE "OriginalFilename", "npTestNetscapePlugin.dll" + VALUE "ProductName", "WebKit Test PlugIn" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/content/shell/tools/plugin/win/TestNetscapePlugin_debug.def b/content/shell/tools/plugin/win/TestNetscapePlugin_debug.def new file mode 100644 index 0000000..158fb7c --- /dev/null +++ b/content/shell/tools/plugin/win/TestNetscapePlugin_debug.def @@ -0,0 +1,6 @@ +LIBRARY "npTestNetscapePlugin_debug" + +EXPORTS + NP_GetEntryPoints @1 + NP_Initialize @2 + NP_Shutdown @3 diff --git a/content/shell/tools/plugin/win/resource.h b/content/shell/tools/plugin/win/resource.h new file mode 100644 index 0000000..7aa780f --- /dev/null +++ b/content/shell/tools/plugin/win/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by TestNetscapePlugin.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif |