[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

mrobinson at webkit.org mrobinson at webkit.org
Wed Dec 22 15:34:10 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit e5ad7392a5b5ee1730015a763a84df5f8a7672b6
Author: mrobinson at webkit.org <mrobinson at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Nov 8 16:42:48 2010 +0000

    2010-11-08  Martin Robinson  <mrobinson at igalia.com>
    
            Reviewed by Xan Lopez.
    
            [GTK] Wrapped DOM bindings GObjects do not disconnect event listeners when they die
            https://bugs.webkit.org/show_bug.cgi?id=49136
    
            When GObjects are finalized and freed, disconnect their event listeners, so that
            WebCore does not try to fire signals on dead GObjects. We do this by holding a weak
            reference to the GObject in the signal listener. When the weak reference notification
            callback is executed, we disconnect the event listener.
    
            No new tests; this fix is proved by prevention of crashes in soon to be
            landed editing delegate signals, which are covered by the layout tests.
    
            * bindings/gobject/GObjectEventListener.cpp:
            (WebCore::GObjectEventListener::GObjectEventListener): Updated the constructor.
            (WebCore::GObjectEventListener::~GObjectEventListener): Disconnect the weak reference
            if the GObject is still alive.
            (WebCore::GObjectEventListener::gobjectDestroyed): When the GObject is destroyed,
            disconnect the appropriate event listener.
            (WebCore::GObjectEventListener::handleEvent): Changes to reflect use of CString
            instead of WebCore string.
            * bindings/gobject/GObjectEventListener.h:
            (WebCore::GObjectEventListener::addEventListener): Changed create to addEventListener,
            so that the connection and disconnection is an internal contract to the class.
            (WebCore::GObjectEventListener::gobjectDestroyedCallback): Added.
            * bindings/scripts/CodeGeneratorGObject.pm: Modified the code generate to use
            GObjectEventListener::addEventListener and no longer call addEventListener on
            its own.
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@71528 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 1e48643..efcb2ee 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,34 @@
+2010-11-08  Martin Robinson  <mrobinson at igalia.com>
+
+        Reviewed by Xan Lopez.
+
+        [GTK] Wrapped DOM bindings GObjects do not disconnect event listeners when they die
+        https://bugs.webkit.org/show_bug.cgi?id=49136
+
+        When GObjects are finalized and freed, disconnect their event listeners, so that
+        WebCore does not try to fire signals on dead GObjects. We do this by holding a weak
+        reference to the GObject in the signal listener. When the weak reference notification
+        callback is executed, we disconnect the event listener.
+
+        No new tests; this fix is proved by prevention of crashes in soon to be
+        landed editing delegate signals, which are covered by the layout tests.
+
+        * bindings/gobject/GObjectEventListener.cpp:
+        (WebCore::GObjectEventListener::GObjectEventListener): Updated the constructor.
+        (WebCore::GObjectEventListener::~GObjectEventListener): Disconnect the weak reference
+        if the GObject is still alive.
+        (WebCore::GObjectEventListener::gobjectDestroyed): When the GObject is destroyed,
+        disconnect the appropriate event listener.
+        (WebCore::GObjectEventListener::handleEvent): Changes to reflect use of CString
+        instead of WebCore string.
+        * bindings/gobject/GObjectEventListener.h:
+        (WebCore::GObjectEventListener::addEventListener): Changed create to addEventListener,
+        so that the connection and disconnection is an internal contract to the class.
+        (WebCore::GObjectEventListener::gobjectDestroyedCallback): Added.
+        * bindings/scripts/CodeGeneratorGObject.pm: Modified the code generate to use
+        GObjectEventListener::addEventListener and no longer call addEventListener on
+        its own.
+
 2010-11-08  Adam Roben  <aroben at apple.com>
 
         Windows Release build fix after r71514
diff --git a/WebCore/bindings/gobject/GObjectEventListener.cpp b/WebCore/bindings/gobject/GObjectEventListener.cpp
index 3ce8461..553d717 100644
--- a/WebCore/bindings/gobject/GObjectEventListener.cpp
+++ b/WebCore/bindings/gobject/GObjectEventListener.cpp
@@ -19,20 +19,63 @@
 #include "config.h"
 #include "GObjectEventListener.h"
 
+#include "DOMWindow.h"
 #include "Event.h"
 #include "EventListener.h"
+#include "Node.h"
 #include "webkit/WebKitDOMEvent.h"
 #include "webkit/WebKitDOMEventPrivate.h"
+#include <glib-object.h>
+#include <glib.h>
 #include <wtf/HashMap.h>
-#include <wtf/text/CString.h>
 
 namespace WebCore {
 
+GObjectEventListener::GObjectEventListener(GObject* object, DOMWindow* window, Node* node, const char* domEventName, const char* signalName)
+    : EventListener(GObjectEventListenerType)
+    , m_object(object)
+    , m_coreNode(node)
+    , m_coreWindow(window)
+    , m_domEventName(domEventName)
+    , m_signalName(signalName)
+{
+    ASSERT(!m_coreWindow || !m_coreNode);
+    if (m_coreWindow)
+        m_coreWindow->addEventListener(domEventName, this, false);
+    if (m_coreNode)
+        m_coreNode->addEventListener(domEventName, this, false);
+    g_object_weak_ref(object, reinterpret_cast<GWeakNotify>(GObjectEventListener::gobjectDestroyedCallback), this);
+}
+
+GObjectEventListener::~GObjectEventListener()
+{
+    if (!m_coreWindow && !m_coreNode)
+        return;
+    g_object_weak_unref(m_object, reinterpret_cast<GWeakNotify>(GObjectEventListener::gobjectDestroyedCallback), this);
+}
+
+void GObjectEventListener::gobjectDestroyed()
+{
+    ASSERT(!m_coreWindow || !m_coreNode);
+
+    // We must set m_coreWindow and m_coreNode to null, because removeEventListener may call the
+    // destructor as a side effect and we must be in the proper state to prevent g_object_weak_unref.
+    if (DOMWindow* window = m_coreWindow) {
+        m_coreWindow = 0;
+        window->removeEventListener(m_domEventName.data(), this, false);
+        return;
+    }
+
+    Node* node = m_coreNode;
+    m_coreNode = 0; // See above.
+    node->removeEventListener(m_domEventName.data(), this, false);
+}
+
 void GObjectEventListener::handleEvent(ScriptExecutionContext*, Event* event)
 {
     gboolean handled = FALSE;
     WebKitDOMEvent* gobjectEvent = WEBKIT_DOM_EVENT(WebKit::kit(event));
-    g_signal_emit_by_name(m_object, m_signalName.utf8().data(), gobjectEvent, &handled);
+    g_signal_emit_by_name(m_object, m_signalName.data(), gobjectEvent, &handled);
 }
 
 bool GObjectEventListener::operator==(const EventListener& listener)
diff --git a/WebCore/bindings/gobject/GObjectEventListener.h b/WebCore/bindings/gobject/GObjectEventListener.h
index 7ca2cc7..e5ad2e5 100644
--- a/WebCore/bindings/gobject/GObjectEventListener.h
+++ b/WebCore/bindings/gobject/GObjectEventListener.h
@@ -21,15 +21,34 @@
 
 #include "EventListener.h"
 
-#include "PlatformString.h"
-#include <glib-object.h>
-#include <glib.h>
-#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/CString.h>
+
+typedef struct _GObject GObject;
 
 namespace WebCore {
+
+class DOMWindow;
+class Node;
+
 class GObjectEventListener : public EventListener {
 public:
-    static PassRefPtr<GObjectEventListener> create(GObject* object, const char* signalName) { return adoptRef(new GObjectEventListener(object, signalName)); }
+
+    static void addEventListener(GObject* object, DOMWindow* window, const char* domEventName, const char* signalName)
+    {
+        RefPtr<GObjectEventListener> listener(adoptRef(new GObjectEventListener(object, window, 0, domEventName, signalName)));
+    }
+
+    static void addEventListener(GObject* object, Node* node, const char* domEventName, const char* signalName)
+    {
+        RefPtr<GObjectEventListener> listener(adoptRef(new GObjectEventListener(object, 0, node, domEventName, signalName)));
+    }
+
+    static void gobjectDestroyedCallback(GObjectEventListener* listener, GObject*)
+    {
+        listener->gobjectDestroyed();
+    }
+
     static const GObjectEventListener* cast(const EventListener* listener)
     {
         return listener->type() == GObjectEventListenerType
@@ -40,17 +59,20 @@ public:
     virtual bool operator==(const EventListener& other);
 
 private:
-    GObjectEventListener(GObject* object, const char* signalName)
-        : EventListener(GObjectEventListenerType)
-        , m_object(object)
-        , m_signalName(signalName)
-    {
-    }
+    GObjectEventListener(GObject*, DOMWindow*, Node*, const char* domEventName, const char* signalName);
+    ~GObjectEventListener();
+    void gobjectDestroyed();
 
     virtual void handleEvent(ScriptExecutionContext*, Event*);
 
     GObject* m_object;
-    String m_signalName;
+
+    // We do not need to keep a reference to these WebCore objects, because
+    // we only use them when the GObject and thus the WebCore object is alive.
+    Node* m_coreNode;
+    DOMWindow* m_coreWindow;
+    CString m_domEventName;
+    CString m_signalName;
 };
 } // namespace WebCore
 
diff --git a/WebCore/bindings/scripts/CodeGeneratorGObject.pm b/WebCore/bindings/scripts/CodeGeneratorGObject.pm
index dd9e3c7..6c450ad 100644
--- a/WebCore/bindings/scripts/CodeGeneratorGObject.pm
+++ b/WebCore/bindings/scripts/CodeGeneratorGObject.pm
@@ -501,8 +501,7 @@ EOF
     my ${listenerName} = $name . "Listener";
 
     my $txtInstallEventListener = << "EOF";
-    RefPtr<WebCore::GObjectEventListener> ${listenerName} = WebCore::GObjectEventListener::create(reinterpret_cast<GObject*>(object), "${gobjectSignalName}");
-    coreObject->addEventListener("${name}", ${listenerName}, false);
+    WebCore::GObjectEventListener::addEventListener(object, coreObject, "${name}", "${gobjectSignalName}");
 EOF
     push(@txtInstallEventListeners, $txtInstallEventListener);
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list