Title: [231950] trunk
Revision
231950
Author
[email protected]
Date
2018-05-18 07:08:45 -0700 (Fri, 18 May 2018)

Log Message

[modern-media-controls] AirPlaySupport should be disabled by default
https://bugs.webkit.org/show_bug.cgi?id=185658
<rdar://problem/40272213>

Reviewed by Simon Fraser.

Source/WebCore:

We now only enable AirplaySupport if the controls are visible to the user _and_ media has played.

Test: media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play.html

* Modules/modern-media-controls/media/airplay-support.js:
(AirplaySupport.prototype.enable):
(AirplaySupport.prototype.controlsUserVisibilityDidChange):
(AirplaySupport.prototype._shouldBeEnabled):
(AirplaySupport):

LayoutTests:

Add a new test that checks that we create an AirplaySupport object only after media has started playing.
We also modify a couple of existing tests so they are no longer flaky, as a first pass of this patch
revealed some flakiness.

* media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play-expected.txt: Added.
* media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play.html: Added.
* media/modern-media-controls/scrubber-support/scrubber-support-drag-expected.txt:
* media/modern-media-controls/scrubber-support/scrubber-support-drag.html:
* media/modern-media-controls/volume-support/volume-support-click-expected.txt:
* media/modern-media-controls/volume-support/volume-support-click.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (231949 => 231950)


--- trunk/LayoutTests/ChangeLog	2018-05-18 08:11:17 UTC (rev 231949)
+++ trunk/LayoutTests/ChangeLog	2018-05-18 14:08:45 UTC (rev 231950)
@@ -1,5 +1,24 @@
 2018-05-18  Antoine Quint  <[email protected]>
 
+        [modern-media-controls] AirPlaySupport should be disabled by default
+        https://bugs.webkit.org/show_bug.cgi?id=185658
+        <rdar://problem/40272213>
+
+        Reviewed by Simon Fraser.
+
+        Add a new test that checks that we create an AirplaySupport object only after media has started playing.
+        We also modify a couple of existing tests so they are no longer flaky, as a first pass of this patch
+        revealed some flakiness.
+
+        * media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play-expected.txt: Added.
+        * media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play.html: Added.
+        * media/modern-media-controls/scrubber-support/scrubber-support-drag-expected.txt:
+        * media/modern-media-controls/scrubber-support/scrubber-support-drag.html:
+        * media/modern-media-controls/volume-support/volume-support-click-expected.txt:
+        * media/modern-media-controls/volume-support/volume-support-click.html:
+
+2018-05-18  Antoine Quint  <[email protected]>
+
         [Web Animations] Turn Web Animations with CSS integration on for test runners
         https://bugs.webkit.org/show_bug.cgi?id=184819
         <rdar://problem/39597337>

Added: trunk/LayoutTests/media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play-expected.txt (0 => 231950)


--- trunk/LayoutTests/media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play-expected.txt	2018-05-18 14:08:45 UTC (rev 231950)
@@ -0,0 +1,23 @@
+Testing AirPlaySupport is only enabled once media has started playing.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Starting test, the media can be played but hasn't started playing.
+
+Making AirPlay routes available.
+
+Airplay routes are available and controls are visible on the screen, but since the media hasn't played yet, AirplaySupport should be disabled.
+PASS controls.airplayButton.uiDelegate is undefined.
+PASS controls.visible is true
+PASS controls.faded is false
+
+We play the media so that the Airplay button can be enabled.
+
+Media played, AirplaySupport should become enabled now.
+PASS !!controls.airplayButton.uiDelegate became true
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play.html (0 => 231950)


--- trunk/LayoutTests/media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play.html	                        (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play.html	2018-05-18 14:08:45 UTC (rev 231950)
@@ -0,0 +1,83 @@
+<script src=""
+<script src="" type="text/_javascript_"></script>
+<body>
+<video src="" style="width: 320px; height: 240px;" preload controls></video>
+<div id="host"></div>
+<script type="text/_javascript_">
+
+window.jsTestIsAsync = true;
+
+description("Testing <code>AirPlaySupport</code> is only enabled once media has started playing.");
+
+const container = document.querySelector("div#host");
+const media = document.querySelector("video");
+const mediaController = createControls(container, media, null);
+const controls = mediaController.controls;
+
+controls.autoHideController.autoHideDelay = 100;
+
+media.addEventListener("canplay", startTest);
+
+function startTest()
+{
+    debug("Starting test, the media can be played but hasn't started playing.");
+
+    makeAirPlayAvailable();
+}
+
+function makeAirPlayAvailable()
+{
+    debug("");
+    debug("Making AirPlay routes available.");
+    media.addEventListener("webkitplaybacktargetavailabilitychanged", playbackTargetAvailabilityChangedOnce, true);
+    window.internals.setMockMediaPlaybackTargetPickerEnabled(true);
+}
+
+function playbackTargetAvailabilityChangedOnce(event)
+{
+    media.removeEventListener('webkitplaybacktargetavailabilitychanged', playbackTargetAvailabilityChangedOnce, true);
+    media.addEventListener('webkitplaybacktargetavailabilitychanged', playbackTargetAvailabilityChangedAgain, true);
+
+    window.internals.setMockMediaPlaybackTargetPickerState('Sleepy TV', 'DeviceAvailable');
+}
+
+function playbackTargetAvailabilityChangedAgain(event)
+{
+    // setMockMediaPlaybackTargetPickerState happens asynchronously in WK2 and a
+    // "webkitplaybacktargetavailabilitychanged" is always sent when an event listener
+    // is added, so we may get a "not available" event first.
+    if (event.availability == 'not-available')
+        return;
+
+    media.removeEventListener('webkitplaybacktargetavailabilitychanged', playbackTargetAvailabilityChangedAgain, true);
+
+    debug("");
+    debug("Airplay routes are available and controls are visible on the screen, but since the media hasn't played yet, AirplaySupport should be disabled.");
+    shouldBeUndefined("controls.airplayButton.uiDelegate");
+    shouldBeTrue("controls.visible");
+    shouldBeFalse("controls.faded");
+
+    debug("");
+    debug("We play the media so that the Airplay button can be enabled.");
+    media.addEventListener("play", mediaDidPlay);
+    media.play();
+}
+
+function mediaDidPlay()
+{
+    debug("");
+    debug("Media played, AirplaySupport should become enabled now.");
+    shouldBecomeEqual("!!controls.airplayButton.uiDelegate", "true", finishTest);
+}
+
+function finishTest()
+{
+    debug("");
+    container.remove();
+    media.remove();
+    finishJSTest();
+}
+
+</script>
+<script src=""
+</body>

Modified: trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-drag-expected.txt (231949 => 231950)


--- trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-drag-expected.txt	2018-05-18 08:11:17 UTC (rev 231949)
+++ trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-drag-expected.txt	2018-05-18 14:08:45 UTC (rev 231950)
@@ -4,7 +4,7 @@
 
 
 PASS media.currentTime is within 0.2 of 3.0136
-PASS media.currentTime is 0
+PASS media.currentTime became 0
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-drag.html (231949 => 231950)


--- trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-drag.html	2018-05-18 08:11:17 UTC (rev 231949)
+++ trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-drag.html	2018-05-18 14:08:45 UTC (rev 231950)
@@ -24,7 +24,6 @@
 const media = document.querySelector("video");
 const mediaController = createControls(container, media, null);
 
-let numberOfEvents = 0;
 scheduler.frameDidFire = function() {
     if (media.paused)
         return;
@@ -42,24 +41,21 @@
     const centerY = bounds.top + bounds.height / 2;
 
     media.addEventListener("timeupdate", () => {
-        numberOfEvents++;
+        shouldBeCloseTo("media.currentTime", media.duration / 2, 0.2);
+        const delta = dragEndX - dragStartX;
+        const iterations = Math.abs(delta);
 
-        if (numberOfEvents == 1) {
-            shouldBeCloseTo("media.currentTime", media.duration / 2, 0.2);
-            const delta = dragEndX - dragStartX;
-            const iterations = Math.abs(delta);
-            for (let i = 1; i <= iterations; ++i)
-                eventSender.mouseMoveTo(dragStartX + i * Math.sign(delta), centerY);
+        for (let i = 1; i <= iterations; ++i)
+            eventSender.mouseMoveTo(dragStartX + i * Math.sign(delta), centerY);
 
-            eventSender.mouseUp();
-        } else {
-            shouldBe("media.currentTime", "0");
+        eventSender.mouseUp();
+
+        shouldBecomeEqual("media.currentTime", "0", () => {
             container.remove();
             media.remove();
             finishJSTest();
-        }
-    
-    });
+        });
+    }, { once: true });
 
     // Start dragging.
     eventSender.mouseMoveTo(dragStartX, centerY);

Modified: trunk/LayoutTests/media/modern-media-controls/volume-support/volume-support-click-expected.txt (231949 => 231950)


--- trunk/LayoutTests/media/modern-media-controls/volume-support/volume-support-click-expected.txt	2018-05-18 08:11:17 UTC (rev 231949)
+++ trunk/LayoutTests/media/modern-media-controls/volume-support/volume-support-click-expected.txt	2018-05-18 14:08:45 UTC (rev 231950)
@@ -3,8 +3,11 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
+PASS media.paused became false
+PASS !!muteButtonElement.getBoundingClientRect().width became true
+PASS !!volumeSliderElement.getBoundingClientRect().width became true
 PASS mediaController.controls.volumeSlider.parent.visible is true
-PASS media.volume is 0.51
+PASS media.volume became 0.51
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/media/modern-media-controls/volume-support/volume-support-click.html (231949 => 231950)


--- trunk/LayoutTests/media/modern-media-controls/volume-support/volume-support-click.html	2018-05-18 08:11:17 UTC (rev 231949)
+++ trunk/LayoutTests/media/modern-media-controls/volume-support/volume-support-click.html	2018-05-18 14:08:45 UTC (rev 231950)
@@ -24,43 +24,32 @@
 const media = document.querySelector("video");
 const mediaController = createControls(container, media, null);
 
-let numberOfFrames = 0;
-scheduler.frameDidFire = function() {
-    const muteButtonElement = mediaController.controls.muteButton.element;
-    const muteButtonBounds = muteButtonElement.getBoundingClientRect();
+const muteButtonElement = mediaController.controls.muteButton.element;
+const volumeSliderElement = mediaController.controls.volumeSlider.element;
 
-    if (media.paused || muteButtonBounds.width === 0)
-        return;
-
-    numberOfFrames++;
-
-    if (numberOfFrames == 1) {
+shouldBecomeEqual("media.paused", "false", () => {
+    shouldBecomeEqual("!!muteButtonElement.getBoundingClientRect().width", "true", () => {
         // Controls are now visible, let's hover over the mute button to make the volume control visible.
+        const muteButtonBounds = muteButtonElement.getBoundingClientRect();
         eventSender.mouseMoveTo(muteButtonBounds.left + muteButtonBounds.width / 2, muteButtonBounds.top + muteButtonBounds.height / 2);
-    } else if (numberOfFrames == 2) {
-        // Volume slider is visible, let's click in the middle of it.
-        const volumeSliderBounds = mediaController.controls.volumeSlider.element.getBoundingClientRect();
-        eventSender.mouseMoveTo(volumeSliderBounds.left + volumeSliderBounds.width / 2, volumeSliderBounds.top + volumeSliderBounds.height / 2);
-        eventSender.mouseDown();
-        eventSender.mouseUp();
 
-        // Ensure the volume slider remains visible.
-        shouldBeTrue("mediaController.controls.volumeSlider.parent.visible");
+        shouldBecomeEqual("!!volumeSliderElement.getBoundingClientRect().width", "true", () => {
+            // Volume slider is visible, let's click in the middle of it.
+            const volumeSliderBounds = volumeSliderElement.getBoundingClientRect();
+            eventSender.mouseMoveTo(volumeSliderBounds.left + volumeSliderBounds.width / 2, volumeSliderBounds.top + volumeSliderBounds.height / 2);
+            eventSender.mouseDown();
+            eventSender.mouseUp();
 
-        scheduler.frameDidFire = null;
-    }
-};
+            // Ensure the volume slider remains visible.
+            shouldBeTrue("mediaController.controls.volumeSlider.parent.visible");
 
-// First, ensure controls are shown.
-mediaController.controls.showsStartButton = false;
-
-media.addEventListener("volumechange", () => {
-    // Because the slider has a 9pt-wide knob and tests are ran at 1x, we can't get 0.5 here, and instead get 0.51 since
-    // the slider will only increment on whole pixels.
-    shouldBe("media.volume", "0.51");
-    container.remove();
-    media.remove();
-    finishJSTest();
+            shouldBecomeEqual("media.volume", "0.51", () => {
+                container.remove();
+                media.remove();
+                finishJSTest();
+            });
+        });
+    });
 });
 
 </script>

Modified: trunk/Source/WebCore/ChangeLog (231949 => 231950)


--- trunk/Source/WebCore/ChangeLog	2018-05-18 08:11:17 UTC (rev 231949)
+++ trunk/Source/WebCore/ChangeLog	2018-05-18 14:08:45 UTC (rev 231950)
@@ -1,3 +1,21 @@
+2018-05-18  Antoine Quint  <[email protected]>
+
+        [modern-media-controls] AirPlaySupport should be disabled by default
+        https://bugs.webkit.org/show_bug.cgi?id=185658
+        <rdar://problem/40272213>
+
+        Reviewed by Simon Fraser.
+
+        We now only enable AirplaySupport if the controls are visible to the user _and_ media has played.
+
+        Test: media/modern-media-controls/airplay-support/airplay-support-disable-event-listeners-until-play.html
+
+        * Modules/modern-media-controls/media/airplay-support.js:
+        (AirplaySupport.prototype.enable):
+        (AirplaySupport.prototype.controlsUserVisibilityDidChange):
+        (AirplaySupport.prototype._shouldBeEnabled):
+        (AirplaySupport):
+
 2018-05-18  Tim Horton  <[email protected]>
 
         Stop softlinking QuickLook when loading from client-registered schemes

Modified: trunk/Source/WebCore/Modules/modern-media-controls/media/airplay-support.js (231949 => 231950)


--- trunk/Source/WebCore/Modules/modern-media-controls/media/airplay-support.js	2018-05-18 08:11:17 UTC (rev 231949)
+++ trunk/Source/WebCore/Modules/modern-media-controls/media/airplay-support.js	2018-05-18 14:08:45 UTC (rev 231950)
@@ -38,6 +38,12 @@
         return ["webkitplaybacktargetavailabilitychanged", "webkitcurrentplaybacktargetiswirelesschanged"];
     }
 
+    enable()
+    {
+        if (this._shouldBeEnabled())
+            super.enable();
+    }
+
     buttonWasPressed(control)
     {
         this.mediaController.media.webkitShowPlaybackTargetPicker();
@@ -45,8 +51,7 @@
 
     controlsUserVisibilityDidChange()
     {
-        const controls = this.mediaController.controls;
-        if (controls.visible && !controls.faded)
+        if (this._shouldBeEnabled())
             this.enable();
         else
             this.disable();
@@ -67,4 +72,15 @@
         this.mediaController.controls.muteButton.enabled = !this.control.on;
     }
 
+    // Private
+
+    _shouldBeEnabled()
+    {
+        if (!this.mediaController.hasPlayed)
+            return false;
+
+        const controls = this.mediaController.controls;
+        return controls.visible && !controls.faded;
+    }
+
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to