Jacek Caban : mshtml: Properly remove event listeners.

Alexandre Julliard julliard at winehq.org
Thu Nov 24 15:04:39 CST 2011


Module: wine
Branch: master
Commit: ea0ebbfeb2c513e41d0ebf1812ff3f40bd728dbd
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=ea0ebbfeb2c513e41d0ebf1812ff3f40bd728dbd

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Thu Nov 24 12:48:31 2011 +0100

mshtml: Properly remove event listeners.

---

 dlls/mshtml/htmldoc.c    |    1 +
 dlls/mshtml/htmlevent.c  |   14 ++++++++++++++
 dlls/mshtml/htmlevent.h  |    2 ++
 dlls/mshtml/htmlwindow.c |    1 +
 dlls/mshtml/nsevents.c   |   30 +++++++++++++++++++++++++++++-
 5 files changed, 47 insertions(+), 1 deletions(-)

diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c
index 32cbde4..45a7986 100644
--- a/dlls/mshtml/htmldoc.c
+++ b/dlls/mshtml/htmldoc.c
@@ -2032,6 +2032,7 @@ static void HTMLDocumentNode_destructor(HTMLDOMNode *iface)
         heap_free(This->elem_vars[i]);
     heap_free(This->elem_vars);
 
+    detach_events(This);
     if(This->body_event_target)
         release_event_target(This->body_event_target);
     if(This->nsevent_listener)
diff --git a/dlls/mshtml/htmlevent.c b/dlls/mshtml/htmlevent.c
index 2b9e62e..74e8069 100644
--- a/dlls/mshtml/htmlevent.c
+++ b/dlls/mshtml/htmlevent.c
@@ -1184,6 +1184,20 @@ static HRESULT ensure_nsevent_handler(HTMLDocumentNode *doc, event_target_t *eve
     return S_OK;
 }
 
+void detach_events(HTMLDocumentNode *doc)
+{
+    int i;
+
+    if(!doc->event_vector)
+        return;
+
+    for(i=0; i < EVENTID_LAST; i++) {
+        if(doc->event_vector[i])
+            detach_nsevent(doc, event_info[i].name);
+    }
+}
+
+
 static HRESULT remove_event_handler(event_target_t **event_target, eventid_t eid)
 {
     if(*event_target && (*event_target)->event_table[eid] && (*event_target)->event_table[eid]->handler_prop) {
diff --git a/dlls/mshtml/htmlevent.h b/dlls/mshtml/htmlevent.h
index 9072482..b3ff251 100644
--- a/dlls/mshtml/htmlevent.h
+++ b/dlls/mshtml/htmlevent.h
@@ -54,10 +54,12 @@ HRESULT dispatch_event(HTMLDOMNode*,const WCHAR*,VARIANT*,VARIANT_BOOL*) DECLSPE
 HRESULT call_fire_event(HTMLDOMNode*,eventid_t) DECLSPEC_HIDDEN;
 void update_cp_events(HTMLWindow*,event_target_t**,cp_static_data_t*,nsIDOMNode*) DECLSPEC_HIDDEN;
 HRESULT doc_init_events(HTMLDocumentNode*) DECLSPEC_HIDDEN;
+void detach_events(HTMLDocumentNode *doc) DECLSPEC_HIDDEN;
 
 void init_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
 void release_nsevents(HTMLDocumentNode*) DECLSPEC_HIDDEN;
 void add_nsevent_listener(HTMLDocumentNode*,nsIDOMNode*,LPCWSTR) DECLSPEC_HIDDEN;
+void detach_nsevent(HTMLDocumentNode*,const WCHAR*) DECLSPEC_HIDDEN;
 
 static inline event_target_t **get_node_event_target(HTMLDOMNode *node)
 {
diff --git a/dlls/mshtml/htmlwindow.c b/dlls/mshtml/htmlwindow.c
index e9bb8eb..f907776 100644
--- a/dlls/mshtml/htmlwindow.c
+++ b/dlls/mshtml/htmlwindow.c
@@ -46,6 +46,7 @@ static void window_set_docnode(HTMLWindow *window, HTMLDocumentNode *doc_node)
     if(window->doc) {
         if(window->doc_obj && window == window->doc_obj->basedoc.window)
             window->doc->basedoc.cp_container.forward_container = NULL;
+        detach_events(window->doc);
         abort_document_bindings(window->doc);
         window->doc->basedoc.window = NULL;
         htmldoc_release(&window->doc->basedoc);
diff --git a/dlls/mshtml/nsevents.c b/dlls/mshtml/nsevents.c
index 89684fe..d4cdc10 100644
--- a/dlls/mshtml/nsevents.c
+++ b/dlls/mshtml/nsevents.c
@@ -281,7 +281,7 @@ static nsresult NSAPI handle_htmlevent(nsIDOMEventListener *iface, nsIDOMEvent *
     eventid_t eid;
     nsresult nsres;
 
-    TRACE("\n");
+    TRACE("%p\n", This->This);
 
     nsAString_Init(&type_str, NULL);
     nsIDOMEvent_GetType(event, &type_str);
@@ -363,8 +363,34 @@ void add_nsevent_listener(HTMLDocumentNode *doc, nsIDOMNode *nsnode, LPCWSTR typ
     nsIDOMEventTarget_Release(target);
 }
 
+void detach_nsevent(HTMLDocumentNode *doc, const WCHAR *type)
+{
+    nsIDOMEventTarget *target;
+    nsAString type_str;
+    nsresult nsres;
+
+    if(!doc->basedoc.window)
+        return;
+
+    nsres = nsIDOMWindow_QueryInterface(doc->basedoc.window->nswindow, &IID_nsIDOMEventTarget, (void**)&target);
+    if(NS_FAILED(nsres)) {
+        ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres);
+        return;
+    }
+
+    nsAString_InitDepend(&type_str, type);
+    nsres = nsIDOMEventTarget_RemoveEventListener(target, &type_str,
+            &doc->nsevent_listener->htmlevent_listener.nsIDOMEventListener_iface, TRUE);
+    nsAString_Finish(&type_str);
+    nsIDOMEventTarget_Release(target);
+    if(NS_FAILED(nsres))
+        ERR("RemoveEventTarget failed: %08x\n", nsres);
+}
+
 void release_nsevents(HTMLDocumentNode *doc)
 {
+    TRACE("%p %p\n", doc, doc->nsevent_listener);
+
     if(doc->nsevent_listener) {
         doc->nsevent_listener->doc = NULL;
         release_listener(doc->nsevent_listener);
@@ -387,6 +413,8 @@ void init_nsevents(HTMLDocumentNode *doc)
     if(!listener)
         return;
 
+    TRACE("%p %p\n", doc, listener);
+
     listener->ref = 1;
     listener->doc = doc;
 




More information about the wine-cvs mailing list