Bug 1466208 - part 40: Create PresShell::EventHandler::PrepareToDispatchEvent() r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Sat, 09 Mar 2019 23:38:38 +0000
changeset 521289 f9482e1d252f37c9da57bb1e76e6d8ea6bb7c89b
parent 521288 6b61335177b8506c1f1d4dfb2640b91a4e07d192
child 521290 43376e0c35631124193d304daeea1c557d487a8a
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
bugs1466208
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 1466208 - part 40: Create PresShell::EventHandler::PrepareToDispatchEvent() r=smaug For making `PresShell::EventHandler::HandleEventInternal()` easier to read, move the large switch statement for preparation into the new method. Differential Revision: https://phabricator.services.mozilla.com/D21341
layout/base/PresShell.cpp
layout/base/PresShell.h
layout/base/TouchManager.cpp
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -7639,90 +7639,46 @@ nsresult PresShell::EventHandler::Handle
   // XXX Is this intentional?  In such case, the score is really good because
   //     of nothing to do.  So, it may make average and median better.
   if (NS_EVENT_NEEDS_FRAME(aEvent) && !mPresShell->GetCurrentEventFrame() &&
       !mPresShell->GetCurrentEventContent()) {
     RecordEventHandlingResponsePerformance(aEvent);
     return NS_OK;
   }
 
-  bool touchIsNew = false;
-  bool isHandlingUserInput = false;
-
   if (mPresShell->mCurrentEventContent && aEvent->IsTargetedAtFocusedWindow()) {
     nsFocusManager* fm = nsFocusManager::GetFocusManager();
     if (fm) {
+      // This may run script now.  So, mPresShell might be destroyed after here.
       fm->FlushBeforeEventHandlingIfNeeded(mPresShell->mCurrentEventContent);
     }
   }
 
-  // XXX How about IME events and input events for plugins?
-  if (aEvent->IsTrusted()) {
-    if (aEvent->IsUserAction()) {
-      mPresShell->mHasHandledUserInput = true;
-    }
-
-    switch (aEvent->mMessage) {
-      case eKeyPress:
-      case eKeyDown:
-      case eKeyUp: {
-        WidgetKeyboardEvent* keyboardEvent = aEvent->AsKeyboardEvent();
-        MaybeHandleKeyboardEventBeforeDispatch(keyboardEvent);
-        // Not all keyboard events are treated as user input, so that popups
-        // can't be opened, fullscreen mode can't be started, etc at unexpected
-        // time.
-        isHandlingUserInput = keyboardEvent->CanTreatAsUserInput();
-        break;
-      }
-      case eMouseDown:
-      case eMouseUp:
-      case ePointerDown:
-      case ePointerUp:
-        isHandlingUserInput = true;
-        break;
-
-      case eMouseMove:
-        nsIPresShell::AllowMouseCapture(
-            EventStateManager::GetActiveEventStateManager() == manager);
-        break;
-
-      case eDrop: {
-        nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
-        if (session) {
-          bool onlyChromeDrop = false;
-          session->GetOnlyChromeDrop(&onlyChromeDrop);
-          if (onlyChromeDrop) {
-            aEvent->mFlags.mOnlyChromeDispatch = true;
-          }
-        }
-        break;
-      }
-
-      default:
-        break;
-    }
-
-    RecordEventPreparationPerformance(aEvent);
-
-    if (!mPresShell->mTouchManager.PreHandleEvent(
-            aEvent, aEventStatus, touchIsNew, isHandlingUserInput,
-            mPresShell->mCurrentEventContent)) {
-      return NS_OK;
-    }
-  }
+  bool isHandlingUserInput = PrepareToDispatchEvent(aEvent);
 
   // If we cannot open context menu even though eContextMenu is fired, we
   // should stop dispatching it into the DOM.
-  // XXX Can it be untrusted eContextMenu event here?  If not, we can do
-  //     this in the above block's switch statement.
   if (aEvent->mMessage == eContextMenu &&
       !PrepareToDispatchContextMenuEvent(aEvent)) {
     return NS_OK;
   }
 
+  // We finished preparing to dispatch the event.  So, let's record the
+  // performance.
+  RecordEventPreparationPerformance(aEvent);
+
+  // XXX Why don't we measure the performance of TouchManager::PreHandleEvent()
+  //     with RecordEventPreparationPerformance()?
+  bool touchIsNew = false;
+  if (!mPresShell->mTouchManager.PreHandleEvent(
+          aEvent, aEventStatus, touchIsNew, isHandlingUserInput,
+          mPresShell->mCurrentEventContent)) {
+    return NS_OK;
+  }
+
   AutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput,
                                                       aEvent, GetDocument());
 
   nsAutoPopupStatePusher popupStatePusher(
       PopupBlocker::GetEventPopupControlState(aEvent));
 
   // FIXME. If the event was reused, we need to clear the old target,
   // bug 329430
@@ -7844,21 +7800,74 @@ nsresult PresShell::EventHandler::Handle
     }
     default:
       break;
   }
   RecordEventHandlingResponsePerformance(aEvent);
   return rv;
 }
 
+bool PresShell::EventHandler::PrepareToDispatchEvent(WidgetEvent* aEvent) {
+  if (!aEvent->IsTrusted()) {
+    return false;
+  }
+
+  if (aEvent->IsUserAction()) {
+    mPresShell->mHasHandledUserInput = true;
+  }
+
+  switch (aEvent->mMessage) {
+    case eKeyPress:
+    case eKeyDown:
+    case eKeyUp: {
+      WidgetKeyboardEvent* keyboardEvent = aEvent->AsKeyboardEvent();
+      MaybeHandleKeyboardEventBeforeDispatch(keyboardEvent);
+      // Not all keyboard events are treated as user input, so that popups
+      // can't be opened, fullscreen mode can't be started, etc at unexpected
+      // time.
+      return keyboardEvent->CanTreatAsUserInput();
+    }
+    case eMouseDown:
+    case eMouseUp:
+    case ePointerDown:
+    case ePointerUp:
+      return true;
+
+    case eMouseMove: {
+      bool allowCapture = EventStateManager::GetActiveEventStateManager() &&
+                          GetPresContext() &&
+                          GetPresContext()->EventStateManager() ==
+                              EventStateManager::GetActiveEventStateManager();
+      nsIPresShell::AllowMouseCapture(allowCapture);
+      return false;
+    }
+    case eDrop: {
+      nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
+      if (session) {
+        bool onlyChromeDrop = false;
+        session->GetOnlyChromeDrop(&onlyChromeDrop);
+        if (onlyChromeDrop) {
+          aEvent->mFlags.mOnlyChromeDispatch = true;
+        }
+      }
+      return false;
+    }
+
+    default:
+      return false;
+  }
+}
+
 bool PresShell::EventHandler::PrepareToDispatchContextMenuEvent(
     WidgetEvent* aEvent) {
   MOZ_ASSERT(aEvent);
   MOZ_ASSERT(aEvent->mMessage == eContextMenu);
 
+  // XXX Why do we treat untrusted eContextMenu here?
+
   WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
   if (mouseEvent->IsContextMenuKeyEvent() &&
       !AdjustContextMenuKeyEvent(mouseEvent)) {
     return false;
   }
 
   // If "Shift" state is active, context menu should be forcibly opened even
   // if web apps want to prevent it since we respect our users' intention.
@@ -7923,16 +7932,20 @@ void PresShell::EventHandler::MaybeHandl
     }
   }
 }
 
 void PresShell::EventHandler::RecordEventPreparationPerformance(
     const WidgetEvent* aEvent) {
   MOZ_ASSERT(aEvent);
 
+  if (!aEvent->IsTrusted()) {
+    return;
+  }
+
   switch (aEvent->mMessage) {
     case eKeyPress:
     case eKeyDown:
     case eKeyUp:
       if (aEvent->AsKeyboardEvent()->ShouldInteractionTimeRecorded()) {
         GetPresContext()->RecordInteractionTime(
             nsPresContext::InteractionType::eKeyInteraction,
             aEvent->mTimeStamp);
@@ -7981,16 +7994,19 @@ void PresShell::EventHandler::RecordEven
 
     default:
       return;
   }
 }
 
 void PresShell::EventHandler::RecordEventHandlingResponsePerformance(
     const WidgetEvent* aEvent) {
+  // XXX Why we include the peformance of untrusted events only here?
+  //     We don't include it at recoding the preparation performance.
+
   if (!Telemetry::CanRecordBase() || aEvent->mTimeStamp.IsNull() ||
       aEvent->mTimeStamp <= mPresShell->mLastOSWake ||
       !aEvent->AsInputEvent()) {
     return;
   }
 
   TimeStamp now = TimeStamp::Now();
   double millis = (now - aEvent->mTimeStamp).ToMilliseconds();
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -1065,32 +1065,43 @@ class PresShell final : public nsIPresSh
      private:
       const EventHandler& mEventHandler;
       const WidgetEvent* mEvent;
       TimeStamp mHandlingStartTime;
     };
 
     /**
      * RecordEventPreparationPerformance() records event preparation performance
-     * with telemetry.
+     * with telemetry only when aEvent is a trusted event.
      *
      * @param aEvent            The handling event which we've finished
      *                          preparing something to dispatch.
      */
     void RecordEventPreparationPerformance(const WidgetEvent* aEvent);
 
     /**
      * RecordEventHandlingResponsePerformance() records event handling response
      * performance with telemetry.
      *
      * @param aEvent            The handled event.
      */
     void RecordEventHandlingResponsePerformance(const WidgetEvent* aEvent);
 
     /**
+     * PrepareToDispatchEvent() prepares to dispatch aEvent.
+     *
+     * @param aEvent            The handling event.
+     * @return                  true if the event is user interaction.  I.e.,
+     *                          enough obvious input to allow to open popup,
+     *                          etc.  false, otherwise.
+     */
+    MOZ_CAN_RUN_SCRIPT
+    bool PrepareToDispatchEvent(WidgetEvent* aEvent);
+
+    /**
      * MaybeHandleKeyboardEventBeforeDispatch() may handle aKeyboardEvent
      * if it should do something before dispatched into the DOM.
      *
      * @param aKeyboardEvent    The handling keyboard event.
      */
     MOZ_CAN_RUN_SCRIPT
     void MaybeHandleKeyboardEventBeforeDispatch(
         WidgetKeyboardEvent* aKeyboardEvent);
--- a/layout/base/TouchManager.cpp
+++ b/layout/base/TouchManager.cpp
@@ -217,16 +217,20 @@ nsIFrame* TouchManager::SuppressInvalidP
     }
   }
   return frame;
 }
 
 bool TouchManager::PreHandleEvent(WidgetEvent* aEvent, nsEventStatus* aStatus,
                                   bool& aTouchIsNew, bool& aIsHandlingUserInput,
                                   nsCOMPtr<nsIContent>& aCurrentEventContent) {
+  if (!aEvent->IsTrusted()) {
+    return true;
+  }
+
   switch (aEvent->mMessage) {
     case eTouchStart: {
       aIsHandlingUserInput = true;
       WidgetTouchEvent* touchEvent = aEvent->AsTouchEvent();
       // if there is only one touch in this touchstart event, assume that it is
       // the start of a new touch session and evict any old touches in the
       // queue
       if (touchEvent->mTouches.Length() == 1) {