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;
+ }
+
}