Bug 1379466 - Make editor listen for auxclick mouse events. r=smaug,masayuki
authorIan Moody <moz-ian@perix.co.uk>
Thu, 18 Apr 2019 12:57:36 +0000
changeset 470161 273553e141f1188c807488a12e45ab12c9ccb8a8
parent 470160 4e152cfac89d9f368599cadf8b9dc1e87fd06d2b
child 470162 0e9fa06f3fd885525adaad2e9995e3077258c94c
push id112843
push useraiakab@mozilla.com
push dateFri, 19 Apr 2019 09:50:22 +0000
treeherdermozilla-inbound@c06f27cbfe40 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, masayuki
bugs1379466
milestone68.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 1379466 - Make editor listen for auxclick mouse events. r=smaug,masayuki Editable elements will no longer get click events for non-primary mouse buttons since they are being unshipped from the web in favour of auxclick events. Listen for auxclick as well so middle-click paste still works. Don't stop propagation after middle-click paste, instead ignore clicks on contenteditable elements in ClickHandlerChild. Update test_middle_click_paste.html for the new behaviour. Also remove the mNoContentDispatch overrides in HTMLInputElement and HTMLTextAreaElement that were needed for middle-pasting. Differential Revision: https://phabricator.services.mozilla.com/D26792
browser/actors/ClickHandlerChild.jsm
dom/events/EventStateManager.cpp
dom/events/test/test_clickevent_on_input.html
dom/html/HTMLInputElement.cpp
dom/html/HTMLTextAreaElement.cpp
editor/libeditor/EditorEventListener.cpp
editor/libeditor/tests/test_bug674770-1.html
editor/libeditor/tests/test_middle_click_paste.html
widget/tests/test_assign_event_data.html
--- a/browser/actors/ClickHandlerChild.jsm
+++ b/browser/actors/ClickHandlerChild.jsm
@@ -18,16 +18,26 @@ ChromeUtils.defineModuleGetter(this, "E1
                                "resource://gre/modules/E10SUtils.jsm");
 
 class ClickHandlerChild extends ActorChild {
   handleEvent(event) {
     if (!event.isTrusted || event.defaultPrevented || event.button == 2 ||
         (event.type == "click" && event.button == 1)) {
       return;
     }
+    // Don't do anything on editable things, we shouldn't open links in
+    // contenteditables, and editor needs to possibly handle middlemouse paste
+    let composedTarget = event.composedTarget;
+    if (composedTarget.isContentEditable ||
+        (composedTarget.ownerDocument &&
+         composedTarget.ownerDocument.designMode == "on") ||
+        ChromeUtils.getClassName(composedTarget) == "HTMLInputElement" ||
+        ChromeUtils.getClassName(composedTarget) == "HTMLTextAreaElement") {
+      return;
+    }
 
     let originalTarget = event.originalTarget;
     let ownerDoc = originalTarget.ownerDocument;
     if (!ownerDoc) {
       return;
     }
 
     // Handle click events from about pages
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -5012,17 +5012,17 @@ nsresult EventStateManager::DispatchClic
   return rv;
 }
 
 nsresult EventStateManager::HandleMiddleClickPaste(
     nsIPresShell* aPresShell, WidgetMouseEvent* aMouseEvent,
     nsEventStatus* aStatus, TextEditor* aTextEditor) {
   MOZ_ASSERT(aPresShell);
   MOZ_ASSERT(aMouseEvent);
-  MOZ_ASSERT((aMouseEvent->mMessage == eMouseClick &&
+  MOZ_ASSERT((aMouseEvent->mMessage == eMouseAuxClick &&
               aMouseEvent->button == WidgetMouseEventBase::eMiddleButton) ||
              EventCausesClickEvents(*aMouseEvent));
   MOZ_ASSERT(aStatus);
   MOZ_ASSERT(*aStatus != nsEventStatus_eConsumeNoDefault);
 
   // Even if we're called twice or more for a mouse operation, we should
   // handle only once.  Although mMultipleActionsPrevented may be set to
   // true by different event handler in the future, we can use it for now.
--- a/dom/events/test/test_clickevent_on_input.html
+++ b/dom/events/test/test_clickevent_on_input.html
@@ -55,24 +55,21 @@ function isEnabledAccessibleCaret()
     return SpecialPowers.getBoolPref("layout.accessiblecaret.enabled");
   } catch (e) {
     return false;
   }
 }
 
 function doTest(aButton)
 {
-  // NOTE #1: Right click causes a context menu to popup, then, the click event
-  //          isn't generated.
-  // NOTE #2: If middle click causes text to be pasted, then, the click event
-  //          isn't generated.
-  // NOTE #3: If touch caret is enabled, touch caret would ovelap input element,
+  // NOTE #1: Non-primary buttons don't generate 'click' events
+  // NOTE #2: If touch caret is enabled, touch caret would ovelap input element,
   //          then, the click event isn't generated.
   if (aButton != 2 &&
-      (aButton != 1 || !isEnabledMiddleClickPaste()) &&
+      aButton != 1 &&
       (aButton != 0 || !isEnabledAccessibleCaret())) {
     gClickCount = 0;
     // click on border of input
     synthesizeMouse(input, 5, 5, { button: aButton });
     is(gClickCount, 1,
        "click event doesn't fired on input element (button is " +
          aButton + ")");
 
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -122,26 +122,25 @@ NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER
 // XXX align=left, hspace, vspace, border? other nav4 attrs
 
 namespace mozilla {
 namespace dom {
 
 // First bits are needed for the control type.
 #define NS_OUTER_ACTIVATE_EVENT (1 << 9)
 #define NS_ORIGINAL_CHECKED_VALUE (1 << 10)
-#define NS_NO_CONTENT_DISPATCH (1 << 11)
+// (1 << 11 is unused)
 #define NS_ORIGINAL_INDETERMINATE_VALUE (1 << 12)
 #define NS_PRE_HANDLE_BLUR_EVENT (1 << 13)
 #define NS_PRE_HANDLE_INPUT_EVENT (1 << 14)
 #define NS_IN_SUBMIT_CLICK (1 << 15)
-#define NS_CONTROL_TYPE(bits)                                            \
-  ((bits) & ~(NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE |      \
-              NS_NO_CONTENT_DISPATCH | NS_ORIGINAL_INDETERMINATE_VALUE | \
-              NS_PRE_HANDLE_BLUR_EVENT | NS_PRE_HANDLE_INPUT_EVENT |     \
-              NS_IN_SUBMIT_CLICK))
+#define NS_CONTROL_TYPE(bits)                                              \
+  ((bits) & ~(NS_OUTER_ACTIVATE_EVENT | NS_ORIGINAL_CHECKED_VALUE |        \
+              NS_ORIGINAL_INDETERMINATE_VALUE | NS_PRE_HANDLE_BLUR_EVENT | \
+              NS_PRE_HANDLE_INPUT_EVENT | NS_IN_SUBMIT_CLICK))
 
 // whether textfields should be selected once focused:
 //  -1: no, 1: yes, 0: uninitialized
 static int32_t gSelectTextFieldOnFocus;
 UploadLastDir* HTMLInputElement::gUploadLastDir;
 
 static const nsAttrValue::EnumTable kInputTypeTable[] = {
     {"button", NS_FORM_INPUT_BUTTON},
@@ -3197,29 +3196,16 @@ void HTMLInputElement::GetEventTargetPar
         break;
     }
   }
 
   if (originalCheckedValue) {
     aVisitor.mItemFlags |= NS_ORIGINAL_CHECKED_VALUE;
   }
 
-  // If mNoContentDispatch is true we will not allow content to handle
-  // this event.  But to allow middle mouse button paste to work we must allow
-  // middle clicks to go to text fields anyway.
-  if (aVisitor.mEvent->mFlags.mNoContentDispatch) {
-    aVisitor.mItemFlags |= NS_NO_CONTENT_DISPATCH;
-  }
-  if (IsSingleLineTextControl(false) &&
-      aVisitor.mEvent->mMessage == eMouseClick &&
-      aVisitor.mEvent->AsMouseEvent()->button ==
-          WidgetMouseEvent::eMiddleButton) {
-    aVisitor.mEvent->mFlags.mNoContentDispatch = false;
-  }
-
   // We must cache type because mType may change during JS event (bug 2369)
   aVisitor.mItemFlags |= mType;
 
   if (aVisitor.mEvent->mMessage == eFocus && aVisitor.mEvent->IsTrusted() &&
       MayFireChangeOnBlur() &&
       // StartRangeThumbDrag already set mFocusedValue on 'mousedown' before
       // we get the 'focus' event.
       !mIsDraggingRange) {
@@ -3700,17 +3686,16 @@ nsresult HTMLInputElement::PostHandleEve
 
     UpdateState(true);
   }
 
   nsresult rv = NS_OK;
   bool outerActivateEvent = !!(aVisitor.mItemFlags & NS_OUTER_ACTIVATE_EVENT);
   bool originalCheckedValue =
       !!(aVisitor.mItemFlags & NS_ORIGINAL_CHECKED_VALUE);
-  bool noContentDispatch = !!(aVisitor.mItemFlags & NS_NO_CONTENT_DISPATCH);
   uint8_t oldType = NS_CONTROL_TYPE(aVisitor.mItemFlags);
 
   // Ideally we would make the default action for click and space just dispatch
   // DOMActivate, and the default action for DOMActivate flip the checkbox/
   // radio state and fire onchange.  However, for backwards compatibility, we
   // need to flip the state before firing click, and we need to fire click
   // when space is pressed.  So, we just nest the firing of DOMActivate inside
   // the click event handling, and allow cancellation of DOMActivate to cancel
@@ -3751,19 +3736,16 @@ nsresult HTMLInputElement::PostHandleEve
         // will be flushed or forgoten.
         mForm->OnSubmitClickEnd();
         break;
       default:
         break;
     }
   }
 
-  // Reset the flag for other content besides this text field
-  aVisitor.mEvent->mFlags.mNoContentDispatch = noContentDispatch;
-
   // now check to see if the event was "cancelled"
   if (mCheckedIsToggled && outerActivateEvent) {
     if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault) {
       // if it was cancelled and a radio button, then set the old
       // selected btn to TRUE. if it is a checkbox then set it to its
       // original value
       if (oldType == NS_FORM_INPUT_RADIO) {
         nsCOMPtr<nsIContent> content = do_QueryInterface(aVisitor.mItemData);
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -38,18 +38,16 @@
 #include "nsPresContext.h"
 #include "mozilla/PresState.h"
 #include "nsReadableUtils.h"
 #include "nsStyleConsts.h"
 #include "nsTextEditorState.h"
 #include "nsBaseCommandController.h"
 #include "nsXULControllers.h"
 
-#define NS_NO_CONTENT_DISPATCH (1 << 0)
-
 NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(TextArea)
 
 namespace mozilla {
 namespace dom {
 
 HTMLTextAreaElement::HTMLTextAreaElement(
     already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
     FromParser aFromParser)
@@ -447,28 +445,16 @@ void HTMLTextAreaElement::GetEventTarget
   // one.
   if (aVisitor.mEvent->mMessage == eFormSelect) {
     if (mHandlingSelect) {
       return;
     }
     mHandlingSelect = true;
   }
 
-  // If noContentDispatch is true we will not allow content to handle
-  // this event.  But to allow middle mouse button paste to work we must allow
-  // middle clicks to go to text fields anyway.
-  if (aVisitor.mEvent->mFlags.mNoContentDispatch) {
-    aVisitor.mItemFlags |= NS_NO_CONTENT_DISPATCH;
-  }
-  if (aVisitor.mEvent->mMessage == eMouseClick &&
-      aVisitor.mEvent->AsMouseEvent()->button ==
-          WidgetMouseEvent::eMiddleButton) {
-    aVisitor.mEvent->mFlags.mNoContentDispatch = false;
-  }
-
   if (aVisitor.mEvent->mMessage == eBlur) {
     // Set mWantsPreHandleEvent and fire change event in PreHandleEvent to
     // prevent it breaks event target chain creation.
     aVisitor.mWantsPreHandleEvent = true;
   }
 
   nsGenericHTMLFormElementWithState::GetEventTargetParent(aVisitor);
 }
@@ -515,20 +501,16 @@ nsresult HTMLTextAreaElement::PostHandle
     } else {  // eBlur
       mCanShowInvalidUI = true;
       mCanShowValidUI = true;
     }
 
     UpdateState(true);
   }
 
-  // Reset the flag for other content besides this text field
-  aVisitor.mEvent->mFlags.mNoContentDispatch =
-      ((aVisitor.mItemFlags & NS_NO_CONTENT_DISPATCH) != 0);
-
   return NS_OK;
 }
 
 void HTMLTextAreaElement::DoneAddingChildren(bool aHaveNotified) {
   if (!mValueChanged) {
     if (!mDoneAddingChildren) {
       // Reset now that we're done adding children if the content sink tried to
       // sneak some text in without calling AppendChildTo.
--- a/editor/libeditor/EditorEventListener.cpp
+++ b/editor/libeditor/EditorEventListener.cpp
@@ -165,16 +165,18 @@ nsresult EditorEventListener::InstallToE
   //     However, if we do so, all click handlers in any frames and frontend
   //     code need to check if it's editable.  It makes easier create new bugs.
   elmP->AddEventListenerByType(this, NS_LITERAL_STRING("mousedown"),
                                TrustedEventsAtCapture());
   elmP->AddEventListenerByType(this, NS_LITERAL_STRING("mouseup"),
                                TrustedEventsAtCapture());
   elmP->AddEventListenerByType(this, NS_LITERAL_STRING("click"),
                                TrustedEventsAtCapture());
+  elmP->AddEventListenerByType(this, NS_LITERAL_STRING("auxclick"),
+                               TrustedEventsAtSystemGroupCapture());
   // Focus event doesn't bubble so adding the listener to capturing phase as
   // system event group.
   elmP->AddEventListenerByType(this, NS_LITERAL_STRING("blur"),
                                TrustedEventsAtSystemGroupCapture());
   elmP->AddEventListenerByType(this, NS_LITERAL_STRING("focus"),
                                TrustedEventsAtSystemGroupCapture());
   elmP->AddEventListenerByType(this, NS_LITERAL_STRING("text"),
                                TrustedEventsAtSystemGroupBubble());
@@ -237,16 +239,18 @@ void EditorEventListener::UninstallFromE
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("drop"),
                                   TrustedEventsAtSystemGroupBubble());
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("mousedown"),
                                   TrustedEventsAtCapture());
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("mouseup"),
                                   TrustedEventsAtCapture());
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("click"),
                                   TrustedEventsAtCapture());
+  elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("auxclick"),
+                                  TrustedEventsAtSystemGroupCapture());
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("blur"),
                                   TrustedEventsAtSystemGroupCapture());
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("focus"),
                                   TrustedEventsAtSystemGroupCapture());
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("text"),
                                   TrustedEventsAtSystemGroupBubble());
   elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("compositionstart"),
                                   TrustedEventsAtSystemGroupBubble());
@@ -393,16 +397,25 @@ EditorEventListener::HandleEvent(Event* 
         return NS_OK;
       }
       RefPtr<MouseEvent> mouseEvent = aEvent->AsMouseEvent();
       return NS_WARN_IF(!mouseEvent) ? NS_OK : MouseUp(mouseEvent);
     }
     // click
     case eMouseClick: {
       WidgetMouseEvent* widgetMouseEvent = internalEvent->AsMouseEvent();
+      // Don't handle non-primary click events
+      if (widgetMouseEvent->button != WidgetMouseEventBase::eLeftButton) {
+        return NS_OK;
+      }
+      MOZ_FALLTHROUGH;
+    }
+    // auxclick
+    case eMouseAuxClick: {
+      WidgetMouseEvent* widgetMouseEvent = internalEvent->AsMouseEvent();
       if (NS_WARN_IF(!widgetMouseEvent)) {
         return NS_OK;
       }
       // If the preceding mousedown event or mouseup event was consumed,
       // editor shouldn't handle this click event.
       if (mMouseDownOrUpConsumedByIME) {
         mMouseDownOrUpConsumedByIME = false;
         widgetMouseEvent->PreventDefault();
@@ -645,19 +658,19 @@ nsresult EditorEventListener::MouseClick
   MOZ_ASSERT(!aMouseClickEvent->DefaultPrevented());
   nsEventStatus status = nsEventStatus_eIgnore;
   RefPtr<EventStateManager> esm = presContext->EventStateManager();
   DebugOnly<nsresult> rv = esm->HandleMiddleClickPaste(
       presShell, aMouseClickEvent, &status, textEditor);
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                        "Failed to paste for the middle button click");
   if (status == nsEventStatus_eConsumeNoDefault) {
-    // Prevent the event from propagating up to be possibly handled
-    // again by the containing window:
-    aMouseClickEvent->StopImmediatePropagation();
+    // We no longer need to StopImmediatePropagation here since
+    // ClickHandlerChild.jsm checks for and ignores editables, so won't
+    // re-handle the event
     aMouseClickEvent->PreventDefault();
   }
   return NS_OK;
 }
 
 bool EditorEventListener::NotifyIMEOfMouseButtonEvent(
     WidgetMouseEvent* aMouseEvent) {
   MOZ_ASSERT(aMouseEvent);
--- a/editor/libeditor/tests/test_bug674770-1.html
+++ b/editor/libeditor/tests/test_bug674770-1.html
@@ -50,17 +50,17 @@ function startTests() {
 
   addEventListener("storage", function(e) {
     is(e.key, "clicked", currentTest.description + "Key should always be 'clicked'");
     is(e.newValue, "true", currentTest.description + "Value should always be 'true'");
     ok(currentTest.linkShouldWork, currentTest.description + "The click operation on the link " + (currentTest.linkShouldWork ? "should work" : "shouldn't work"));
     SimpleTest.executeSoon(runNextTest);
   }, false);
 
-  SpecialPowers.addSystemEventListener(window, "click", function(aEvent) {
+  SpecialPowers.addSystemEventListener(window, "auxclick", function(aEvent) {
     // When the click event should cause default action, e.g., opening the link,
     // the event shouldn't have been consumed except the link handler.
     // However, in e10s mode, it's not consumed during propagating the event but
     // in non-e10s mode, it's consumed during the propagation.  Therefore,
     // we cannot check defaultPrevented value when the link should work as is
     // if there is no way to detect if it's running in e10s mode or not.
     // So, let's skip checking Event.defaultPrevented value when the link should
     // work.  In such case, we should receive "storage" event later.
--- a/editor/libeditor/tests/test_middle_click_paste.html
+++ b/editor/libeditor/tests/test_middle_click_paste.html
@@ -159,22 +159,22 @@ async function doTextareaTests(aTextarea
   }
   aTextarea.addEventListener("paste", pasteEventLogger);
 
   await copyPlaintext("abc");
   aTextarea.focus();
   document.body.addEventListener("click", (event) => { event.preventDefault(); }, {capture: true, once: true});
   inputEvents = [];
   synthesizeMouseAtCenter(aTextarea, {button: 1});
-  is(aTextarea.value, "",
-     "If 'click' event is consumed at capturing phase of the <body>, paste should be canceled");
-  is(pasteEventCount, 0,
-     "If 'click' event is consumed at capturing phase of the <body>, 'paste' event should not be fired");
-  is(inputEvents.length, 0,
-     'No "input" event should be fired when the "click" event is canceled');
+  is(aTextarea.value, "abc",
+     "If 'click' event is consumed at capturing phase of the <body>, paste should not be canceled");
+  is(pasteEventCount, 1,
+     "If 'click' event is consumed at capturing phase of the <body>, 'paste' event should still be fired");
+  is(inputEvents.length, 1,
+     '"input" event should be fired when the "click" event is canceled');
   aTextarea.value = "";
 
   await copyPlaintext("abc");
   aTextarea.focus();
   aTextarea.addEventListener("mouseup", (event) => { event.preventDefault(); }, {once: true});
   pasteEventCount = 0;
   inputEvents = [];
   synthesizeMouseAtCenter(aTextarea, {button: 1});
@@ -189,36 +189,36 @@ async function doTextareaTests(aTextarea
 
   await copyPlaintext("abc");
   aTextarea.focus();
   aTextarea.addEventListener("click", (event) => { event.preventDefault(); }, {once: true});
   pasteEventCount = 0;
   inputEvents = [];
   synthesizeMouseAtCenter(aTextarea, {button: 1});
   is(aTextarea.value, "abc",
-     "Even if 'click' event handler is added to the <textarea>, paste should not be canceled");
+     "If 'click' event handler is added to the <textarea>, paste should not be canceled");
   is(pasteEventCount, 1,
-     "Even if 'click' event handler is added to the <textarea>, 'paste' event should be fired once");
+     "If 'click' event handler is added to the <textarea>, 'paste' event should be fired once");
   is(inputEvents.length, 1,
      'One "input" event should be fired even if "click" event is canceled in bubbling phase');
   checkInputEvent(inputEvents[0], "insertFromPaste", "abc", null, 'even if "click" event is canceled in bubbling phase');
   aTextarea.value = "";
 
   await copyPlaintext("abc");
   aTextarea.focus();
   aTextarea.addEventListener("auxclick", (event) => { event.preventDefault(); }, {once: true});
   pasteEventCount = 0;
   inputEvents = [];
   synthesizeMouseAtCenter(aTextarea, {button: 1});
-  todo_is(aTextarea.value, "",
-          "If 'auxclick' event is consumed, paste should be canceled");
-  todo_is(pasteEventCount, 0,
-          "If 'auxclick' event is consumed, 'paste' event should not be fired once");
-  todo_is(inputEvents.length, 0,
-          'No "input" event should be fired if "auxclick" event is canceled');
+  is(aTextarea.value, "",
+     "If 'auxclick' event is consumed, paste should be canceled");
+  is(pasteEventCount, 0,
+     "If 'auxclick' event is consumed, 'paste' event should not be fired once");
+  is(inputEvents.length, 0,
+     'No "input" event should be fired if "auxclick" event is canceled');
   aTextarea.value = "";
 
   aTextarea.removeEventListener("paste", pasteEventLogger);
   aTextarea.removeEventListener("input", onInput);
 }
 
 async function doContenteditableTests(aEditableDiv) {
   let inputEvents = [];
@@ -246,22 +246,22 @@ async function doContenteditableTests(aE
   }
   aEditableDiv.addEventListener("paste", pasteEventLogger);
 
   await copyPlaintext("abc");
   aEditableDiv.focus();
   window.addEventListener("click", (event) => { event.preventDefault(); }, {capture: true, once: true});
   inputEvents = [];
   synthesizeMouseAtCenter(aEditableDiv, {button: 1});
-  is(aEditableDiv.innerHTML, "",
-     "If 'click' event is consumed at capturing phase of the window, paste should be canceled");
-  is(pasteEventCount, 0,
+  is(aEditableDiv.innerHTML, "abc",
+     "If 'click' event is consumed at capturing phase of the window, paste should not be canceled");
+  is(pasteEventCount, 1,
      "If 'click' event is consumed at capturing phase of the window, 'paste' event should be fired once");
-  is(inputEvents.length, 0,
-     'No "input" event should be fired when the "click" event is canceled (contenteditable)');
+  is(inputEvents.length, 1,
+     '"input" event should still be fired when the "click" event is canceled (contenteditable)');
   aEditableDiv.innerHTML = "";
 
   await copyPlaintext("abc");
   aEditableDiv.focus();
   aEditableDiv.addEventListener("mouseup", (event) => { event.preventDefault(); }, {once: true});
   pasteEventCount = 0;
   inputEvents = [];
   synthesizeMouseAtCenter(aEditableDiv, {button: 1});
@@ -292,22 +292,22 @@ async function doContenteditableTests(aE
   aEditableDiv.innerHTML = "";
 
   await copyPlaintext("abc");
   aEditableDiv.focus();
   aEditableDiv.addEventListener("auxclick", (event) => { event.preventDefault(); }, {once: true});
   pasteEventCount = 0;
   inputEvents = [];
   synthesizeMouseAtCenter(aEditableDiv, {button: 1});
-  todo_is(aEditableDiv.innerHTML, "",
-          "If 'auxclick' event is consumed, paste should be canceled");
-  todo_is(pasteEventCount, 0,
-          "If 'auxclick' event is consumed, 'paste' event should not be fired");
-  todo_is(inputEvents.length, 0,
-          'No "input" event should be fired if "auxclick" event is canceled (contenteditable)');
+  is(aEditableDiv.innerHTML, "",
+     "If 'auxclick' event is consumed, paste should be canceled");
+  is(pasteEventCount, 0,
+     "If 'auxclick' event is consumed, 'paste' event should not be fired");
+  is(inputEvents.length, 0,
+     'No "input" event should be fired if "auxclick" event is canceled (contenteditable)');
   aEditableDiv.innerHTML = "";
 
   // If clipboard event is disabled, InputEvent.dataTransfer should have only empty string.
   await SpecialPowers.pushPrefEnv({"set": [["dom.event.clipboardevents.enabled", false]]});
   await copyPlaintext("abc");
   aEditableDiv.focus();
   pasteEventCount = 0;
   inputEvents = [];
@@ -378,18 +378,18 @@ async function doNestedEditorTests(aEdit
      "Clicking in <textarea> in an editable <div> should paste the clipboard text into the <textarea>");
   is(aEditableDiv.innerHTML, '<p id="p">foo</p><textarea id="textarea"></textarea>',
      "Pasting in the <textarea> shouldn't be handled by the HTMLEditor");
 
   textarea.value = "";
   textarea.readOnly = true;
   pasteTarget = null;
   synthesizeMouseAtCenter(textarea, {button: 1});
-  todo_is(pasteTarget, textarea,
-          "Target of 'paste' event should be the clicked <textarea> even if it's read-only");
+  is(pasteTarget, textarea,
+     "Target of 'paste' event should be the clicked <textarea> even if it's read-only");
   is(textarea.value, "",
      "Clicking in read-only <textarea> in an editable <div> should not paste the clipboard text into the read-only <textarea>");
   // HTMLEditor thinks that read-only <textarea> is not modifiable.
   // Therefore, HTMLEditor does not paste the text.
   is(aEditableDiv.innerHTML, '<p id="p">foo</p><textarea id="textarea" readonly=""></textarea>',
      "Clicking in read-only <textarea> shouldn't cause pasting the clipboard text into its parent HTMLEditor");
 
   textarea.value = "";
@@ -420,18 +420,18 @@ async function doAfterRemoveOfClickedEle
   let pasteTarget = null;
   document.addEventListener("paste", (aEvent) => { pasteTarget = aEvent.target; }, {once: true});
   document.addEventListener("auxclick", (aEvent) => {
     is(aEvent.target.getAttribute("id"), "span",
        "Target of auxclick event should be the <span> element");
     span.parentElement.removeChild(span);
   }, {once: true});
   synthesizeMouseAtCenter(span, {button: 1});
-  todo_is(pasteTarget.getAttribute("id"), "p",
-          "Target of 'paste' event should be the <p> element since <span> has gone");
+  is(pasteTarget.getAttribute("id"), "p",
+     "Target of 'paste' event should be the <p> element since <span> has gone");
   // XXX Currently, pasted to start of the <p> because EventStateManager
   //     do not recompute event target frame.
   todo_is(aEditableDiv.innerHTML, '<p id="p">fooCLIPBOARD TEXT</p>',
           "Clipbpard text should looks like replacing the <span> element");
   aEditableDiv.innerHTML = "";
 }
 
 async function doTests() {
--- a/widget/tests/test_assign_event_data.html
+++ b/widget/tests/test_assign_event_data.html
@@ -287,18 +287,17 @@ const kTests = [
                               { button: 0 });
     },
     canRun() {
       return true;
     },
     todoMismatch: [],
   },
   { description: "WidgetMouseEvent (click of middle button with Shift)",
-    // XXX I'm not sure why middle click event isn't fired on button element.
-    targetID: "input-text", eventType: "click",
+    targetID: "button", eventType: "auxclick",
     dispatchEvent() {
       document.getElementById(this.targetID).value = "";
       synthesizeMouseAtCenter(document.getElementById(this.targetID),
                               { button: 1, shiftKey: true, pressure: 0.5 });
     },
     canRun() {
       return true;
     },