Bug 1489308 part 3. Add a public RemoveAllListeners method on EventListenerManager. r=smaug
authorBoris Zbarsky <bzbarsky@mit.edu>
Wed, 27 Feb 2019 05:08:50 +0000
changeset 519454 b393e04da7e97d49c577c5537c1f62cb0cc6b91e
parent 519453 f2b0ceb55cedd2cffea476c0ff187d4b283ec4e2
child 519455 015db4a424d9f817a7dbaee4e520e81f20430727
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1489308
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1489308 part 3. Add a public RemoveAllListeners method on EventListenerManager. r=smaug Differential Revision: https://phabricator.services.mozilla.com/D17321
dom/events/EventListenerManager.cpp
dom/events/EventListenerManager.h
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -142,20 +142,20 @@ EventListenerManager::~EventListenerMana
   // this class can have Disconnect called in one of two ways:
   // if it is part of a cycle, then in Unlink() (such a cycle
   // would be with one of the listeners, not mTarget which is weak).
   // If not part of a cycle, then Disconnect must be called manually,
   // typically from the destructor of the owner class (mTarget).
   // XXX azakai: Is there any reason to not just call Disconnect
   //             from right here, if not previously called?
   NS_ASSERTION(!mTarget, "didn't call Disconnect");
-  RemoveAllListeners();
+  RemoveAllListenersSilently();
 }
 
-void EventListenerManager::RemoveAllListeners() {
+void EventListenerManager::RemoveAllListenersSilently() {
   if (mClearingListeners) {
     return;
   }
   mClearingListeners = true;
   mListeners.Clear();
   mClearingListeners = false;
 }
 
@@ -1314,17 +1314,17 @@ void EventListenerManager::HandleEventIn
 
   if (aEvent->DefaultPrevented()) {
     *aEventStatus = nsEventStatus_eConsumeNoDefault;
   }
 }
 
 void EventListenerManager::Disconnect() {
   mTarget = nullptr;
-  RemoveAllListeners();
+  RemoveAllListenersSilently();
 }
 
 void EventListenerManager::AddEventListener(const nsAString& aType,
                                             EventListenerHolder aListenerHolder,
                                             bool aUseCapture,
                                             bool aWantsUntrusted) {
   EventListenerFlags flags;
   flags.mCapture = aUseCapture;
@@ -1701,16 +1701,29 @@ bool EventListenerManager::IsApzAwareEve
   // around this constraint easily enough.
   if (aEvent == nsGkAtoms::ontouchstart || aEvent == nsGkAtoms::ontouchmove) {
     return TouchEvent::PrefEnabled(
         nsContentUtils::GetDocShellForEventTarget(mTarget));
   }
   return false;
 }
 
+void EventListenerManager::RemoveAllListeners() {
+  while (!mListeners.IsEmpty()) {
+    size_t idx = mListeners.Length() - 1;
+    RefPtr<nsAtom> type = mListeners.ElementAt(idx).mTypeAtom;
+    EventMessage message = mListeners.ElementAt(idx).mEventMessage;
+    mListeners.RemoveElementAt(idx);
+    NotifyEventListenerRemoved(type);
+    if (IsDeviceType(message)) {
+      DisableDevice(message);
+    }
+  }
+}
+
 already_AddRefed<nsIScriptGlobalObject>
 EventListenerManager::GetScriptGlobalAndDocument(Document** aDoc) {
   nsCOMPtr<nsINode> node(do_QueryInterface(mTarget));
   nsCOMPtr<Document> doc;
   nsCOMPtr<nsIScriptGlobalObject> global;
   if (node) {
     // Try to get context from doc
     // XXX sXBL/XBL2 issue -- do we really want the owner here?  What
--- a/dom/events/EventListenerManager.h
+++ b/dom/events/EventListenerManager.h
@@ -450,16 +450,22 @@ class EventListenerManager final : publi
 
   bool HasNonSystemGroupListenersForUntrustedKeyEvents();
   bool HasNonPassiveNonSystemGroupListenersForUntrustedKeyEvents();
 
   bool HasApzAwareListeners();
   bool IsApzAwareListener(Listener* aListener);
   bool IsApzAwareEvent(nsAtom* aEvent);
 
+  /**
+   * Remove all event listeners from the event target this EventListenerManager
+   * is for.
+   */
+  void RemoveAllListeners();
+
  protected:
   void HandleEventInternal(nsPresContext* aPresContext, WidgetEvent* aEvent,
                            dom::Event** aDOMEvent,
                            dom::EventTarget* aCurrentTarget,
                            nsEventStatus* aEventStatus, bool aItemInShadowTree);
 
   nsresult HandleEventSubType(Listener* aListener, dom::Event* aDOMEvent,
                               dom::EventTarget* aCurrentTarget);
@@ -575,17 +581,17 @@ class EventListenerManager final : publi
                                 EventMessage aEventMessage, nsAtom* aTypeAtom,
                                 const EventListenerFlags& aFlags,
                                 bool aHandler = false, bool aAllEvents = false);
   void RemoveEventListenerInternal(EventListenerHolder aListener,
                                    EventMessage aEventMessage,
                                    nsAtom* aUserType,
                                    const EventListenerFlags& aFlags,
                                    bool aAllEvents = false);
-  void RemoveAllListeners();
+  void RemoveAllListenersSilently();
   void NotifyEventListenerRemoved(nsAtom* aUserType);
   const EventTypeData* GetTypeDataForIID(const nsIID& aIID);
   const EventTypeData* GetTypeDataForEventName(nsAtom* aName);
   nsPIDOMWindowInner* GetInnerWindowForTarget();
   already_AddRefed<nsPIDOMWindowInner> GetTargetAsInnerWindow() const;
 
   bool ListenerCanHandle(const Listener* aListener, const WidgetEvent* aEvent,
                          EventMessage aEventMessage) const;