[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.21-584-g1e41756

jhoneycutt at apple.com jhoneycutt at apple.com
Fri Feb 26 22:17:06 UTC 2010


The following commit has been merged in the webkit-1.1 branch:
commit c1e21f5ac7f2f6ac799d32ccb890ad3e938cf4c1
Author: jhoneycutt at apple.com <jhoneycutt at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Feb 10 20:18:29 2010 +0000

    <rdar://problem/7436875> Crash in Flash when visiting
    http://www.cctv.com/default.shtml (WER ID 819298200) [watson 2502260]
    
    Reviewed by Darin Adler.
    
    WebCore:
    
    Test: platform/win/plugins/plugin-delayed-destroy.html
    
    * bridge/NP_jsobject.cpp:
    (_NPN_Evaluate):
    If Flash calls this to evaluate a script that destroys the PluginView,
    we crash when returning to Flash code. Before evaluating the script,
    call PluginView::keepAlive() to hold a ref to this instance (and release
    it asynchronously).
    
    * plugins/PluginView.cpp:
    (WebCore::instanceMap):
    Return a map from the NPP to the PluginView.
    (WebCore::PluginView::~PluginView):
    Assert that the keep alive timer is not running; remove ourselves from
    the instance map.
    (WebCore::PluginView::performRequest):
    The parent Frame is now a RefPtr; use .get().
    (WebCore::PluginView::status):
    Ditto.
    (WebCore::PluginView::didReceiveResponse):
    Ditto.
    (WebCore::PluginView::PluginView):
    Add the view to the instance map.
    (WebCore::PluginView::lifeSupportTimerFired):
    Deref the PluginView.
    (WebCore::PluginView::keepAlive):
    Ref the PluginView, then start a time to release the reference
    asynchronously.
    (WebCore::PluginView::keepAlive):
    Find the PluginView in the map, and call its keepAlive() function.
    
    * plugins/PluginView.h:
    Made m_parentFrame a RefPtr, so that it will remain valid when the
    keep alive timer fires.
    (WebCore::PluginView::parentFrame):
    Use .get().
    
    * plugins/gtk/PluginViewGtk.cpp:
    (WebCore::PluginView::updatePluginWidget):
    Use .get().
    (WebCore::PluginView::handleKeyboardEvent):
    Use .get().
    (WebCore::PluginView::handleMouseEvent):
    Use .get().
    
    * plugins/PluginViewNone.cpp:
    (WebCore::PluginView::keepAlive):
    Stubbed.
    
    WebKitTools:
    
    * DumpRenderTree/win/TestNetscapePlugin/main.cpp:
    (executeScript):
    Moved to an earlier point in the file.
    (NPP_New):
    If the plug-in has an onDestroy attribute, store its value.
    (NPP_Destroy):
    If the plug-in has code to run on destruction, run it and free it.
    
    LayoutTests:
    
    * platform/win/plugins/plugin-delayed-destroy-expected.txt: Added.
    * platform/win/plugins/plugin-delayed-destroy.html: Added.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@54614 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 066a663..d2bf0fa 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2010-02-08  Jon Honeycutt  <jhoneycutt at apple.com>
+
+        <rdar://problem/7436875> Crash in Flash when visiting
+        http://www.cctv.com/default.shtml (WER ID 819298200) [watson 2502260]
+
+        Reviewed by Darin Adler.
+
+        * platform/win/plugins/plugin-delayed-destroy-expected.txt: Added.
+        * platform/win/plugins/plugin-delayed-destroy.html: Added.
+
 2010-02-10  Diego Gonzalez  <diego.gonzalez at openbossa.org>
 
         Reviewed by Kenneth Rohde Christiansen.
diff --git a/LayoutTests/platform/win/plugins/plugin-delayed-destroy-expected.txt b/LayoutTests/platform/win/plugins/plugin-delayed-destroy-expected.txt
new file mode 100644
index 0000000..f5479f9
--- /dev/null
+++ b/LayoutTests/platform/win/plugins/plugin-delayed-destroy-expected.txt
@@ -0,0 +1,3 @@
+The should be printed before destroy.
+Plug-in destroyed.
+
diff --git a/LayoutTests/platform/win/plugins/plugin-delayed-destroy.html b/LayoutTests/platform/win/plugins/plugin-delayed-destroy.html
new file mode 100644
index 0000000..74c3d1f
--- /dev/null
+++ b/LayoutTests/platform/win/plugins/plugin-delayed-destroy.html
@@ -0,0 +1,31 @@
+<html>
+<body>
+    <pre id="console"></pre>
+    <div id="outer">
+        <embed id="plg" type="application/x-webkit-test-netscape" onDestroy="pluginDestroyed()"></embed>
+    </div>
+    <script>
+        function log(message)
+        {
+            document.getElementById("console").appendChild(document.createTextNode(message + "\n"));
+        }
+
+        function pluginDestroyed()
+        {
+            log("Plug-in destroyed.")
+            layoutTestController.notifyDone();
+        }
+
+        if (window.layoutTestController) {
+            layoutTestController.waitUntilDone();
+            layoutTestController.dumpAsText();
+        }
+
+        var plugin = document.getElementById("plg");
+
+        plugin.testEvaluate("window.document.getElementById('outer').innerHTML = '';");
+
+        log("The should be printed before destroy.");
+    </script>
+</body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 3c49e38..dcdadd9 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,59 @@
+2010-02-08  Jon Honeycutt  <jhoneycutt at apple.com>
+
+        <rdar://problem/7436875> Crash in Flash when visiting
+        http://www.cctv.com/default.shtml (WER ID 819298200) [watson 2502260]
+
+        Reviewed by Darin Adler.
+
+        Test: platform/win/plugins/plugin-delayed-destroy.html
+
+        * bridge/NP_jsobject.cpp:
+        (_NPN_Evaluate):
+        If Flash calls this to evaluate a script that destroys the PluginView,
+        we crash when returning to Flash code. Before evaluating the script,
+        call PluginView::keepAlive() to hold a ref to this instance (and release
+        it asynchronously).
+
+        * plugins/PluginView.cpp:
+        (WebCore::instanceMap):
+        Return a map from the NPP to the PluginView.
+        (WebCore::PluginView::~PluginView):
+        Assert that the keep alive timer is not running; remove ourselves from
+        the instance map.
+        (WebCore::PluginView::performRequest):
+        The parent Frame is now a RefPtr; use .get().
+        (WebCore::PluginView::status):
+        Ditto.
+        (WebCore::PluginView::didReceiveResponse):
+        Ditto.
+        (WebCore::PluginView::PluginView):
+        Add the view to the instance map.
+        (WebCore::PluginView::lifeSupportTimerFired):
+        Deref the PluginView.
+        (WebCore::PluginView::keepAlive):
+        Ref the PluginView, then start a time to release the reference
+        asynchronously.
+        (WebCore::PluginView::keepAlive):
+        Find the PluginView in the map, and call its keepAlive() function.
+
+        * plugins/PluginView.h:
+        Made m_parentFrame a RefPtr, so that it will remain valid when the
+        keep alive timer fires.
+        (WebCore::PluginView::parentFrame):
+        Use .get().
+
+        * plugins/gtk/PluginViewGtk.cpp:
+        (WebCore::PluginView::updatePluginWidget):
+        Use .get().
+        (WebCore::PluginView::handleKeyboardEvent):
+        Use .get().
+        (WebCore::PluginView::handleMouseEvent):
+        Use .get().
+
+        * plugins/PluginViewNone.cpp:
+        (WebCore::PluginView::keepAlive):
+        Stubbed.
+
 2010-02-10  Jesus Sanchez-Palencia  <jesus.palencia at openbossa.org>
 
         Reviewed by Kenneth Rohde Christiansen.
diff --git a/WebCore/bridge/NP_jsobject.cpp b/WebCore/bridge/NP_jsobject.cpp
index a30b6d7..09851df 100644
--- a/WebCore/bridge/NP_jsobject.cpp
+++ b/WebCore/bridge/NP_jsobject.cpp
@@ -30,6 +30,7 @@
 #include "NP_jsobject.h"
 
 #include "PlatformString.h"
+#include "PluginView.h"
 #include "StringSourceProvider.h"
 #include "c_utility.h"
 #include "c_instance.h"
@@ -190,7 +191,7 @@ bool _NPN_Invoke(NPP npp, NPObject* o, NPIdentifier methodName, const NPVariant*
     return true;
 }
 
-bool _NPN_Evaluate(NPP, NPObject* o, NPString* s, NPVariant* variant)
+bool _NPN_Evaluate(NPP instance, NPObject* o, NPString* s, NPVariant* variant)
 {
     if (o->_class == NPScriptObjectClass) {
         JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(o); 
@@ -199,6 +200,10 @@ bool _NPN_Evaluate(NPP, NPObject* o, NPString* s, NPVariant* variant)
         if (!rootObject || !rootObject->isValid())
             return false;
 
+        // There is a crash in Flash when evaluating a script that destroys the
+        // PluginView, so we destroy it asynchronously.
+        PluginView::keepAlive(instance);
+
         ExecState* exec = rootObject->globalObject()->globalExec();
         JSLock lock(SilenceAssertionsOnly);
         String scriptString = convertNPStringToUTF16(s);
diff --git a/WebCore/plugins/PluginView.cpp b/WebCore/plugins/PluginView.cpp
index 3ff4c82..9e1d454 100644
--- a/WebCore/plugins/PluginView.cpp
+++ b/WebCore/plugins/PluginView.cpp
@@ -86,6 +86,14 @@ using namespace HTMLNames;
 
 static int s_callingPlugin;
 
+typedef HashMap<NPP, PluginView*> InstanceMap;
+
+static InstanceMap& instanceMap()
+{
+    static InstanceMap& map = *new InstanceMap;
+    return map;
+}
+
 static String scriptStringIfJavaScriptURL(const KURL& url)
 {
     if (!protocolIsJavaScript(url))
@@ -258,6 +266,10 @@ PluginView::~PluginView()
 {
     LOG(Plugins, "PluginView::~PluginView()");
 
+    ASSERT(!m_lifeSupportTimer.isActive());
+
+    instanceMap().remove(m_instance);
+
     removeFromUnstartedListIfNecessary();
 
     stop();
@@ -423,7 +435,7 @@ void PluginView::performRequest(PluginRequest* request)
         // if this is not a targeted request, create a stream for it. otherwise,
         // just pass it off to the loader
         if (targetFrameName.isEmpty()) {
-            RefPtr<PluginStream> stream = PluginStream::create(this, m_parentFrame, request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks());
+            RefPtr<PluginStream> stream = PluginStream::create(this, m_parentFrame.get(), request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks());
             m_streams.add(stream);
             stream->start();
         } else {
@@ -461,7 +473,7 @@ void PluginView::performRequest(PluginRequest* request)
         if (getString(parentFrame->script(), result, resultString))
             cstr = resultString.utf8();
 
-        RefPtr<PluginStream> stream = PluginStream::create(this, m_parentFrame, request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks());
+        RefPtr<PluginStream> stream = PluginStream::create(this, m_parentFrame.get(), request->frameLoadRequest().resourceRequest(), request->sendNotification(), request->notifyData(), plugin()->pluginFuncs(), instance(), m_plugin->quirks());
         m_streams.add(stream);
         stream->sendJavaScriptStream(requestURL, cstr);
     }
@@ -600,7 +612,7 @@ NPError PluginView::destroyStream(NPStream* stream, NPReason reason)
 void PluginView::status(const char* message)
 {
     if (Page* page = m_parentFrame->page())
-        page->chrome()->setStatusbarText(m_parentFrame, String(message));
+        page->chrome()->setStatusbarText(m_parentFrame.get(), String(message));
 }
 
 NPError PluginView::setValue(NPPVariable variable, void* value)
@@ -792,6 +804,7 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p
     , m_requestTimer(this, &PluginView::requestTimerFired)
     , m_invalidateTimer(this, &PluginView::invalidateTimerFired)
     , m_popPopupsStateTimer(this, &PluginView::popPopupsStateTimerFired)
+    , m_lifeSupportTimer(this, &PluginView::lifeSupportTimerFired)
     , m_mode(loadManually ? NP_FULL : NP_EMBED)
     , m_paramNames(0)
     , m_paramValues(0)
@@ -845,6 +858,8 @@ PluginView::PluginView(Frame* parentFrame, const IntSize& size, PluginPackage* p
     m_instance->ndata = this;
     m_instance->pdata = 0;
 
+    instanceMap().add(m_instance, this);
+
     setParameters(paramNames, paramValues);
 
     memset(&m_npWindow, 0, sizeof(m_npWindow));
@@ -871,7 +886,7 @@ void PluginView::didReceiveResponse(const ResourceResponse& response)
     ASSERT(m_loadManually);
     ASSERT(!m_manualStream);
 
-    m_manualStream = PluginStream::create(this, m_parentFrame, m_parentFrame->loader()->activeDocumentLoader()->request(), false, 0, plugin()->pluginFuncs(), instance(), m_plugin->quirks());
+    m_manualStream = PluginStream::create(this, m_parentFrame.get(), m_parentFrame->loader()->activeDocumentLoader()->request(), false, 0, plugin()->pluginFuncs(), instance(), m_plugin->quirks());
     m_manualStream->setLoadManually(true);
 
     m_manualStream->didReceiveResponse(0, response);
@@ -1249,4 +1264,27 @@ String PluginView::pluginName() const
     return m_plugin->name();
 }
 
+void PluginView::lifeSupportTimerFired(Timer<PluginView>*)
+{
+    deref();
+}
+
+void PluginView::keepAlive()
+{
+    if (m_lifeSupportTimer.isActive())
+        return;
+
+    ref();
+    m_lifeSupportTimer.startOneShot(0);
+}
+
+void PluginView::keepAlive(NPP instance)
+{
+    PluginView* view = instanceMap().get(instance);
+    if (!view)
+        return;
+
+    view->keepAlive();
+}
+
 } // namespace WebCore
diff --git a/WebCore/plugins/PluginView.h b/WebCore/plugins/PluginView.h
index ac60fd4..bb06f14 100644
--- a/WebCore/plugins/PluginView.h
+++ b/WebCore/plugins/PluginView.h
@@ -179,7 +179,7 @@ namespace WebCore {
 
         virtual bool isPluginView() const { return true; }
 
-        Frame* parentFrame() const { return m_parentFrame; }
+        Frame* parentFrame() const { return m_parentFrame.get(); }
 
         void focusPluginElement();
 
@@ -213,6 +213,9 @@ namespace WebCore {
 
         bool start();
 
+        static void keepAlive(NPP);
+        void keepAlive();
+
     private:
         PluginView(Frame* parentFrame, const IntSize&, PluginPackage*, Element*, const KURL&, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually);
 
@@ -238,7 +241,7 @@ namespace WebCore {
         static BOOL WINAPI hookedEndPaint(HWND, const PAINTSTRUCT*);
 #endif
 
-        Frame* m_parentFrame;
+        RefPtr<Frame> m_parentFrame;
         RefPtr<PluginPackage> m_plugin;
         Element* m_element;
         bool m_isStarted;
@@ -257,6 +260,9 @@ namespace WebCore {
         void popPopupsStateTimerFired(Timer<PluginView>*);
         Timer<PluginView> m_popPopupsStateTimer;
 
+        void lifeSupportTimerFired(Timer<PluginView>*);
+        Timer<PluginView> m_lifeSupportTimer;
+
 #ifndef NP_NO_CARBON
         bool dispatchNPEvent(NPEvent&);
 #endif
diff --git a/WebCore/plugins/PluginViewNone.cpp b/WebCore/plugins/PluginViewNone.cpp
index 725af82..8b2f17a 100644
--- a/WebCore/plugins/PluginViewNone.cpp
+++ b/WebCore/plugins/PluginViewNone.cpp
@@ -120,4 +120,8 @@ void PluginView::restart()
 {
 }
 
+void PluginView::keepAlive(NPP)
+{
+}
+
 } // namespace WebCore
diff --git a/WebCore/plugins/gtk/PluginViewGtk.cpp b/WebCore/plugins/gtk/PluginViewGtk.cpp
index 8f4b2d5..6d992fb 100644
--- a/WebCore/plugins/gtk/PluginViewGtk.cpp
+++ b/WebCore/plugins/gtk/PluginViewGtk.cpp
@@ -137,7 +137,7 @@ void PluginView::updatePluginWidget()
         if (m_drawable)
             XFreePixmap(GDK_DISPLAY(), m_drawable);
 
-        m_drawable = XCreatePixmap(GDK_DISPLAY(), getRootWindow(m_parentFrame),
+        m_drawable = XCreatePixmap(GDK_DISPLAY(), getRootWindow(m_parentFrame.get()),
                                    m_windowRect.width(), m_windowRect.height(),
                                    ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth);
         XSync(GDK_DISPLAY(), False); // make sure that the server knows about the Drawable
@@ -319,7 +319,7 @@ void PluginView::handleKeyboardEvent(KeyboardEvent* event)
     GdkEventKey* gdkEvent = event->keyEvent()->gdkEventKey();
 
     xEvent.type = (event->type() == eventNames().keydownEvent) ? 2 : 3; // KeyPress/Release get unset somewhere
-    xEvent.xkey.root = getRootWindow(m_parentFrame);
+    xEvent.xkey.root = getRootWindow(m_parentFrame.get());
     xEvent.xkey.subwindow = 0; // we have no child window
     xEvent.xkey.time = event->timeStamp();
     xEvent.xkey.state = gdkEvent->state; // GdkModifierType mirrors xlib state masks
@@ -445,11 +445,11 @@ void PluginView::handleMouseEvent(MouseEvent* event)
     IntPoint postZoomPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation()));
 
     if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent)
-        setXButtonEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame);
+        setXButtonEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame.get());
     else if (event->type() == eventNames().mousemoveEvent)
-        setXMotionEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame);
+        setXMotionEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame.get());
     else if (event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mouseoverEvent)
-        setXCrossingEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame);
+        setXCrossingEventSpecificFields(&xEvent, event, postZoomPos, m_parentFrame.get());
     else
         return;
 #endif
diff --git a/WebKitTools/ChangeLog b/WebKitTools/ChangeLog
index 44949b8..8952010 100644
--- a/WebKitTools/ChangeLog
+++ b/WebKitTools/ChangeLog
@@ -1,3 +1,18 @@
+2010-02-08  Jon Honeycutt  <jhoneycutt at apple.com>
+
+        <rdar://problem/7436875> Crash in Flash when visiting
+        http://www.cctv.com/default.shtml (WER ID 819298200) [watson 2502260]
+
+        Reviewed by Darin Adler.
+
+        * DumpRenderTree/win/TestNetscapePlugin/main.cpp:
+        (executeScript):
+        Moved to an earlier point in the file.
+        (NPP_New):
+        If the plug-in has an onDestroy attribute, store its value.
+        (NPP_Destroy):
+        If the plug-in has code to run on destruction, run it and free it.
+
 2010-02-10  Diego Gonzalez  <diego.gonzalez at openbossa.org>
 
         Reviewed by Kenneth Rohde Christiansen.
diff --git a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp
index 82b1d4d..08a2f6a 100644
--- a/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp
+++ b/WebKitTools/DumpRenderTree/win/TestNetscapePlugin/main.cpp
@@ -71,6 +71,19 @@ NPError __stdcall NP_Shutdown()
     return NPERR_NO_ERROR;
 }
 
+static void executeScript(const PluginObject* object, const char* script)
+{
+    NPObject *windowScriptObject;
+    browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject);
+
+    NPString npScript;
+    npScript.UTF8Characters = script;
+    npScript.UTF8Length = strlen(script);
+
+    NPVariant browserResult;
+    browser->evaluate(object->npp, windowScriptObject, &npScript, &browserResult);
+    browser->releasevariantvalue(&browserResult);
+}
 
 NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char *argn[], char *argv[], NPSavedData *saved)
 {
@@ -84,6 +97,8 @@ NPError NPP_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, ch
                 obj->onStreamDestroy = _strdup(argv[i]);
             else if (_stricmp(argn[i], "onURLNotify") == 0 && !obj->onURLNotify)
                 obj->onURLNotify = _strdup(argv[i]);
+            else if (_stricmp(argn[i], "onDestroy") == 0 && !obj->onDestroy)
+                obj->onDestroy = _strdup(argv[i]);
             else if (_stricmp(argn[i], "logSrc") == 0) {
                 for (int i = 0; i < argc; i++)
                     if (_stricmp(argn[i], "src") == 0)
@@ -113,6 +128,11 @@ NPError NPP_Destroy(NPP instance, NPSavedData **save)
         if (obj->onStreamDestroy)
             free(obj->onStreamDestroy);
 
+        if (obj->onDestroy) {
+            executeScript(obj, obj->onDestroy);
+            free(obj->onDestroy);
+        }
+
         if (obj->logDestroy)
             printf("PLUGIN: NPP_Destroy\n");
 
@@ -135,20 +155,6 @@ NPError NPP_SetWindow(NPP instance, NPWindow *window)
     return NPERR_NO_ERROR;
 }
 
-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 *stype)
 {
     PluginObject* obj = (PluginObject*)instance->pdata;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list