Module: wine Branch: master Commit: ea0ebbfeb2c513e41d0ebf1812ff3f40bd728dbd URL: http://source.winehq.org/git/wine.git/?a=commit;h=ea0ebbfeb2c513e41d0ebf1812...
Author: Jacek Caban jacek@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;