diff options
11 files changed, 175 insertions, 41 deletions
diff --git a/webkit/data/layout_tests/platform/chromium-linux/LayoutTests/plugins/document-open-expected.txt b/webkit/data/layout_tests/platform/chromium-linux/LayoutTests/plugins/document-open-expected.txt new file mode 100644 index 0000000..5c32f92 --- /dev/null +++ b/webkit/data/layout_tests/platform/chromium-linux/LayoutTests/plugins/document-open-expected.txt @@ -0,0 +1 @@ +CONSOLE MESSAGE: line 1: PLUGIN: DOCUMENT OPEN SUCCESS diff --git a/webkit/data/layout_tests/platform/chromium-linux/LayoutTests/plugins/window-open-expected.txt b/webkit/data/layout_tests/platform/chromium-linux/LayoutTests/plugins/window-open-expected.txt new file mode 100644 index 0000000..29ee4e7 --- /dev/null +++ b/webkit/data/layout_tests/platform/chromium-linux/LayoutTests/plugins/window-open-expected.txt @@ -0,0 +1,3 @@ +CONSOLE MESSAGE: line 1: PLUGIN: WINDOW OPEN SUCCESS + +This tests that window.open invoked by a plugin via NPN_Invoke without a javascript context succeeds. diff --git a/webkit/data/layout_tests/platform/chromium-mac/LayoutTests/plugins/document-open-expected.txt b/webkit/data/layout_tests/platform/chromium-mac/LayoutTests/plugins/document-open-expected.txt new file mode 100644 index 0000000..5c32f92 --- /dev/null +++ b/webkit/data/layout_tests/platform/chromium-mac/LayoutTests/plugins/document-open-expected.txt @@ -0,0 +1 @@ +CONSOLE MESSAGE: line 1: PLUGIN: DOCUMENT OPEN SUCCESS diff --git a/webkit/data/layout_tests/platform/chromium-mac/LayoutTests/plugins/window-open-expected.txt b/webkit/data/layout_tests/platform/chromium-mac/LayoutTests/plugins/window-open-expected.txt new file mode 100644 index 0000000..29ee4e7 --- /dev/null +++ b/webkit/data/layout_tests/platform/chromium-mac/LayoutTests/plugins/window-open-expected.txt @@ -0,0 +1,3 @@ +CONSOLE MESSAGE: line 1: PLUGIN: WINDOW OPEN SUCCESS + +This tests that window.open invoked by a plugin via NPN_Invoke without a javascript context succeeds. diff --git a/webkit/data/layout_tests/platform/chromium-win/LayoutTests/plugins/document-open-expected.txt b/webkit/data/layout_tests/platform/chromium-win/LayoutTests/plugins/document-open-expected.txt new file mode 100644 index 0000000..5c32f92 --- /dev/null +++ b/webkit/data/layout_tests/platform/chromium-win/LayoutTests/plugins/document-open-expected.txt @@ -0,0 +1 @@ +CONSOLE MESSAGE: line 1: PLUGIN: DOCUMENT OPEN SUCCESS diff --git a/webkit/data/layout_tests/platform/chromium-win/LayoutTests/plugins/window-open-expected.txt b/webkit/data/layout_tests/platform/chromium-win/LayoutTests/plugins/window-open-expected.txt new file mode 100644 index 0000000..29ee4e7 --- /dev/null +++ b/webkit/data/layout_tests/platform/chromium-win/LayoutTests/plugins/window-open-expected.txt @@ -0,0 +1,3 @@ +CONSOLE MESSAGE: line 1: PLUGIN: WINDOW OPEN SUCCESS + +This tests that window.open invoked by a plugin via NPN_Invoke without a javascript context succeeds. diff --git a/webkit/glue/plugins/plugin_stream_url.cc b/webkit/glue/plugins/plugin_stream_url.cc index ae26e62..602733d 100644 --- a/webkit/glue/plugins/plugin_stream_url.cc +++ b/webkit/glue/plugins/plugin_stream_url.cc @@ -29,6 +29,9 @@ PluginStreamUrl::~PluginStreamUrl() { } bool PluginStreamUrl::Close(NPReason reason) { + // Protect the stream against it being destroyed or the whole plugin instance + // being destroyed within the destroy stream handler. + scoped_refptr<PluginStream> protect(this); CancelRequest(); bool result = PluginStream::Close(reason); instance()->RemoveStream(this); @@ -45,6 +48,10 @@ void PluginStreamUrl::DidReceiveResponse(const std::string& mime_type, uint32 expected_length, uint32 last_modified, bool request_is_seekable) { + // Protect the stream against it being destroyed or the whole plugin instance + // being destroyed within the new stream handler. + scoped_refptr<PluginStream> protect(this); + bool opened = Open(mime_type, headers, expected_length, @@ -64,6 +71,10 @@ void PluginStreamUrl::DidReceiveData(const char* buffer, int length, if (!open()) return; + // Protect the stream against it being destroyed or the whole plugin instance + // being destroyed within the write handlers + scoped_refptr<PluginStream> protect(this); + if (length > 0) { // The PluginStreamUrl instance could get deleted if the plugin fails to // accept data in NPP_Write. diff --git a/webkit/glue/plugins/plugin_string_stream.cc b/webkit/glue/plugins/plugin_string_stream.cc index 3997fba..f174267 100644 --- a/webkit/glue/plugins/plugin_string_stream.cc +++ b/webkit/glue/plugins/plugin_string_stream.cc @@ -21,6 +21,10 @@ PluginStringStream::~PluginStringStream() { void PluginStringStream::SendToPlugin(const std::string &data, const std::string &mime_type) { + // Protect the stream against it being destroyed or the whole plugin instance + // being destroyed within the plugin stream callbacks. + scoped_refptr<PluginStringStream> protect(this); + int length = static_cast<int>(data.length()); if (Open(mime_type, std::string(), length, 0, false)) { // TODO - check if it was not fully sent, and figure out a backup plan. diff --git a/webkit/tools/npapi_layout_test_plugin/PluginObject.cpp b/webkit/tools/npapi_layout_test_plugin/PluginObject.cpp index f06e099..922faf3 100644 --- a/webkit/tools/npapi_layout_test_plugin/PluginObject.cpp +++ b/webkit/tools/npapi_layout_test_plugin/PluginObject.cpp @@ -33,6 +33,60 @@ #define snprintf sprintf_s #endif +static void logWithWindowObject(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); +} + +static void logWithWindowObjectVariableArgs(NPObject* windowObject, NPP instance, const char* format, ...) +{ + va_list args; + va_start(args, format); + char message[2048] = "PLUGIN: "; + vsprintf(message + strlen(message), format, args); + va_end(args); + + logWithWindowObject(windowObject, instance, message); +} + +void log(NPP instance, const char* format, ...) +{ + va_list args; + va_start(args, format); + char message[2048] = "PLUGIN: "; + vsprintf(message + strlen(message), format, args); + va_end(args); + + 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; + } + + logWithWindowObject(windowObject, instance, message); + browser->releaseobject(windowObject); +} + static void pluginInvalidate(NPObject*); static bool pluginHasProperty(NPObject*, NPIdentifier name); static bool pluginHasMethod(NPObject*, NPIdentifier name); @@ -629,6 +683,76 @@ static bool testConstruct(PluginObject* obj, const NPVariant* args, uint32_t arg return browser->construct(obj->npp, NPVARIANT_TO_OBJECT(args[0]), args + 1, argCount - 1, result); } +// 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.layoutTestController.notifyDone();"; + script.UTF8Length = strlen("javascript:window.layoutTestController.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 = NULL; + browser->getvalue(npp, NPNVWindowNPObject, &windowObject); + if (!windowObject) + return false; + + NPVariant docVariant; + browser->getproperty(npp, windowObject, documentId, &docVariant); + if (docVariant.type != NPVariantType_Object) + 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; + browser->invoke(npp, documentObject, openId, openArgs, 2, &result); + browser->releaseobject(documentObject); + + if (result.type == NPVariantType_Object) { + logWithWindowObjectVariableArgs(windowObject, npp, "DOCUMENT OPEN SUCCESS"); + notifyTestCompletion(npp, result.value.objectValue); + browser->releaseobject(result.value.objectValue); + return true; + } + + return false; +} + +bool testWindowOpen(NPP npp) +{ + NPIdentifier openId = browser->getstringidentifier("open"); + + NPObject *windowObject = NULL; + 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; + browser->invoke(npp, windowObject, openId, openArgs, 2, &result); + if (result.type == NPVariantType_Object) { + logWithWindowObjectVariableArgs(windowObject, npp, "WINDOW OPEN SUCCESS"); + notifyTestCompletion(npp, result.value.objectValue); + browser->releaseobject(result.value.objectValue); + return true; + } + return false; +} + static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result) { PluginObject* plugin = reinterpret_cast<PluginObject*>(header); @@ -838,6 +962,9 @@ static NPObject *pluginAllocate(NPP npp, NPClass *theClass) newInstance->lastUrl = NULL; newInstance->lastHeaders = NULL; + newInstance->testDocumentOpenInDestroyStream = FALSE; + newInstance->testWindowOpen = FALSE; + return (NPObject*)newInstance; } diff --git a/webkit/tools/npapi_layout_test_plugin/PluginObject.h b/webkit/tools/npapi_layout_test_plugin/PluginObject.h index 7162954..7d86d19 100644 --- a/webkit/tools/npapi_layout_test_plugin/PluginObject.h +++ b/webkit/tools/npapi_layout_test_plugin/PluginObject.h @@ -36,6 +36,8 @@ typedef struct { NPBool returnErrorFromNewStream; NPObject* testObject; NPStream* stream; + NPBool testWindowOpen; + NPBool testDocumentOpenInDestroyStream; char* onStreamLoad; char* onStreamDestroy; char* onURLNotify; @@ -49,3 +51,6 @@ extern NPClass *getPluginClass(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 bool testDocumentOpen(NPP npp); +extern bool testWindowOpen(NPP npp); +extern void log(NPP instance, const char* format, ...); diff --git a/webkit/tools/npapi_layout_test_plugin/main.cpp b/webkit/tools/npapi_layout_test_plugin/main.cpp index 032985f..1b41f7e6 100644 --- a/webkit/tools/npapi_layout_test_plugin/main.cpp +++ b/webkit/tools/npapi_layout_test_plugin/main.cpp @@ -53,46 +53,6 @@ #include <X11/Xlib.h> #endif -static void log(NPP instance, const char* format, ...) -{ - va_list args; - va_start(args, format); - char message[2048] = "PLUGIN: "; - vsprintf(message + strlen(message), format, args); - va_end(args); - - 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; - } - - NPVariant consoleVariant; - if (!browser->getproperty(instance, windowObject, browser->getstringidentifier("console"), &consoleVariant)) { - fprintf(stderr, "Failed to retrieve console object while logging: %s\n", message); - browser->releaseobject(windowObject); - 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); - browser->releaseobject(windowObject); - return; - } - - browser->releasevariantvalue(&result); - browser->releaseobject(consoleObject); - browser->releaseobject(windowObject); -} - // Plugin entry points extern "C" { EXPORT NPError NPAPI NP_Initialize(NPNetscapeFuncs *browserFuncs @@ -174,8 +134,13 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, ch fflush(stdout); } } - } else if (strcasecmp(argn[i], "cleardocumentduringnew") == 0) + } else if (strcasecmp(argn[i], "cleardocumentduringnew") == 0) { executeScript(obj, "document.body.innerHTML = ''"); + } else if (strcasecmp(argn[i], "testdocumentopenindestroystream") == 0) { + obj->testDocumentOpenInDestroyStream = TRUE; + } else if (strcasecmp(argn[i], "testwindowopen") == 0) { + obj->testWindowOpen = TRUE; + } } instance->pdata = obj; @@ -219,6 +184,11 @@ NPError NPP_SetWindow(NPP instance, NPWindow *window) fflush(stdout); obj->logSetWindow = false; } + + if (obj->testWindowOpen) { + testWindowOpen(instance); + obj->testWindowOpen = FALSE; + } } return NPERR_NO_ERROR; @@ -264,6 +234,11 @@ NPError NPP_DestroyStream(NPP instance, NPStream *stream, NPReason reason) if (obj->onStreamDestroy) executeScript(obj, obj->onStreamDestroy); + if (obj->testDocumentOpenInDestroyStream) { + testDocumentOpen(instance); + obj->testDocumentOpenInDestroyStream = FALSE; + } + return NPERR_NO_ERROR; } |