Bug 1466208 - part 36: Create PresShell::EventHandler::PrepareToDispatchContextMenuEvent() r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Thu, 28 Feb 2019 10:33:52 +0000
changeset 521010 525dd00d5636
parent 521009 e1459b0afa25
child 521011 56aaf8c9fb7c
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 36: Create PresShell::EventHandler::PrepareToDispatchContextMenuEvent() r=smaug If `Shift` state of `eContextMenu` event is active, we make it not fired on web content. Additionally, if it's not time to open context menu, we shouldn't dispatch it into the DOM. The new method prepare and check them. Differential Revision: https://phabricator.services.mozilla.com/D21337
layout/base/PresShell.cpp
layout/base/PresShell.h
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -7778,26 +7778,23 @@ nsresult PresShell::EventHandler::Handle
 
     if (!mPresShell->mTouchManager.PreHandleEvent(
             aEvent, aEventStatus, touchIsNew, isHandlingUserInput,
             mPresShell->mCurrentEventContent)) {
       return NS_OK;
     }
   }
 
-  if (aEvent->mMessage == eContextMenu) {
-    WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
-    if (mouseEvent->IsContextMenuKeyEvent() &&
-        !AdjustContextMenuKeyEvent(mouseEvent)) {
-      return NS_OK;
-    }
-    if (mouseEvent->IsShift()) {
-      aEvent->mFlags.mOnlyChromeDispatch = true;
-      aEvent->mFlags.mRetargetToNonNativeAnonymous = true;
-    }
+  // 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;
   }
 
   AutoHandlingUserInputStatePusher userInpStatePusher(isHandlingUserInput,
                                                       aEvent, GetDocument());
 
   if (aEvent->IsTrusted() && aEvent->mMessage == eMouseMove) {
     nsIPresShell::AllowMouseCapture(
         EventStateManager::GetActiveEventStateManager() == manager);
@@ -7930,16 +7927,38 @@ nsresult PresShell::EventHandler::Handle
     }
     default:
       break;
   }
   RecordEventHandlingResponsePerformance(aEvent);
   return rv;
 }
 
+bool PresShell::EventHandler::PrepareToDispatchContextMenuEvent(
+    WidgetEvent* aEvent) {
+  MOZ_ASSERT(aEvent);
+  MOZ_ASSERT(aEvent->mMessage == eContextMenu);
+
+  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.
+  // In this case, we don't fire "contextmenu" event on web content because
+  // of not cancelable.
+  if (mouseEvent->IsShift()) {
+    aEvent->mFlags.mOnlyChromeDispatch = true;
+    aEvent->mFlags.mRetargetToNonNativeAnonymous = true;
+  }
+  return true;
+}
+
 void PresShell::EventHandler::RecordEventHandlingResponsePerformance(
     const WidgetEvent* aEvent) {
   if (!Telemetry::CanRecordBase() || aEvent->mTimeStamp.IsNull() ||
       aEvent->mTimeStamp <= mPresShell->mLastOSWake ||
       !aEvent->AsInputEvent()) {
     return;
   }
 
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -1072,16 +1072,26 @@ class PresShell final : public nsIPresSh
      * RecordEventHandlingResponsePerformance() records event handling response
      * performance with telemetry.
      *
      * @param aEvent            The handled event.
      */
     void RecordEventHandlingResponsePerformance(const WidgetEvent* aEvent);
 
     /**
+     * PrepareToDispatchContextMenuEvent() prepares to dispatch aEvent into
+     * the DOM.
+     *
+     * @param aEvent            Must be eContextMenu event.
+     * @return                  true if it can be dispatched into the DOM.
+     *                          Otherwise, false.
+     */
+    bool PrepareToDispatchContextMenuEvent(WidgetEvent* aEvent);
+
+    /**
      * This and the next two helper methods are used to target and position the
      * context menu when the keyboard shortcut is used to open it.
      *
      * If another menu is open, the context menu is opened relative to the
      * active menuitem within the menu, or the menu itself if no item is active.
      * Otherwise, if the caret is visible, the menu is opened near the caret.
      * Otherwise, if a selectable list such as a listbox is focused, the
      * current item within the menu is opened relative to this item.