Bug 1225412 Part 1 - Make AsyncEventDispatcher cancelable. r=smaug
authorTing-Yu Lin <tlin@mozilla.com>
Sat, 12 Mar 2016 19:53:50 +0800
changeset 339902 48adfd045db5e7ee610408b2014ca74c845fced3
parent 339901 0ce67740545443ec87c0afd2d3d8b146dc517466
child 339903 5ee96a182b8d7e872b657b8ed0cb2dfccb58711f
push id12823
push userjmaher@mozilla.com
push dateMon, 14 Mar 2016 10:52:22 +0000
reviewerssmaug
bugs1225412
milestone48.0a1
Bug 1225412 Part 1 - Make AsyncEventDispatcher cancelable. r=smaug Also I found that mBubbles are not initialized in the constructor in AsyncEventDispatcher.cpp. I initialized those bool member variables directly. MozReview-Commit-ID: FiU4NKGJjU9
dom/events/AsyncEventDispatcher.cpp
dom/events/AsyncEventDispatcher.h
--- a/dom/events/AsyncEventDispatcher.cpp
+++ b/dom/events/AsyncEventDispatcher.cpp
@@ -18,45 +18,54 @@ using namespace dom;
 
 /******************************************************************************
  * mozilla::AsyncEventDispatcher
  ******************************************************************************/
 
 AsyncEventDispatcher::AsyncEventDispatcher(EventTarget* aTarget,
                                            WidgetEvent& aEvent)
   : mTarget(aTarget)
-  , mOnlyChromeDispatch(false)
 {
   MOZ_ASSERT(mTarget);
   RefPtr<Event> event =
     EventDispatcher::CreateEvent(aTarget, nullptr, &aEvent, EmptyString());
   mEvent = do_QueryInterface(event);
   NS_ASSERTION(mEvent, "Should never fail to create an event");
   mEvent->DuplicatePrivateData();
   mEvent->SetTrusted(aEvent.mFlags.mIsTrusted);
 }
 
 NS_IMETHODIMP
 AsyncEventDispatcher::Run()
 {
+  if (mCanceled) {
+    return NS_OK;
+  }
   RefPtr<Event> event = mEvent ? mEvent->InternalDOMEvent() : nullptr;
   if (!event) {
     event = NS_NewDOMEvent(mTarget, nullptr, nullptr);
     event->InitEvent(mEventType, mBubbles, false);
     event->SetTrusted(true);
   }
   if (mOnlyChromeDispatch) {
     MOZ_ASSERT(event->IsTrusted());
     event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
   }
   bool dummy;
   mTarget->DispatchEvent(event, &dummy);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+AsyncEventDispatcher::Cancel()
+{
+  mCanceled = true;
+  return NS_OK;
+}
+
 nsresult
 AsyncEventDispatcher::PostDOMEvent()
 {
   RefPtr<AsyncEventDispatcher> ensureDeletionWhenFailing = this;
   return NS_DispatchToCurrentThread(this);
 }
 
 void
--- a/dom/events/AsyncEventDispatcher.h
+++ b/dom/events/AsyncEventDispatcher.h
@@ -14,23 +14,23 @@
 #include "nsString.h"
 #include "nsThreadUtils.h"
 
 class nsINode;
 
 namespace mozilla {
 
 /**
- * Use nsAsyncDOMEvent to fire a DOM event that requires safe a stable DOM.
+ * Use AsyncEventDispatcher to fire a DOM event that requires safe a stable DOM.
  * For example, you may need to fire an event from within layout, but
  * want to ensure that the event handler doesn't mutate the DOM at
  * the wrong time, in order to avoid resulting instability.
  */
- 
-class AsyncEventDispatcher : public nsRunnable
+
+class AsyncEventDispatcher : public nsCancelableRunnable
 {
 public:
   /**
    * If aOnlyChromeDispatch is true, the event is dispatched to only
    * chrome node. In that case, if aTarget is already a chrome node,
    * the event is dispatched to it, otherwise the dispatch path starts
    * at the first chrome ancestor of that target.
    */
@@ -43,39 +43,38 @@ public:
   {
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget, const nsAString& aEventType,
                        bool aBubbles)
     : mTarget(aTarget)
     , mEventType(aEventType)
     , mBubbles(aBubbles)
-    , mOnlyChromeDispatch(false)
   {
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget, nsIDOMEvent* aEvent)
     : mTarget(aTarget)
     , mEvent(aEvent)
-    , mBubbles(false)
-    , mOnlyChromeDispatch(false)
   {
   }
 
   AsyncEventDispatcher(dom::EventTarget* aTarget, WidgetEvent& aEvent);
 
   NS_IMETHOD Run() override;
+  NS_IMETHOD Cancel() override;
   nsresult PostDOMEvent();
   void RunDOMEventWhenSafe();
 
   nsCOMPtr<dom::EventTarget> mTarget;
   nsCOMPtr<nsIDOMEvent> mEvent;
   nsString              mEventType;
-  bool                  mBubbles;
-  bool                  mOnlyChromeDispatch;
+  bool                  mBubbles = false;
+  bool                  mOnlyChromeDispatch = false;
+  bool                  mCanceled = false;
 };
 
 class LoadBlockingAsyncEventDispatcher final : public AsyncEventDispatcher
 {
 public:
   LoadBlockingAsyncEventDispatcher(nsINode* aEventNode,
                                    const nsAString& aEventType,
                                    bool aBubbles, bool aDispatchChromeOnly)
@@ -91,17 +90,17 @@ public:
   LoadBlockingAsyncEventDispatcher(nsINode* aEventNode, nsIDOMEvent* aEvent)
     : AsyncEventDispatcher(aEventNode, aEvent)
     , mBlockedDoc(aEventNode->OwnerDoc())
   {
     if (mBlockedDoc) {
       mBlockedDoc->BlockOnload();
     }
   }
-  
+
   ~LoadBlockingAsyncEventDispatcher();
 
 private:
   nsCOMPtr<nsIDocument> mBlockedDoc;
 };
 
 } // namespace mozilla