Diff
Modified: trunk/LayoutTests/ChangeLog (219661 => 219662)
--- trunk/LayoutTests/ChangeLog 2017-07-19 19:18:40 UTC (rev 219661)
+++ trunk/LayoutTests/ChangeLog 2017-07-19 20:13:15 UTC (rev 219662)
@@ -1,3 +1,20 @@
+2017-07-19 Antoine Quint <[email protected]>
+
+ [iOS] REGRESSION: Scrubbing media using built-in controls does not pause media
+ https://bugs.webkit.org/show_bug.cgi?id=174650
+ <rdar://problem/33401877>
+
+ Reviewed by Dean Jackson.
+
+ Rebaseline and turn back on all the ScrubberSupport tests on macOS and iOS.
+
+ * media/modern-media-controls/scrubber-support/ipad/scrubber-support-drag-expected.txt:
+ * media/modern-media-controls/scrubber-support/ipad/scrubber-support-drag.html:
+ * media/modern-media-controls/scrubber-support/scrubber-support-media-api-expected.txt:
+ * media/modern-media-controls/scrubber-support/scrubber-support-media-api.html:
+ * platform/ios-simulator/TestExpectations:
+ * platform/mac/TestExpectations:
+
2017-07-19 Nan Wang <[email protected]>
AX: Web page reloaded when a node is labelling multiple childnodes
Modified: trunk/LayoutTests/media/modern-media-controls/scrubber-support/ipad/scrubber-support-drag-expected.txt (219661 => 219662)
--- trunk/LayoutTests/media/modern-media-controls/scrubber-support/ipad/scrubber-support-drag-expected.txt 2017-07-19 19:18:40 UTC (rev 219661)
+++ trunk/LayoutTests/media/modern-media-controls/scrubber-support/ipad/scrubber-support-drag-expected.txt 2017-07-19 20:13:15 UTC (rev 219662)
@@ -3,7 +3,9 @@
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
-FAIL media.currentTime should be within 0.01 of 3.0136. Was 0.
+PASS mediaController.controls.timeControl.elapsedTimeLabel.element.getBoundingClientRect().width became different from 0
+PASS media.currentTime became 3.1872
+
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/media/modern-media-controls/scrubber-support/ipad/scrubber-support-drag.html (219661 => 219662)
--- trunk/LayoutTests/media/modern-media-controls/scrubber-support/ipad/scrubber-support-drag.html 2017-07-19 19:18:40 UTC (rev 219661)
+++ trunk/LayoutTests/media/modern-media-controls/scrubber-support/ipad/scrubber-support-drag.html 2017-07-19 20:13:15 UTC (rev 219662)
@@ -7,13 +7,10 @@
position: absolute;
top: 0;
left: 0;
- }
-
- video {
width: 720px;
height: 240px;
}
-
+
</style>
<video src="" autoplay controls></video>
<div id="host"></div>
@@ -26,51 +23,39 @@
const container = document.querySelector("div#host");
const media = document.querySelector("video");
const mediaController = createControls(container, media, null);
+let bounds;
-let numberOfEvents = 0;
-scheduler.frameDidFire = function() {
- if (media.paused)
- return;
-
+media.addEventListener("play", () => {
media.pause();
+ if (isNaN(media.duration))
+ media.addEventListener("durationchange", runTest);
+ else
+ runTest();
+});
- const input = mediaController.controls.timeControl.scrubber.children[1].element;
- const bounds = input.getBoundingClientRect();
+function runTest()
+{
+ shouldBecomeDifferent("mediaController.controls.timeControl.elapsedTimeLabel.element.getBoundingClientRect().width", "0", () => {
+ const bounds = mediaController.controls.timeControl.scrubber.children[1].element.getBoundingClientRect();
+ const minX = bounds.left + 12;
+ const dragStartX = minX;
+ const dragEndX = minX + bounds.width / 2;
+ const centerY = bounds.top + bounds.height / 2;
- if (bounds.width === 0)
- return;
+ testRunner.runUIScript(`
+ uiController.dragFromPointToPoint(${dragStartX}, ${centerY}, ${dragEndX}, ${centerY}, 0.15, function() {
+ uiController.uiScriptComplete("Done");
+ });`);
- media.addEventListener("timeupdate", () => {
- numberOfEvents++;
-
- debug("timeupdate event with media.currentTime = " + media.currentTime);
+ shouldBecomeEqual("media.currentTime", "3.1872", () => {
+ debug("");
+ media.remove();
+ container.remove();
+ finishJSTest();
+ });
});
+}
- const minX = bounds.left + 7;
- const dragStartX = minX;
- const dragEndX = minX + bounds.width / 2;
- const centerY = bounds.top + bounds.height / 2;
-
- const point = document.body.appendChild(document.createElement("div"));
- point.style.left = minX + "px";
- point.style.top = centerY + "px";
- point.style.width = "1px";
- point.style.height = "1px";
- point.style.position = "absolute";
- point.style.backgroundColor = "red";
-
- debug(`
- uiController.dragFromPointToPoint(${dragStartX}, ${centerY}, ${dragEndX}, ${centerY}, 0.15, function() {
- uiController.uiScriptComplete("Done");
- });`);
- testRunner.runUIScript(`
- uiController.dragFromPointToPoint(${dragStartX}, ${centerY}, ${dragEndX}, ${centerY}, 0.15, function() {
- uiController.uiScriptComplete("Done");
- });`);
-
- scheduler.frameDidFire = null;
-};
-
</script>
<script src=""
</body>
Modified: trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-media-api-expected.txt (219661 => 219662)
--- trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-media-api-expected.txt 2017-07-19 19:18:40 UTC (rev 219661)
+++ trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-media-api-expected.txt 2017-07-19 20:13:15 UTC (rev 219662)
@@ -4,7 +4,7 @@
PASS mediaController.controls.timeControl.scrubber.value is 0
-PASS mediaController.controls.timeControl.scrubber.value is 0.5
+PASS mediaController.controls.timeControl.scrubber.value became 0.5
PASS successfullyParsed is true
Modified: trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-media-api.html (219661 => 219662)
--- trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-media-api.html 2017-07-19 19:18:40 UTC (rev 219661)
+++ trunk/LayoutTests/media/modern-media-controls/scrubber-support/scrubber-support-media-api.html 2017-07-19 20:13:15 UTC (rev 219662)
@@ -1,8 +1,13 @@
<script src=""
<script src="" type="text/_javascript_"></script>
<body>
-<video src="" style="width: 320px; height: 240px;"></video>
-<div id="shadow"></div>
+<style type="text/css" media="screen">
+ video, #host {
+ position: absolute; width: 320px; height: 240px;
+ }
+</style>
+<video src="" controls autoplay></video>
+<div id="host"></div>
<script type="text/_javascript_">
window.jsTestIsAsync = true;
@@ -9,22 +14,32 @@
description("Testing the <code>ScrubberSupport</code> behavior by using the media API.");
-const shadowRoot = document.querySelector("div#shadow").attachShadow({ mode: "open" });
+const host = document.querySelector("div#host");
const media = document.querySelector("video");
-const mediaController = createControls(shadowRoot, media, null);
+const mediaController = createControls(host, media, null);
shouldBe("mediaController.controls.timeControl.scrubber.value", "0");
-media.addEventListener("durationchange", () => {
+media.addEventListener("play", () => {
+ media.pause();
+ if (isNaN(media.duration))
+ media.addEventListener("durationchange", runTest);
+ else
+ runTest();
+});
+
+function runTest()
+{
media.addEventListener("timeupdate", () => {
- shouldBe("mediaController.controls.timeControl.scrubber.value", "0.5");
- debug("");
- shadowRoot.host.remove();
- media.remove();
- finishJSTest();
+ shouldBecomeEqual("mediaController.controls.timeControl.scrubber.value", "0.5", () => {
+ debug("");
+ host.remove();
+ media.remove();
+ finishJSTest();
+ });
});
media.currentTime = media.duration / 2;
-});
+}
</script>
<script src=""
Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (219661 => 219662)
--- trunk/LayoutTests/platform/ios-simulator/TestExpectations 2017-07-19 19:18:40 UTC (rev 219661)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations 2017-07-19 20:13:15 UTC (rev 219662)
@@ -96,6 +96,7 @@
media/modern-media-controls/rewind-button [ Pass ]
media/modern-media-controls/scheduler [ Pass ]
media/modern-media-controls/scrubber [ Pass ]
+media/modern-media-controls/scrubber-support [ Pass ]
media/modern-media-controls/skip-back-button [ Pass ]
media/modern-media-controls/skip-forward-button [ Pass ]
media/modern-media-controls/slider [ Pass ]
@@ -116,6 +117,7 @@
media/modern-media-controls/mute-support/mute-support-press-on-button.html [ Skip ]
media/modern-media-controls/pip-support/ipad/pip-support-tap.html [ Skip ]
media/modern-media-controls/placard-support/ipad [ Skip ]
+media/modern-media-controls/scrubber-support/ipad/scrubber-support-drag.html [ Skip ]
# These tests rely on fullscreen which do not use the WebKit media controls on iOS
media/modern-media-controls/controls-visibility-support/controls-visibility-support-fullscreen-on-parent-element.html [ Skip ]
@@ -132,6 +134,8 @@
media/modern-media-controls/media-documents/media-document-audio-mac-sizing.html [ Skip ]
media/modern-media-controls/media-documents/media-document-video-mac-sizing.html [ Skip ]
media/modern-media-controls/playback-support/playback-support-button-click.html [ Skip ]
+media/modern-media-controls/scrubber-support/scrubber-support-click.html [ Skip ]
+media/modern-media-controls/scrubber-support/scrubber-support-drag.html [ Skip ]
webkit.org/b/172965 media/track/track-cue-overlap-snap-to-lines-not-set.html [ Failure ]
Modified: trunk/LayoutTests/platform/mac/TestExpectations (219661 => 219662)
--- trunk/LayoutTests/platform/mac/TestExpectations 2017-07-19 19:18:40 UTC (rev 219661)
+++ trunk/LayoutTests/platform/mac/TestExpectations 2017-07-19 20:13:15 UTC (rev 219662)
@@ -1577,6 +1577,7 @@
media/modern-media-controls/rewind-button [ Pass ]
media/modern-media-controls/scheduler [ Pass ]
media/modern-media-controls/scrubber [ Pass ]
+media/modern-media-controls/scrubber-support [ Pass ]
media/modern-media-controls/skip-back-button [ Pass ]
media/modern-media-controls/skip-forward-button [ Pass ]
media/modern-media-controls/slider [ Pass ]
@@ -1594,6 +1595,7 @@
media/modern-media-controls/media-documents/ipad [ Skip ]
media/modern-media-controls/media-documents/media-document-audio-ios-sizing.html [ Skip ]
media/modern-media-controls/media-documents/media-document-video-ios-sizing.html [ Skip ]
+media/modern-media-controls/scrubber-support/ipad [ Skip ]
# These tests use Picture-in-Picture which isn't supported on El Capitan.
[ ElCapitan ] media/modern-media-controls/placard-support/placard-support-pip.html [ Skip ]
Modified: trunk/Source/WebCore/ChangeLog (219661 => 219662)
--- trunk/Source/WebCore/ChangeLog 2017-07-19 19:18:40 UTC (rev 219661)
+++ trunk/Source/WebCore/ChangeLog 2017-07-19 20:13:15 UTC (rev 219662)
@@ -1,3 +1,43 @@
+2017-07-19 Antoine Quint <[email protected]>
+
+ [iOS] REGRESSION: Scrubbing media using built-in controls does not pause media
+ https://bugs.webkit.org/show_bug.cgi?id=174650
+ <rdar://problem/33401877>
+
+ Reviewed by Dean Jackson.
+
+ We would only pause when scrubbing on macOS because we only listened to "mousedown" events on the
+ scrubber's backing <input> element to identify that the user had started interacting with the
+ scrubber.
+
+ Implementing the same technique on iOS required a little more work than just listening to "touchstart"
+ events on the same element. On top of that, we needed to make sure that we would only respond to
+ "touchstart" events on the slider's thumb, and not on the track, since only on macOS should the user
+ be able to click anywhere on the track to scrub. So we turn off pointer-events for the <input> on iOS
+ only, and turn them back on specifically for the thumb.
+
+ There is also some finessing when dealing with touch events where we need to track the identifier of
+ the touch that started the user interaction. So we keep track of it in an ivar and wait until we get
+ a "touchend" event where the changedTouches list contains a touch with that same identifier to ensure
+ the same touch that initiates and ends the scrubbing interaction.
+
+ Finally, we fix another issue that was uncovered while turning back on the ScrubbingSupport tests
+ where we would not trash the cached _value ivar when we initiated scrubbing, which was important since
+ we would mistakenly use the pre-srubbing value during a scrub.
+
+ * Modules/modern-media-controls/controls/slider.css:
+ (.ios .slider > input):
+ (.slider > input::-webkit-slider-thumb):
+ * Modules/modern-media-controls/controls/slider.js:
+ (Slider.prototype.handleEvent):
+ (Slider.prototype._handleMousedownEvent):
+ (Slider.prototype._interactionEndTarget):
+ (Slider.prototype._handleTouchstartEvent):
+ (Slider.prototype._valueWillStartChanging):
+ (Slider.prototype._valueDidStopChanging):
+ (Slider.prototype._handleMouseupEvent):
+ (Slider.prototype._handleTouchendEvent):
+
2017-07-19 Nan Wang <[email protected]>
AX: Web page reloaded when a node is labelling multiple childnodes
Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/slider.css (219661 => 219662)
--- trunk/Source/WebCore/Modules/modern-media-controls/controls/slider.css 2017-07-19 19:18:40 UTC (rev 219661)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/slider.css 2017-07-19 20:13:15 UTC (rev 219662)
@@ -83,6 +83,16 @@
-webkit-appearance: none !important;
}
+.ios .slider > input {
+ /* On iOS only, we want to only capture events on the thumb and not the track. */
+ pointer-events: none;
+
+ /* Make sure we don't show any UI as we drag the scrubber on iOS. */
+ -webkit-user-select: none !important;
+ -webkit-touch-callout: none !important;
+ -webkit-tap-highlight-color: transparent;
+}
+
.slider > input::-webkit-slider-thumb {
width: 9px;
height: 100%;
@@ -90,6 +100,7 @@
box-shadow: none;
background-color: transparent;
-webkit-appearance: none !important;
+ pointer-events: all;
}
/* When disabled, we only want to show the track and turn off interaction. */
Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/slider.js (219661 => 219662)
--- trunk/Source/WebCore/Modules/modern-media-controls/controls/slider.js 2017-07-19 19:18:40 UTC (rev 219661)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/slider.js 2017-07-19 20:13:15 UTC (rev 219662)
@@ -38,7 +38,7 @@
this._container.children = [this._track, this._primaryFill, this._secondaryFill, this._knob];
this._input = new LayoutNode(`<input type="range" min="0" max="1" step="0.001" />`);
- this._input.element.addEventListener("mousedown", this);
+ this._input.element.addEventListener(GestureRecognizer.SupportsTouches ? "touchstart" : "mousedown", this);
this._input.element.addEventListener("input", this);
this._input.element.addEventListener("change", this);
@@ -112,9 +112,15 @@
case "mousedown":
this._handleMousedownEvent();
break;
+ case "touchstart":
+ this._handleTouchstartEvent(event);
+ break;
case "mouseup":
this._handleMouseupEvent();
break;
+ case "touchend":
+ this._handleTouchendEvent(event);
+ break;
case "change":
case "input":
this._valueDidChange();
@@ -154,10 +160,38 @@
_handleMousedownEvent()
{
- const mediaControls = this.parentOfType(MediaControls);
- this._mouseupTarget = (!mediaControls || mediaControls instanceof MacOSInlineMediaControls) ? window : mediaControls.element;
+ this._mouseupTarget = this._interactionEndTarget();
this._mouseupTarget.addEventListener("mouseup", this, true);
+ this._valueWillStartChanging();
+ }
+
+ _interactionEndTarget()
+ {
+ const mediaControls = this.parentOfType(MediaControls);
+ return (!mediaControls || mediaControls instanceof MacOSInlineMediaControls) ? window : mediaControls.element;
+ }
+
+ _handleTouchstartEvent(event)
+ {
+ // We're only interested in the very first touch on the <input>.
+ if (event.touches.length !== 1)
+ return;
+
+ this._initialTouchIdentifier = event.touches[0].identifier;
+
+ this._touchendTarget = this._interactionEndTarget();
+ this._touchendTarget.addEventListener("touchend", this, true);
+
+ this._valueWillStartChanging();
+ }
+
+ _valueWillStartChanging()
+ {
+ // We should no longer cache the value since we'll be interacting with the <input>
+ // so the value should be read back from it dynamically.
+ delete this._value;
+
if (this.uiDelegate && typeof this.uiDelegate.controlValueWillStartChanging === "function")
this.uiDelegate.controlValueWillStartChanging(this);
this.isActive = true;
@@ -172,11 +206,8 @@
this.needsLayout = true;
}
- _handleMouseupEvent()
+ _valueDidStopChanging()
{
- this._mouseupTarget.removeEventListener("mouseup", this, true);
- delete this._mouseupTarget;
-
this.isActive = false;
if (this.uiDelegate && typeof this.uiDelegate.controlValueDidStopChanging === "function")
this.uiDelegate.controlValueDidStopChanging(this);
@@ -184,4 +215,24 @@
this.needsLayout = true;
}
+ _handleMouseupEvent()
+ {
+ this._mouseupTarget.removeEventListener("mouseup", this, true);
+ delete this._mouseupTarget;
+
+ this._valueDidStopChanging();
+ }
+
+ _handleTouchendEvent(event)
+ {
+ if (!Array.from(event.changedTouches).find(touch => touch.identifier === this._initialTouchIdentifier))
+ return;
+
+ this._touchendTarget.removeEventListener("touchend", this, true);
+ delete this._touchendTarget;
+ delete this._initialTouchIdentifier;
+
+ this._valueDidStopChanging();
+ }
+
}