Bug 1402877 - Part 2. Don't let click event dispatch through controlBar to video element. r=jaws
☠☠ backed out by c396dc1fb2c5 ☠ ☠
authorRay Lin <ralin@mozilla.com>
Tue, 26 Sep 2017 16:19:10 +0800
changeset 387928 8dc86e170ef476bf89b48789ed133282a11ca8b7
parent 387927 aa39d335365a7b2e196ce164b2387a8ee7ae9645
child 387929 106f4a9da29f0a189808f885197d4afc0274d0c2
push id32739
push useracraciun@mozilla.com
push dateWed, 25 Oct 2017 09:29:21 +0000
treeherdermozilla-central@252a8528c5ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1402877
milestone58.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 1402877 - Part 2. Don't let click event dispatch through controlBar to video element. r=jaws MozReview-Commit-ID: BUW9PDxCSAY
toolkit/content/tests/widgets/test_videocontrols.html
toolkit/content/widgets/videocontrols.xml
--- a/toolkit/content/tests/widgets/test_videocontrols.html
+++ b/toolkit/content/tests/widgets/test_videocontrols.html
@@ -52,16 +52,17 @@ const muteButtonCenterY = videoHeight - 
 const fullscreenButtonCenterX = videoWidth - Math.round(fullscreenButtonWidth / 2) - controlBarMargin;
 const fullscreenButtonCenterY = videoHeight - Math.round(fullscreenButtonHeight / 2);
 // Scrubber bar is between the play and mute buttons. We don't need it's
 // X center, just the offset of its box.
 const scrubberOffsetX = controlBarMargin + playButtonWidth + scrubberMargin;
 const scrubberCenterY = videoHeight - Math.round(scrubberHeight / 2);
 
 const video = document.getElementById("video");
+const controlBar = getAnonElementWithinVideoByAttribute(video, "anonid", "controlBar");
 
 let expectingEvents;
 let expectingEventPromise;
 
 async function isMuteButtonMuted() {
   const muteButton = getAnonElementWithinVideoByAttribute(video, "anonid", "muteButton");
   await new Promise(SimpleTest.executeSoon);
   return muteButton.getAttribute("muted") === "true";
@@ -326,16 +327,36 @@ add_task(async function whitespace_pause
 add_task(async function click_and_hold_slider() {
   synthesizeMouse(video, scrubberOffsetX + 10, scrubberCenterY, {type: "mousedown", button: 0});
   await waitForEvent("pause", "seeking", "seeked");
 
   synthesizeMouse(video, scrubberOffsetX + 10, scrubberCenterY, {});
   await waitForEvent("play");
 });
 
+/*
+ * Bug 1402877: Don't let click event dispatch through controlBar to video element.
+ */
+add_task(async function click_event_dispatch() {
+  const clientScriptClickHandler = (e) => {
+    ok(false, "Should not receive the event");
+  };
+  video.addEventListener("click", clientScriptClickHandler);
+
+  video.pause();
+  await waitForEvent("pause");
+  video.currentTime = 0.0;
+  await waitForEvent("seeking", "seeked");
+  is(video.paused, true, "checking video play state");
+  synthesizeMouse(video, scrubberOffsetX + 10, scrubberCenterY, {});
+  await waitForEvent("seeking", "seeked");
+
+  video.removeEventListener("click", clientScriptClickHandler);
+});
+
 // Bug 1367194: Always ensure video is paused before finishing the test.
 add_task(async function ensure_video_pause() {
   if (!video.paused) {
     video.pause();
     await waitForEvent("pause");
   }
 });
 
--- a/toolkit/content/widgets/videocontrols.xml
+++ b/toolkit/content/widgets/videocontrols.xml
@@ -705,17 +705,17 @@
             } catch (ex) {}
           }
         }
 
         if (this.controlListeners) {
           for (let element of this.controlListeners) {
             try {
               element.item.removeEventListener(element.event, element.func,
-                { mozSystemGroup: true, capture: element.capture });
+                { mozSystemGroup: element.mozSystemGroup, capture: element.capture });
             } catch (ex) {}
           }
 
           delete this.controlListeners;
         }
 
         this.log("--- videocontrols terminated ---");
       },
@@ -1813,37 +1813,46 @@
 
         var self = this;
         this.controlListeners = [];
 
         // Helper function to add an event listener to the given element
         // Due to this helper function, "Utils" is made available to the event
         // listener functions. Hence declare it as a global for ESLint.
         /* global Utils */
-        function addListener(elem, eventName, func, capture = false) {
+        function addListener(elem, eventName, func, {capture = false, mozSystemGroup = true} = {}) {
           let boundFunc = func.bind(self);
-          self.controlListeners.push({ item: elem, event: eventName, func: boundFunc, capture });
-          elem.addEventListener(eventName, boundFunc, { mozSystemGroup: true, capture });
+          self.controlListeners.push({
+            item: elem,
+            event: eventName,
+            func: boundFunc,
+            capture,
+            mozSystemGroup,
+          });
+          elem.addEventListener(eventName, boundFunc, {mozSystemGroup, capture});
         }
 
         addListener(this.muteButton, "click", this.toggleMute);
         addListener(this.closedCaptionButton, "click", this.toggleClosedCaption);
         addListener(this.fullscreenButton, "click", this.toggleFullscreen);
         addListener(this.playButton, "click", this.clickToPlayClickHandler);
         addListener(this.clickToPlay, "click", this.clickToPlayClickHandler);
         addListener(this.controlsSpacer, "click", this.clickToPlayClickHandler);
         addListener(this.controlsSpacer, "dblclick", this.toggleFullscreen);
 
         addListener(this.videocontrols, "resizevideocontrols", this.adjustControlSize);
         addListener(this.videocontrols, "transitionend", this.onTransitionEnd);
         addListener(this.video.ownerDocument, "mozfullscreenchange", this.onFullscreenChange);
         addListener(this.controlBar, "transitionend", this.onControlBarTransitioned);
         addListener(this.video.ownerDocument, "fullscreenchange", this.onFullscreenChange);
-        addListener(this.video, "keypress", this.keyHandler, true);
-
+        addListener(this.video, "keypress", this.keyHandler, {capture: true});
+        // Prevent any click event within controlBar from dispatching through to video.
+        addListener(this.controlBar, "click", function(event) {
+          event.stopPropagation();
+        }, {mozSystemGroup: false});
         addListener(this.videocontrols, "dragstart", function(event) {
           event.preventDefault(); // prevent dragging of controls image (bug 517114)
         });
 
         if (!this.videocontrols.isTouchControls) {
           addListener(this.scrubber, "input", this.onScrubberInput);
           addListener(this.scrubber, "change", this.onScrubberChange);
           // add mouseup listener additionally to handle the case that `change` event