summaryrefslogtreecommitdiffstats
path: root/content/shell/tools
diff options
context:
space:
mode:
authortfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-19 23:33:01 +0000
committertfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-19 23:33:01 +0000
commit7eb2cf4ef217ad37cb5ec07c626eef549ceaa964 (patch)
tree2484d5ab8eae032c82fb7d2358e6192000e6a6ea /content/shell/tools
parent0443652a79d75dc7bb76eab68c827b20a8b7d30b (diff)
downloadchromium_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')
-rw-r--r--content/shell/tools/plugin/PluginObject.cpp1478
-rw-r--r--content/shell/tools/plugin/PluginObject.h96
-rw-r--r--content/shell/tools/plugin/PluginObjectMac.mm107
-rw-r--r--content/shell/tools/plugin/PluginTest.cpp271
-rw-r--r--content/shell/tools/plugin/PluginTest.h300
-rw-r--r--content/shell/tools/plugin/TestObject.cpp205
-rw-r--r--content/shell/tools/plugin/TestObject.h30
-rw-r--r--content/shell/tools/plugin/Tests/DocumentOpenInDestroyStream.cpp56
-rw-r--r--content/shell/tools/plugin/Tests/EvaluateJSAfterRemovingPluginElement.cpp64
-rw-r--r--content/shell/tools/plugin/Tests/EvaluateJSWithinNPP_New.cpp56
-rw-r--r--content/shell/tools/plugin/Tests/FormValue.cpp53
-rw-r--r--content/shell/tools/plugin/Tests/GetURLNotifyWithURLThatFailsToLoad.cpp72
-rw-r--r--content/shell/tools/plugin/Tests/GetURLWithJavaScriptURL.cpp112
-rw-r--r--content/shell/tools/plugin/Tests/GetURLWithJavaScriptURLDestroyingPlugin.cpp48
-rw-r--r--content/shell/tools/plugin/Tests/GetUserAgentWithNullNPPFromNPPNew.cpp54
-rw-r--r--content/shell/tools/plugin/Tests/InvokeDestroysPluginWithinNPP_New.cpp67
-rw-r--r--content/shell/tools/plugin/Tests/LeakWindowScriptableObject.cpp64
-rw-r--r--content/shell/tools/plugin/Tests/LogNPPSetWindow.cpp61
-rw-r--r--content/shell/tools/plugin/Tests/NPDeallocateCalledBeforeNPShutdown.cpp94
-rw-r--r--content/shell/tools/plugin/Tests/NPPNewFails.cpp47
-rw-r--r--content/shell/tools/plugin/Tests/NPPSetWindowCalledDuringDestruction.cpp125
-rw-r--r--content/shell/tools/plugin/Tests/NPRuntimeCallsWithNullNPP.cpp66
-rw-r--r--content/shell/tools/plugin/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp88
-rw-r--r--content/shell/tools/plugin/Tests/NPRuntimeRemoveProperty.cpp170
-rw-r--r--content/shell/tools/plugin/Tests/NullNPPGetValuePointer.cpp70
-rw-r--r--content/shell/tools/plugin/Tests/PassDifferentNPPStruct.cpp72
-rw-r--r--content/shell/tools/plugin/Tests/PluginScriptableNPObjectInvokeDefault.cpp68
-rw-r--r--content/shell/tools/plugin/Tests/PluginScriptableObjectOverridesAllProperties.cpp83
-rw-r--r--content/shell/tools/plugin/Tests/SlowNPPNew.cpp87
-rw-r--r--content/shell/tools/plugin/mac/Info.plist69
-rw-r--r--content/shell/tools/plugin/main.cpp879
-rw-r--r--content/shell/tools/plugin/win/TestNetscapePlugin.def6
-rw-r--r--content/shell/tools/plugin/win/TestNetscapePlugin.rc102
-rw-r--r--content/shell/tools/plugin/win/TestNetscapePlugin_debug.def6
-rw-r--r--content/shell/tools/plugin/win/resource.h14
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