Diff
Modified: trunk/LayoutTests/ChangeLog (262037 => 262038)
--- trunk/LayoutTests/ChangeLog 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/ChangeLog 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,3 +1,35 @@
+2020-05-21 Peng Liu <peng.l...@apple.com>
+
+ Fix issues of the Picture-in-Picture API under stress tests
+ https://bugs.webkit.org/show_bug.cgi?id=212191
+
+ Reviewed by Eric Carlson.
+
+ Refactor the layout tests for the Picture-in-Picture API with the Mock VideoPresentation Mode.
+
+ * media/picture-in-picture/picture-in-picture-api-css-selector-expected.txt:
+ * media/picture-in-picture/picture-in-picture-api-css-selector.html:
+ * media/picture-in-picture/picture-in-picture-api-enter-pip-1-expected.txt:
+ * media/picture-in-picture/picture-in-picture-api-enter-pip-1.html:
+ * media/picture-in-picture/picture-in-picture-api-enter-pip-2-expected.txt:
+ * media/picture-in-picture/picture-in-picture-api-enter-pip-2.html:
+ * media/picture-in-picture/picture-in-picture-api-enter-pip-3-expected.txt:
+ * media/picture-in-picture/picture-in-picture-api-enter-pip-3.html:
+ * media/picture-in-picture/picture-in-picture-api-enter-pip-4-expected.txt:
+ * media/picture-in-picture/picture-in-picture-api-enter-pip-4.html:
+ * media/picture-in-picture/picture-in-picture-api-events-expected.txt:
+ * media/picture-in-picture/picture-in-picture-api-events.html:
+ * media/picture-in-picture/picture-in-picture-api-exit-pip-1-expected.txt:
+ * media/picture-in-picture/picture-in-picture-api-exit-pip-1.html:
+ * media/picture-in-picture/picture-in-picture-api-exit-pip-2-expected.txt:
+ * media/picture-in-picture/picture-in-picture-api-exit-pip-2.html:
+ * media/picture-in-picture/picture-in-picture-api-pip-window-expected.txt:
+ * media/picture-in-picture/picture-in-picture-api-pip-window.html:
+ * media/picture-in-picture/picture-in-picture-events-expected.txt:
+ * media/picture-in-picture/picture-in-picture-events.html:
+ * media/picture-in-picture/picture-in-picture-interruption-expected.txt:
+ * media/picture-in-picture/picture-in-picture-interruption.html:
+
2020-05-21 Oriol Brufau <obru...@igalia.com>
[css-grid] Don't create renderers for whitespace nodes
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-css-selector-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-css-selector-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-css-selector-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,7 +1,7 @@
This tests that entering and leaving Picture-in-Picture toggles CSS selector.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
-RUN(internals.setPictureInPictureAPITestEnabled(video, true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
RUN(video.src = "" "../content/test"))
EVENT(canplaythrough)
EXPECTED (getComputedStyle(video).color == 'rgb(0, 0, 255)') OK
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-css-selector.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-css-selector.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-css-selector.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -17,16 +17,24 @@
</style>
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
- run('internals.setPictureInPictureAPITestEnabled(video, true)');
+ run('internals.setMockVideoPresentationModeEnabled(true)');
run('video.src = "" "../content/test")');
await waitFor(video, 'canplaythrough');
testExpected('getComputedStyle(video).color', 'rgb(0, 0, 255)');
- runWithKeyDown(function() { video.requestPictureInPicture() });
+ runWithKeyDown(() => {
+ video.requestPictureInPicture();
+ });
+
await waitFor(video, 'enterpictureinpicture');
testExpected('getComputedStyle(video).color', 'rgb(0, 255, 0)');
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-1-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-1-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-1-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,7 +1,7 @@
This tests that request Picture-in-Picture requires a user gesture.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
-RUN(internals.setPictureInPictureAPITestEnabled(video, true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
RUN(video.src = "" "../content/test"))
EVENT(canplaythrough)
EXPECTED (error.name == 'NotAllowedError') OK
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-1.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-1.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-1.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5,10 +5,16 @@
<script src=""
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
- run('internals.setPictureInPictureAPITestEnabled(video, true)');
+ run('internals.setMockVideoPresentationModeEnabled(true)');
+
run('video.src = "" "../content/test")');
await waitFor(video, 'canplaythrough');
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-2-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-2-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-2-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,7 +1,7 @@
This tests that request Picture-in-Picture requires loaded metadata for the video element.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
-RUN(internals.setPictureInPictureAPITestEnabled(video, true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
EXPECTED (error.name == 'InvalidStateError') OK
END OF TEST
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-2.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-2.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-2.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5,11 +5,17 @@
<script src=""
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
- run('internals.setPictureInPictureAPITestEnabled(video, true)');
- runWithKeyDown(function() {
+ run('internals.setMockVideoPresentationModeEnabled(true)');
+
+ runWithKeyDown(() => {
video.requestPictureInPicture()
.then(() => {
failTest('request Picture-in-Picture requires loaded metadata for the video element.')
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-3-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-3-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-3-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,7 +1,7 @@
This tests that request Picture-in-Picture requires video track for the video element.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
-RUN(internals.setPictureInPictureAPITestEnabled(video, true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
RUN(video.src = "" "../content/test"))
EVENT(canplaythrough)
EXPECTED (error.name == 'InvalidStateError') OK
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-3.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-3.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-3.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5,13 +5,19 @@
<script src=""
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
- run('internals.setPictureInPictureAPITestEnabled(video, true)');
+ run('internals.setMockVideoPresentationModeEnabled(true)');
+
run('video.src = "" "../content/test")');
await waitFor(video, 'canplaythrough');
- runWithKeyDown(function() {
+ runWithKeyDown(() => {
video.requestPictureInPicture()
.then(() => {
failTest('request Picture-in-Picture requires video track for the video element.')
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-4-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-4-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-4-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,7 +1,7 @@
This tests that request Picture-in-Picture resolves on user click.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
-RUN(internals.setPictureInPictureAPITestEnabled(video, true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
RUN(video.src = "" "../content/test"))
EVENT(canplaythrough)
END OF TEST
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-4.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-4.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-4.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5,14 +5,19 @@
<script src=""
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
- run('internals.setPictureInPictureAPITestEnabled(video, true)');
+ run('internals.setMockVideoPresentationModeEnabled(true)');
run('video.src = "" "../content/test")');
await waitFor(video, 'canplaythrough');
- runWithKeyDown(function() {
+ runWithKeyDown(() => {
video.requestPictureInPicture()
.then(() => {
document.exitPictureInPicture().then(endTest).catch(() => {
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-events-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-events-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-events-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,7 +1,7 @@
This tests that events are fired correctly when a video element enters and exits the Picture-in-Picture mode.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
-RUN(internals.setPictureInPictureAPITestEnabled(video, true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
RUN(video.src = "" "../content/test"))
EVENT(canplaythrough)
EVENT(enterpictureinpicture)
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-events.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-events.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-events.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5,15 +5,23 @@
<script src=""
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
- run('internals.setPictureInPictureAPITestEnabled(video, true)');
+ run('internals.setMockVideoPresentationModeEnabled(true)');
run('video.src = "" "../content/test")');
await waitFor(video, 'canplaythrough');
- runWithKeyDown(function() { video.requestPictureInPicture(); });
+ runWithKeyDown(() => {
+ video.requestPictureInPicture();
+ });
+
waitForEventOnce('enterpictureinpicture', event => {
window.pipWindow = event.pictureInPictureWindow;
testExpected('pipWindow.width', 0, '>');
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-1-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-1-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-1-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,7 +1,7 @@
This tests that exit Picture-in-Picture resolves when there is a Picture-in-Picture video.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
-RUN(internals.setPictureInPictureAPITestEnabled(video, true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
RUN(video.src = "" "../content/test"))
EVENT(canplaythrough)
EVENT(enterpictureinpicture)
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-1.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-1.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-1.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5,15 +5,23 @@
<script src=""
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
- run('internals.setPictureInPictureAPITestEnabled(video, true)');
+ run('internals.setMockVideoPresentationModeEnabled(true)');
run('video.src = "" "../content/test")');
await waitFor(video, 'canplaythrough');
- runWithKeyDown(function() { video.requestPictureInPicture() });
+ runWithKeyDown(() => {
+ video.requestPictureInPicture();
+ });
+
await waitFor(video, 'enterpictureinpicture');
document.exitPictureInPicture().then(endTest).catch(() => {
failTest('Failed to exit the Picture-in-Picture mode.');
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-2-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-2-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-2-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,7 +1,7 @@
This tests that exit Picture-in-Picture rejects when there is no Picture-in-Picture video.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
-RUN(internals.setPictureInPictureAPITestEnabled(video, true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
EXPECTED (error.name == 'InvalidStateError') OK
END OF TEST
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-2.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-2.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-2.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5,10 +5,15 @@
<script src=""
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
- run('internals.setPictureInPictureAPITestEnabled(video, true)');
+ run('internals.setMockVideoPresentationModeEnabled(true)');
document.exitPictureInPicture()
.then(() => {
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-pip-window-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-pip-window-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-pip-window-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,7 +1,7 @@
This tests that a pip window is returned correctly when a video element enters the Picture-in-Picture mode.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
-RUN(internals.setPictureInPictureAPITestEnabled(video, true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
RUN(video.src = "" "../content/test"))
EVENT(canplaythrough)
EXPECTED (pipWindow.width > '0') OK
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-pip-window.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-pip-window.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-api-pip-window.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5,15 +5,20 @@
<script src=""
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
- run('internals.setPictureInPictureAPITestEnabled(video, true)');
+ run('internals.setMockVideoPresentationModeEnabled(true)');
run('video.src = "" "../content/test")');
await waitFor(video, 'canplaythrough');
- runWithKeyDown(function() {
+ runWithKeyDown(() => {
video.requestPictureInPicture()
.then(pipWindow => {
window.pipWindow = pipWindow;
@@ -28,7 +33,6 @@
failTest("Failed to enter the Picture-in-Picture mode.");
});
});
-
});
</script>
</head>
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-events-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-events-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-events-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,7 +1,7 @@
This tests that events are fired correctly when we use the webkit prefixed API to enters and exits the Picture-in-Picture mode.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
-RUN(internals.setPictureInPictureAPITestEnabled(video, true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
RUN(video.src = "" "../content/test"))
EVENT(canplaythrough)
EVENT(enterpictureinpicture)
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-events.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-events.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-events.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5,15 +5,23 @@
<script src=""
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
- run('internals.setPictureInPictureAPITestEnabled(video, true)');
+ run('internals.setMockVideoPresentationModeEnabled(true)');
run('video.src = "" "../content/test")');
await waitFor(video, 'canplaythrough');
- runWithKeyDown(function() { video.webkitSetPresentationMode('picture-in-picture'); });
+ runWithKeyDown(() => {
+ video.webkitSetPresentationMode('picture-in-picture');
+ });
+
waitForEventOnce('enterpictureinpicture', event => {
window.pipWindow = event.pictureInPictureWindow;
testExpected('pipWindow.width', 0, '>');
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-interruption-expected.txt (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-interruption-expected.txt 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-interruption-expected.txt 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,6 +1,7 @@
This tests that video is in the correct media session state after ending a background interruption while pipped.
RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
+RUN(internals.setMockVideoPresentationModeEnabled(true))
RUN(video.src = "" "../content/test"))
EVENT(canplaythrough)
RUN(video.play())
Modified: trunk/LayoutTests/media/picture-in-picture/picture-in-picture-interruption.html (262037 => 262038)
--- trunk/LayoutTests/media/picture-in-picture/picture-in-picture-interruption.html 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/LayoutTests/media/picture-in-picture/picture-in-picture-interruption.html 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5,9 +5,15 @@
<script src=""
<script>
window.addEventListener('load', async event => {
+ if (!window.internals) {
+ failTest('This test requires window.internals.');
+ return;
+ }
+
findMediaElement();
run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
+ run('internals.setMockVideoPresentationModeEnabled(true)');
run('video.src = "" "../content/test")');
await waitFor(video, 'canplaythrough');
@@ -15,7 +21,10 @@
run('video.play()');
await waitFor(video, 'playing');
- runWithKeyDown(function(){ video.webkitSetPresentationMode('picture-in-picture'); });
+ runWithKeyDown(() => {
+ video.webkitSetPresentationMode('picture-in-picture');
+ });
+
await waitFor(video, 'webkitpresentationmodechanged');
run('internals.beginMediaSessionInterruption("enteringbackground")');
Modified: trunk/Source/WebCore/ChangeLog (262037 => 262038)
--- trunk/Source/WebCore/ChangeLog 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/Source/WebCore/ChangeLog 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,3 +1,41 @@
+2020-05-21 Peng Liu <peng.l...@apple.com>
+
+ Fix issues of the Picture-in-Picture API under stress tests
+ https://bugs.webkit.org/show_bug.cgi?id=212191
+
+ Reviewed by Eric Carlson.
+
+ The current implementation of the Picture-in-Picture API is not robust under stress tests.
+ Changing the video presentation mode of a video element between inline and picture-in-picture
+ continuously may corrupt the internal states of the video element.
+
+ This patch refactors the approach to tracking the progress of video presentation mode changes
+ and make sure no new requestPictureInPicture() or exitPictureInPicture() will trigger
+ a presentation mode change unless the previous operations are completed.
+
+ This patch also removes the code for testing purposes in the HTMLVideoElement class.
+
+ Covered by existing tests.
+
+ * html/HTMLMediaElement.h:
+ * html/HTMLVideoElement.cpp:
+ (WebCore::toPresentationMode):
+ (WebCore::HTMLVideoElement::setFullscreenMode):
+ (WebCore::HTMLVideoElement::fullscreenModeChanged):
+ (WebCore::HTMLVideoElement::didEnterFullscreen):
+ (WebCore::HTMLVideoElement::didExitFullscreen):
+ (WebCore::HTMLVideoElement::setPictureInPictureObserver):
+ (WebCore::HTMLVideoElement::setVideoFullscreenFrame):
+ (WebCore::HTMLVideoElement::didBecomeFullscreenElement): Deleted.
+ (WebCore::HTMLVideoElement::setPictureInPictureAPITestEnabled): Deleted.
+ * html/HTMLVideoElement.h:
+
+ * testing/Internals.cpp:
+ (WebCore::Internals::setPictureInPictureAPITestEnabled): Deleted.
+ * testing/Internals.h:
+ * testing/Internals.idl:
+ Remove setPictureInPictureAPITestEnabled().
+
2020-05-21 Sam Weinig <wei...@apple.com>
Extended Color Cleanup: Remove trivial uses of Color::rgb()
Modified: trunk/Source/WebCore/html/HTMLMediaElement.h (262037 => 262038)
--- trunk/Source/WebCore/html/HTMLMediaElement.h 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/Source/WebCore/html/HTMLMediaElement.h 2020-05-22 00:20:29 UTC (rev 262038)
@@ -561,7 +561,7 @@
bool isSuspended() const final;
- WEBCORE_EXPORT void didBecomeFullscreenElement() override;
+ WEBCORE_EXPORT void didBecomeFullscreenElement() final;
WEBCORE_EXPORT void willExitFullscreen();
#if ENABLE(PICTURE_IN_PICTURE_API)
Modified: trunk/Source/WebCore/html/HTMLVideoElement.cpp (262037 => 262038)
--- trunk/Source/WebCore/html/HTMLVideoElement.cpp 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/Source/WebCore/html/HTMLVideoElement.cpp 2020-05-22 00:20:29 UTC (rev 262038)
@@ -442,6 +442,21 @@
return HTMLMediaElementEnums::VideoFullscreenModeNone;
}
+static inline HTMLVideoElement::VideoPresentationMode toPresentationMode(HTMLMediaElementEnums::VideoFullscreenMode mode)
+{
+ if (mode == HTMLMediaElementEnums::VideoFullscreenModeStandard)
+ return HTMLVideoElement::VideoPresentationMode::Fullscreen;
+
+ if (mode & HTMLMediaElementEnums::VideoFullscreenModePictureInPicture)
+ return HTMLVideoElement::VideoPresentationMode::PictureInPicture;
+
+ if (mode == HTMLMediaElementEnums::VideoFullscreenModeNone)
+ return HTMLVideoElement::VideoPresentationMode::Inline;
+
+ ASSERT_NOT_REACHED();
+ return HTMLVideoElement::VideoPresentationMode::Inline;
+}
+
void HTMLVideoElement::webkitSetPresentationMode(VideoPresentationMode mode)
{
INFO_LOG(LOGIDENTIFIER, ", mode = ", mode);
@@ -451,25 +466,13 @@
void HTMLVideoElement::setFullscreenMode(HTMLMediaElementEnums::VideoFullscreenMode mode)
{
INFO_LOG(LOGIDENTIFIER, ", mode = ", mode);
-#if ENABLE(PICTURE_IN_PICTURE_API)
- if (m_pictureInPictureAPITestEnabled) {
- if (mode == VideoFullscreenModePictureInPicture) {
- fullscreenModeChanged(mode);
- didBecomeFullscreenElement();
- setVideoFullscreenFrame({0, 0, 100, 100});
- return;
- }
- if (mode == VideoFullscreenModeNone) {
- fullscreenModeChanged(mode);
- return;
- }
- }
-#endif
-
if (mode == VideoFullscreenModeNone) {
- if (isFullscreen())
+ if (isFullscreen()) {
+ if (toPresentationMode(fullscreenMode()) == VideoPresentationMode::PictureInPicture)
+ m_isEnteringOrExitingPictureInPicture = true;
exitFullscreen();
+ }
return;
}
@@ -477,24 +480,12 @@
if (!mediaSession().fullscreenPermitted() || !supportsFullscreen(mode))
return;
+ if (mode == VideoFullscreenModePictureInPicture)
+ m_isEnteringOrExitingPictureInPicture = true;
+
enterFullscreen(mode);
}
-static HTMLVideoElement::VideoPresentationMode toPresentationMode(HTMLMediaElementEnums::VideoFullscreenMode mode)
-{
- if (mode == HTMLMediaElementEnums::VideoFullscreenModeStandard)
- return HTMLVideoElement::VideoPresentationMode::Fullscreen;
-
- if (mode & HTMLMediaElementEnums::VideoFullscreenModePictureInPicture)
- return HTMLVideoElement::VideoPresentationMode::PictureInPicture;
-
- if (mode == HTMLMediaElementEnums::VideoFullscreenModeNone)
- return HTMLVideoElement::VideoPresentationMode::Inline;
-
- ASSERT_NOT_REACHED();
- return HTMLVideoElement::VideoPresentationMode::Inline;
-}
-
auto HTMLVideoElement::webkitPresentationMode() const -> VideoPresentationMode
{
return toPresentationMode(fullscreenMode());
@@ -505,18 +496,6 @@
if (mode != fullscreenMode()) {
INFO_LOG(LOGIDENTIFIER, "changed from ", fullscreenMode(), ", to ", mode);
scheduleEvent(eventNames().webkitpresentationmodechangedEvent);
-
-#if ENABLE(PICTURE_IN_PICTURE_API)
- if (m_pictureInPictureObserver) {
- HTMLVideoElement::VideoPresentationMode targetVideoPresentationMode = toPresentationMode(mode);
- HTMLVideoElement::VideoPresentationMode sourceVideoPresentationMode = toPresentationMode(fullscreenMode());
-
- if (targetVideoPresentationMode != HTMLVideoElement::VideoPresentationMode::PictureInPicture && sourceVideoPresentationMode == HTMLVideoElement::VideoPresentationMode::PictureInPicture) {
- m_pictureInPictureObserver->didExitPictureInPicture();
- m_isFullscreen = false;
- }
- }
-#endif
}
if (player())
@@ -525,55 +504,55 @@
HTMLMediaElement::fullscreenModeChanged(mode);
}
-#if ENABLE(PICTURE_IN_PICTURE_API)
-void HTMLVideoElement::didBecomeFullscreenElement()
+void HTMLVideoElement::didEnterFullscreen()
{
- m_isFullscreen = true;
- m_waitingForPictureInPictureWindowFrame = true;
- HTMLMediaElement::didBecomeFullscreenElement();
+ if (m_isEnteringOrExitingPictureInPicture)
+ m_isWaitingForPictureInPictureWindowFrame = true;
}
-void HTMLVideoElement::setPictureInPictureObserver(PictureInPictureObserver* observer)
+void HTMLVideoElement::didExitFullscreen()
{
- m_pictureInPictureObserver = observer;
+ if (m_isEnteringOrExitingPictureInPicture) {
+ m_isEnteringOrExitingPictureInPicture = false;
+#if ENABLE(PICTURE_IN_PICTURE_API)
+ if (m_pictureInPictureObserver)
+ m_pictureInPictureObserver->didExitPictureInPicture();
+#endif
+ }
}
-void HTMLVideoElement::setPictureInPictureAPITestEnabled(bool enabled)
-{
- m_pictureInPictureAPITestEnabled = enabled;
-}
-#endif
-
-#endif
-
-#if ENABLE(VIDEO_PRESENTATION_MODE)
void HTMLVideoElement::setVideoFullscreenFrame(FloatRect frame)
{
HTMLMediaElement::setVideoFullscreenFrame(frame);
+ if (m_isWaitingForPictureInPictureWindowFrame) {
+ m_isWaitingForPictureInPictureWindowFrame = false;
+ m_isEnteringOrExitingPictureInPicture = false;
#if ENABLE(PICTURE_IN_PICTURE_API)
- // fullscreenMode() does not always provide the correct fullscreen mode
- // when mode changing is happening (webkit.org/b/203443)
- if (!m_isFullscreen)
+ if (m_pictureInPictureObserver)
+ m_pictureInPictureObserver->didEnterPictureInPicture(IntSize(frame.size()));
+#endif
return;
+ }
if (toPresentationMode(fullscreenMode()) != VideoPresentationMode::PictureInPicture)
return;
- if (m_waitingForPictureInPictureWindowFrame) {
- m_waitingForPictureInPictureWindowFrame = false;
- if (m_pictureInPictureObserver)
- m_pictureInPictureObserver->didEnterPictureInPicture(IntSize(frame.size()));
-
- return;
- }
-
- if (m_pictureInPictureObserver)
+#if ENABLE(PICTURE_IN_PICTURE_API)
+ if (!m_isEnteringOrExitingPictureInPicture && m_pictureInPictureObserver)
m_pictureInPictureObserver->pictureInPictureWindowResized(IntSize(frame.size()));
#endif
}
+
+#if ENABLE(PICTURE_IN_PICTURE_API)
+void HTMLVideoElement::setPictureInPictureObserver(PictureInPictureObserver* observer)
+{
+ m_pictureInPictureObserver = observer;
+}
#endif
+#endif // ENABLE(VIDEO_PRESENTATION_MODE)
+
#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
void HTMLVideoElement::exitToFullscreenModeWithoutAnimationIfPossible(HTMLMediaElementEnums::VideoFullscreenMode fromMode, HTMLMediaElementEnums::VideoFullscreenMode toMode)
{
Modified: trunk/Source/WebCore/html/HTMLVideoElement.h (262037 => 262038)
--- trunk/Source/WebCore/html/HTMLVideoElement.h 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/Source/WebCore/html/HTMLVideoElement.h 2020-05-22 00:20:29 UTC (rev 262038)
@@ -89,17 +89,15 @@
void setFullscreenMode(VideoFullscreenMode);
void fullscreenModeChanged(VideoFullscreenMode) final;
+ WEBCORE_EXPORT void didEnterFullscreen();
+ WEBCORE_EXPORT void didExitFullscreen();
+ void setVideoFullscreenFrame(FloatRect) final;
+
#if ENABLE(PICTURE_IN_PICTURE_API)
- WEBCORE_EXPORT void didBecomeFullscreenElement() final;
void setPictureInPictureObserver(PictureInPictureObserver*);
- WEBCORE_EXPORT void setPictureInPictureAPITestEnabled(bool);
#endif
#endif
-#if ENABLE(VIDEO_PRESENTATION_MODE)
- void setVideoFullscreenFrame(FloatRect) final;
-#endif
-
#if PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE)
void exitToFullscreenModeWithoutAnimationIfPossible(HTMLMediaElementEnums::VideoFullscreenMode fromMode, HTMLMediaElementEnums::VideoFullscreenMode toMode);
#endif
@@ -136,12 +134,10 @@
unsigned m_lastReportedVideoWidth { 0 };
unsigned m_lastReportedVideoHeight { 0 };
+ bool m_isEnteringOrExitingPictureInPicture { false };
+ bool m_isWaitingForPictureInPictureWindowFrame { false };
#if ENABLE(PICTURE_IN_PICTURE_API)
- bool m_waitingForPictureInPictureWindowFrame { false };
- bool m_isFullscreen { false };
PictureInPictureObserver* m_pictureInPictureObserver { nullptr };
-
- bool m_pictureInPictureAPITestEnabled { false };
#endif
};
Modified: trunk/Source/WebCore/testing/Internals.cpp (262037 => 262038)
--- trunk/Source/WebCore/testing/Internals.cpp 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/Source/WebCore/testing/Internals.cpp 2020-05-22 00:20:29 UTC (rev 262038)
@@ -5604,13 +5604,6 @@
}
#endif
-#if ENABLE(PICTURE_IN_PICTURE_API)
-void Internals::setPictureInPictureAPITestEnabled(HTMLVideoElement& videoElement, bool enabled)
-{
- videoElement.setPictureInPictureAPITestEnabled(enabled);
-}
-#endif
-
void Internals::setMaxCanvasPixelMemory(unsigned size)
{
HTMLCanvasElement::setMaxPixelMemoryForTesting(size);
Modified: trunk/Source/WebCore/testing/Internals.h (262037 => 262038)
--- trunk/Source/WebCore/testing/Internals.h 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/Source/WebCore/testing/Internals.h 2020-05-22 00:20:29 UTC (rev 262038)
@@ -987,10 +987,6 @@
void setMockWebAuthenticationConfiguration(const MockWebAuthenticationConfiguration&);
#endif
-#if ENABLE(PICTURE_IN_PICTURE_API)
- void setPictureInPictureAPITestEnabled(HTMLVideoElement&, bool);
-#endif
-
int processIdentifier() const;
Ref<InternalsSetLike> createInternalsSetLike();
Modified: trunk/Source/WebCore/testing/Internals.idl (262037 => 262038)
--- trunk/Source/WebCore/testing/Internals.idl 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/Source/WebCore/testing/Internals.idl 2020-05-22 00:20:29 UTC (rev 262038)
@@ -886,8 +886,6 @@
[Conditional=WEB_AUTHN] void setMockWebAuthenticationConfiguration(MockWebAuthenticationConfiguration configuration);
- [Conditional=PICTURE_IN_PICTURE_API] void setPictureInPictureAPITestEnabled(HTMLVideoElement videoElement, boolean enabled);
-
InternalsMapLike createInternalsMapLike();
InternalsSetLike createInternalsSetLike();
Modified: trunk/Source/WebKit/ChangeLog (262037 => 262038)
--- trunk/Source/WebKit/ChangeLog 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/Source/WebKit/ChangeLog 2020-05-22 00:20:29 UTC (rev 262038)
@@ -1,3 +1,20 @@
+2020-05-21 Peng Liu <peng.l...@apple.com>
+
+ Fix issues of the Picture-in-Picture API under stress tests
+ https://bugs.webkit.org/show_bug.cgi?id=212191
+
+ Reviewed by Eric Carlson.
+
+ * UIProcess/Cocoa/VideoFullscreenManagerProxy.mm:
+ (WebKit::VideoFullscreenManagerProxy::enterFullscreen):
+ Mock the behavior of the VideoFullscreenInterface[AVKit|Mac] regarding
+ the Picture-in-Picture mode support.
+
+ * WebProcess/cocoa/VideoFullscreenManager.mm:
+ (WebKit::VideoFullscreenManager::didEnterFullscreen):
+ (WebKit::VideoFullscreenManager::didCleanupFullscreen):
+ Add callbacks for the end of entering/exiting fullscreen.
+
2020-05-21 Tyler Wilcock <twilc...@protonmail.com>
Fix misspelling -- m_releaseNetwrokActivityTimer --> m_releaseNetworkActivityTimer
Modified: trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm (262037 => 262038)
--- trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/Source/WebKit/UIProcess/Cocoa/VideoFullscreenManagerProxy.mm 2020-05-22 00:20:29 UTC (rev 262038)
@@ -554,6 +554,7 @@
MESSAGE_CHECK_CONTEXTID(contextId);
if (m_mockVideoPresentationModeEnabled) {
didEnterFullscreen(contextId);
+ setVideoLayerFrame(contextId, {0, 0, 200, 150});
return;
}
Modified: trunk/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm (262037 => 262038)
--- trunk/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm 2020-05-22 00:13:11 UTC (rev 262037)
+++ trunk/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm 2020-05-22 00:20:29 UTC (rev 262038)
@@ -441,6 +441,8 @@
if (!videoElement)
return;
+ videoElement->didEnterFullscreen();
+
dispatch_async(dispatch_get_main_queue(), [protectedThis = makeRefPtr(this), videoElement] {
videoElement->didBecomeFullscreenElement();
});
@@ -505,6 +507,8 @@
model->setVideoFullscreenLayer(nil);
RefPtr<HTMLVideoElement> videoElement = model->videoElement();
+ if (videoElement)
+ videoElement->didExitFullscreen();
interface->setFullscreenMode(HTMLMediaElementEnums::VideoFullscreenModeNone);
interface->setFullscreenStandby(false);