From ea0ebbfeb2c513e41d0ebf1812ff3f40bd728dbd Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Thu, 24 Nov 2011 12:48:31 +0100 Subject: [PATCH] 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 deletion(-) diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c index 32cbde45d6d..45a7986e949 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 2b9e62e98fb..74e80694b17 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 90724827391..b3ff251c66f 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 e9bb8eb0b63..f907776b4d0 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 89684fe612b..d4cdc1036a2 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; -- 2.11.4.GIT