From c88cd8440df238f880f3ab13bed0900a137cb107 Mon Sep 17 00:00:00 2001 From: "bzbarsky%mit.edu" Date: Thu, 15 Nov 2007 22:29:08 +0000 Subject: [PATCH] Unhook event handlers on binding teardown. Bug 403162, r+sr=sicking git-svn-id: svn://10.0.0.236/trunk@239497 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/xbl/src/nsBindingManager.cpp | 2 + mozilla/content/xbl/src/nsXBLBinding.cpp | 78 +++++++++++--------- mozilla/content/xbl/src/nsXBLService.cpp | 1 - 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/mozilla/content/xbl/src/nsBindingManager.cpp b/mozilla/content/xbl/src/nsBindingManager.cpp index d362a85ea40..cee380f4def 100644 --- a/mozilla/content/xbl/src/nsBindingManager.cpp +++ b/mozilla/content/xbl/src/nsBindingManager.cpp @@ -848,6 +848,8 @@ nsBindingManager::RemoveLayeredBinding(nsIContent* aContent, nsIURI* aURL) NS_ASSERTION(doc, "No owner document?"); // Finally remove the binding... + // XXXbz this doesn't remove the implementation! Should fix! Until + // then we need the explicit UnhookEventHandlers here. binding->UnhookEventHandlers(); binding->ChangeDocument(doc, nsnull); SetBinding(aContent, nsnull); diff --git a/mozilla/content/xbl/src/nsXBLBinding.cpp b/mozilla/content/xbl/src/nsXBLBinding.cpp index 53ae2f225a3..6e6198aef1a 100644 --- a/mozilla/content/xbl/src/nsXBLBinding.cpp +++ b/mozilla/content/xbl/src/nsXBLBinding.cpp @@ -972,42 +972,47 @@ nsXBLBinding::UnhookEventHandlers() nsXBLPrototypeHandler* handlerChain = mPrototypeBinding->GetPrototypeHandlers(); if (handlerChain) { - nsCOMPtr piTarget = do_QueryInterface(mBoundElement); - nsCOMPtr target = do_QueryInterface(piTarget); + nsCOMPtr manager; + mBoundElement->GetListenerManager(PR_FALSE, getter_AddRefs(manager)); + if (!manager) { + return; + } + nsCOMPtr systemEventGroup; - nsXBLPrototypeHandler* curr; for (curr = handlerChain; curr; curr = curr->GetNextHandler()) { nsXBLEventHandler* handler = curr->GetCachedEventHandler(); - if (handler) { - nsCOMPtr eventAtom = curr->GetEventName(); - if (!eventAtom || - eventAtom == nsGkAtoms::keyup || - eventAtom == nsGkAtoms::keydown || - eventAtom == nsGkAtoms::keypress) - continue; - - nsAutoString type; - eventAtom->ToString(type); - - // Figure out if we're using capturing or not. - PRBool useCapture = (curr->GetPhase() == NS_PHASE_CAPTURING); - - // If this is a command, remove it from the system event group, otherwise - // remove it from the standard event group. - - // This is a weak ref. systemEventGroup above is already a - // strong ref, so we are guaranteed it will not go away. - nsIDOMEventGroup* eventGroup = nsnull; - if (curr->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) { - if (!systemEventGroup) - piTarget->GetSystemEventGroup(getter_AddRefs(systemEventGroup)); - eventGroup = systemEventGroup; - } - - target->RemoveGroupedEventListener(type, handler, useCapture, - eventGroup); + if (!handler) { + continue; } + + nsCOMPtr eventAtom = curr->GetEventName(); + if (!eventAtom || + eventAtom == nsGkAtoms::keyup || + eventAtom == nsGkAtoms::keydown || + eventAtom == nsGkAtoms::keypress) + continue; + + nsAutoString type; + eventAtom->ToString(type); + + // Figure out if we're using capturing or not. + PRInt32 flags = (curr->GetPhase() == NS_PHASE_CAPTURING) ? + NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE; + + // If this is a command, remove it from the system event group, + // otherwise remove it from the standard event group. + + // This is a weak ref. systemEventGroup above is already a + // strong ref, so we are guaranteed it will not go away. + nsIDOMEventGroup* eventGroup = nsnull; + if (curr->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) { + if (!systemEventGroup) + manager->GetSystemEventGroupLM(getter_AddRefs(systemEventGroup)); + eventGroup = systemEventGroup; + } + + manager->RemoveEventListenerByType(handler, type, flags, eventGroup); } const nsCOMArray* keyHandlers = @@ -1020,7 +1025,8 @@ nsXBLBinding::UnhookEventHandlers() handler->GetEventName(type); // Figure out if we're using capturing or not. - PRBool useCapture = (handler->GetPhase() == NS_PHASE_CAPTURING); + PRInt32 flags = (handler->GetPhase() == NS_PHASE_CAPTURING) ? + NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE; // If this is a command, remove it from the system event group, otherwise // remove it from the standard event group. @@ -1030,12 +1036,11 @@ nsXBLBinding::UnhookEventHandlers() nsIDOMEventGroup* eventGroup = nsnull; if (handler->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) { if (!systemEventGroup) - piTarget->GetSystemEventGroup(getter_AddRefs(systemEventGroup)); + manager->GetSystemEventGroupLM(getter_AddRefs(systemEventGroup)); eventGroup = systemEventGroup; } - target->RemoveGroupedEventListener(type, handler, useCapture, - eventGroup); + manager->RemoveEventListenerByType(handler, type, flags, eventGroup); } } } @@ -1126,6 +1131,9 @@ nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocumen } } } + + // Remove our event handlers + UnhookEventHandlers(); } // Then do our ancestors. This reverses the construction order, so that at diff --git a/mozilla/content/xbl/src/nsXBLService.cpp b/mozilla/content/xbl/src/nsXBLService.cpp index c0d7dff335b..0b6728bbb69 100644 --- a/mozilla/content/xbl/src/nsXBLService.cpp +++ b/mozilla/content/xbl/src/nsXBLService.cpp @@ -589,7 +589,6 @@ nsXBLService::FlushStyleBindings(nsIContent* aContent) if (styleBinding) { // Clear out the script references. - styleBinding->UnhookEventHandlers(); styleBinding->ChangeDocument(document, nsnull); }