Entering/Exiting Picture-in-Picture mode through webkitSetPresentationMode() does...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Nov 2019 00:39:29 +0000 (00:39 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 9 Nov 2019 00:39:29 +0000 (00:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=203989

Patch by Peng Liu <peng.liu6@apple.com> on 2019-11-08
Reviewed by Eric Carlson.

Source/WebCore:

Instantiate a HTMLVideoElementPictureInPicture object when we create a new video element
so that the events defined in the spec will be fired no matter which interface is used
to enter/exit the Picture-in-Picture mode.

Test: media/picture-in-picture/picture-in-picture-events.html

* Modules/pictureinpicture/HTMLVideoElementPictureInPicture.cpp:
(WebCore::HTMLVideoElementPictureInPicture::providePictureInPictureTo):
* Modules/pictureinpicture/HTMLVideoElementPictureInPicture.h:
* WebCore.xcodeproj/project.pbxproj:
* html/HTMLVideoElement.cpp:
(WebCore::HTMLVideoElement::create):

LayoutTests:

Move all layout tests for Picture-in-Picture to folder media/picture-in-picture.
Add a layout test to verify the events defined in the spec are fired when we call the webkit prefixed API.
Update TestExpectations files since webkit.org/b/203614 has been fixed.

* TestExpectations:
* media/picture-in-picture/picture-in-picture-api-element-attributes-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-element-attributes-expected.txt.
* media/picture-in-picture/picture-in-picture-api-element-attributes.html: Renamed from LayoutTests/media/picture-in-picture-api-element-attributes.html.
* media/picture-in-picture/picture-in-picture-api-enter-pip-1-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-1-expected.txt.
* media/picture-in-picture/picture-in-picture-api-enter-pip-1.html: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-1.html.
* media/picture-in-picture/picture-in-picture-api-enter-pip-2-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-2-expected.txt.
* media/picture-in-picture/picture-in-picture-api-enter-pip-2.html: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-2.html.
* media/picture-in-picture/picture-in-picture-api-enter-pip-3-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-3-expected.txt.
* media/picture-in-picture/picture-in-picture-api-enter-pip-3.html: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-3.html.
* media/picture-in-picture/picture-in-picture-api-enter-pip-4-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-4-expected.txt.
* media/picture-in-picture/picture-in-picture-api-enter-pip-4.html: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-4.html.
* media/picture-in-picture/picture-in-picture-api-events-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-pip-events-expected.txt.
* media/picture-in-picture/picture-in-picture-api-events.html: Renamed from LayoutTests/media/picture-in-picture-api-pip-events.html.
* media/picture-in-picture/picture-in-picture-api-exit-pip-1-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-exit-pip-1-expected.txt.
* media/picture-in-picture/picture-in-picture-api-exit-pip-1.html: Renamed from LayoutTests/media/picture-in-picture-api-exit-pip-1.html.
* media/picture-in-picture/picture-in-picture-api-exit-pip-2-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-exit-pip-2-expected.txt.
* media/picture-in-picture/picture-in-picture-api-exit-pip-2.html: Renamed from LayoutTests/media/picture-in-picture-api-exit-pip-2.html.
* media/picture-in-picture/picture-in-picture-api-pip-window-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-pip-window-expected.txt.
* media/picture-in-picture/picture-in-picture-api-pip-window.html: Renamed from LayoutTests/media/picture-in-picture-api-pip-window.html.
* media/picture-in-picture/picture-in-picture-events-expected.txt: Added.
* media/picture-in-picture/picture-in-picture-events.html: Added.
* media/picture-in-picture/picture-in-picture-interruption-expected.txt: Renamed from LayoutTests/media/picture-in-picture-interruption-expected.txt.
* media/picture-in-picture/picture-in-picture-interruption.html: Renamed from LayoutTests/media/picture-in-picture-interruption.html.
* platform/gtk/TestExpectations:
* platform/ios/TestExpectations:
* platform/ipad/TestExpectations:
* platform/mac-wk2/TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@252276 268f45cc-cd09-0410-ab3c-d52691b4dbfc

33 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/media/picture-in-picture/picture-in-picture-api-element-attributes-expected.txt [moved from LayoutTests/media/picture-in-picture-api-element-attributes-expected.txt with 100% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-element-attributes.html [moved from LayoutTests/media/picture-in-picture-api-element-attributes.html with 93% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-1-expected.txt [moved from LayoutTests/media/picture-in-picture-api-enter-pip-1-expected.txt with 82% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-1.html [moved from LayoutTests/media/picture-in-picture-api-enter-pip-1.html with 83% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-2-expected.txt [moved from LayoutTests/media/picture-in-picture-api-enter-pip-2-expected.txt with 100% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-2.html [moved from LayoutTests/media/picture-in-picture-api-enter-pip-2.html with 91% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-3-expected.txt [moved from LayoutTests/media/picture-in-picture-api-enter-pip-3-expected.txt with 83% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-3.html [moved from LayoutTests/media/picture-in-picture-api-enter-pip-3.html with 85% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-4-expected.txt [moved from LayoutTests/media/picture-in-picture-api-enter-pip-4-expected.txt with 79% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-enter-pip-4.html [moved from LayoutTests/media/picture-in-picture-api-enter-pip-4.html with 85% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-events-expected.txt [moved from LayoutTests/media/picture-in-picture-api-pip-events-expected.txt with 71% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-events.html [moved from LayoutTests/media/picture-in-picture-api-pip-events.html with 54% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-1-expected.txt [moved from LayoutTests/media/picture-in-picture-api-exit-pip-1-expected.txt with 82% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-1.html [moved from LayoutTests/media/picture-in-picture-api-exit-pip-1.html with 83% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-2-expected.txt [moved from LayoutTests/media/picture-in-picture-api-exit-pip-2-expected.txt with 100% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-exit-pip-2.html [moved from LayoutTests/media/picture-in-picture-api-exit-pip-2.html with 90% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-pip-window-expected.txt [moved from LayoutTests/media/picture-in-picture-api-pip-window-expected.txt with 85% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-api-pip-window.html [moved from LayoutTests/media/picture-in-picture-api-pip-window.html with 88% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-events-expected.txt [new file with mode: 0644]
LayoutTests/media/picture-in-picture/picture-in-picture-events.html [new file with mode: 0644]
LayoutTests/media/picture-in-picture/picture-in-picture-interruption-expected.txt [moved from LayoutTests/media/picture-in-picture-interruption-expected.txt with 90% similarity]
LayoutTests/media/picture-in-picture/picture-in-picture-interruption.html [moved from LayoutTests/media/picture-in-picture-interruption.html with 86% similarity]
LayoutTests/platform/gtk/TestExpectations
LayoutTests/platform/ios/TestExpectations
LayoutTests/platform/ipad/TestExpectations
LayoutTests/platform/mac-wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/Modules/pictureinpicture/HTMLVideoElementPictureInPicture.cpp
Source/WebCore/Modules/pictureinpicture/HTMLVideoElementPictureInPicture.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/html/HTMLVideoElement.cpp

index 1838510..2e29081 100644 (file)
@@ -1,3 +1,42 @@
+2019-11-08  Peng Liu  <peng.liu6@apple.com>
+
+        Entering/Exiting Picture-in-Picture mode through webkitSetPresentationMode() does not fire events (enterpictureinpicture and leavepictureinpicture) defined in the spec
+        https://bugs.webkit.org/show_bug.cgi?id=203989
+
+        Reviewed by Eric Carlson.
+
+        Move all layout tests for Picture-in-Picture to folder media/picture-in-picture.
+        Add a layout test to verify the events defined in the spec are fired when we call the webkit prefixed API.
+        Update TestExpectations files since webkit.org/b/203614 has been fixed.
+
+        * TestExpectations:
+        * media/picture-in-picture/picture-in-picture-api-element-attributes-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-element-attributes-expected.txt.
+        * media/picture-in-picture/picture-in-picture-api-element-attributes.html: Renamed from LayoutTests/media/picture-in-picture-api-element-attributes.html.
+        * media/picture-in-picture/picture-in-picture-api-enter-pip-1-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-1-expected.txt.
+        * media/picture-in-picture/picture-in-picture-api-enter-pip-1.html: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-1.html.
+        * media/picture-in-picture/picture-in-picture-api-enter-pip-2-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-2-expected.txt.
+        * media/picture-in-picture/picture-in-picture-api-enter-pip-2.html: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-2.html.
+        * media/picture-in-picture/picture-in-picture-api-enter-pip-3-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-3-expected.txt.
+        * media/picture-in-picture/picture-in-picture-api-enter-pip-3.html: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-3.html.
+        * media/picture-in-picture/picture-in-picture-api-enter-pip-4-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-4-expected.txt.
+        * media/picture-in-picture/picture-in-picture-api-enter-pip-4.html: Renamed from LayoutTests/media/picture-in-picture-api-enter-pip-4.html.
+        * media/picture-in-picture/picture-in-picture-api-events-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-pip-events-expected.txt.
+        * media/picture-in-picture/picture-in-picture-api-events.html: Renamed from LayoutTests/media/picture-in-picture-api-pip-events.html.
+        * media/picture-in-picture/picture-in-picture-api-exit-pip-1-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-exit-pip-1-expected.txt.
+        * media/picture-in-picture/picture-in-picture-api-exit-pip-1.html: Renamed from LayoutTests/media/picture-in-picture-api-exit-pip-1.html.
+        * media/picture-in-picture/picture-in-picture-api-exit-pip-2-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-exit-pip-2-expected.txt.
+        * media/picture-in-picture/picture-in-picture-api-exit-pip-2.html: Renamed from LayoutTests/media/picture-in-picture-api-exit-pip-2.html.
+        * media/picture-in-picture/picture-in-picture-api-pip-window-expected.txt: Renamed from LayoutTests/media/picture-in-picture-api-pip-window-expected.txt.
+        * media/picture-in-picture/picture-in-picture-api-pip-window.html: Renamed from LayoutTests/media/picture-in-picture-api-pip-window.html.
+        * media/picture-in-picture/picture-in-picture-events-expected.txt: Added.
+        * media/picture-in-picture/picture-in-picture-events.html: Added.
+        * media/picture-in-picture/picture-in-picture-interruption-expected.txt: Renamed from LayoutTests/media/picture-in-picture-interruption-expected.txt.
+        * media/picture-in-picture/picture-in-picture-interruption.html: Renamed from LayoutTests/media/picture-in-picture-interruption.html.
+        * platform/gtk/TestExpectations:
+        * platform/ios/TestExpectations:
+        * platform/ipad/TestExpectations:
+        * platform/mac-wk2/TestExpectations:
+
 2019-11-08  Chris Dumez  <cdumez@apple.com>
 
         Make DeferredPromise behave nicely with regards to the back/forward cache
index cadc06b..6644a41 100644 (file)
@@ -197,15 +197,7 @@ fast/events/do-not-drag-and-drop-data-detectors-link.html [ Skip ]
 webkit.org/b/202617 imported/w3c/web-platform-tests/picture-in-picture [ Skip ]
 
 # PiP API tests are only relevant on mac and iPad
-media/picture-in-picture-api-element-attributes.html [ Skip ]
-media/picture-in-picture-api-enter-pip-1.html [ Skip ]
-media/picture-in-picture-api-enter-pip-2.html [ Skip ]
-media/picture-in-picture-api-enter-pip-3.html [ Skip ]
-media/picture-in-picture-api-enter-pip-4.html [ Skip ]
-media/picture-in-picture-api-exit-pip-1.html [ Skip ]
-media/picture-in-picture-api-exit-pip-2.html [ Skip ]
-media/picture-in-picture-api-pip-events.html [ Skip ]
-media/picture-in-picture-api-pip-window.html [ Skip ]
+media/picture-in-picture [ Skip ]
 
 # Shared Workers are unsupported
 imported/w3c/web-platform-tests/secure-contexts/basic-shared-worker.html [ Skip ]
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script src="video-test.js"></script>
-    <script src="media-file.js"></script>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
     <script>
         window.addEventListener('load', async event => {
             findMediaElement();
@@ -2,7 +2,7 @@ This tests that request Picture-in-Picture requires a user gesture.
 
 RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
 RUN(internals.setPictureInPictureAPITestEnabled(video, true))
-RUN(video.src = findMediaFile("video", "content/test"))
+RUN(video.src = findMediaFile("video", "../content/test"))
 EVENT(canplaythrough)
 EXPECTED (error.name == 'NotAllowedError') OK
 END OF TEST
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script src="video-test.js"></script>
-    <script src="media-file.js"></script>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
     <script>
         window.addEventListener('load', async event => {
             findMediaElement();
 
             run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
             run('internals.setPictureInPictureAPITestEnabled(video, true)');
-            run('video.src = findMediaFile("video", "content/test")');
+            run('video.src = findMediaFile("video", "../content/test")');
             await waitFor(video, 'canplaythrough');
 
             video.requestPictureInPicture()
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script src="video-test.js"></script>
-    <script src="media-file.js"></script>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
     <script>
         window.addEventListener('load', async event => {
             findMediaElement();
@@ -2,7 +2,7 @@ This tests that request Picture-in-Picture requires video track for the video el
 
 RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
 RUN(internals.setPictureInPictureAPITestEnabled(video, true))
-RUN(video.src = findMediaFile("audio", "content/test"))
+RUN(video.src = findMediaFile("audio", "../content/test"))
 EVENT(canplaythrough)
 EXPECTED (error.name == 'InvalidStateError') OK
 END OF TEST
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script src="video-test.js"></script>
-    <script src="media-file.js"></script>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
     <script>
         window.addEventListener('load', async event => {
             findMediaElement();
 
             run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
             run('internals.setPictureInPictureAPITestEnabled(video, true)');
-            run('video.src = findMediaFile("audio", "content/test")');
+            run('video.src = findMediaFile("audio", "../content/test")');
             await waitFor(video, 'canplaythrough');
             runWithKeyDown(function() {
                 video.requestPictureInPicture()
@@ -2,7 +2,7 @@ This tests that request Picture-in-Picture resolves on user click.
 
 RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
 RUN(internals.setPictureInPictureAPITestEnabled(video, true))
-RUN(video.src = findMediaFile("video", "content/test"))
+RUN(video.src = findMediaFile("video", "../content/test"))
 EVENT(canplaythrough)
 END OF TEST
 
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script src="video-test.js"></script>
-    <script src="media-file.js"></script>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
     <script>
         window.addEventListener('load', async event => {
             findMediaElement();
@@ -10,7 +10,7 @@
             run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
             run('internals.setPictureInPictureAPITestEnabled(video, true)');
 
-            run('video.src = findMediaFile("video", "content/test")');
+            run('video.src = findMediaFile("video", "../content/test")');
             await waitFor(video, 'canplaythrough');
             runWithKeyDown(function() {
                 video.requestPictureInPicture()
@@ -2,9 +2,11 @@ This tests that events are fired correctly when a video element enters and exits
 
 RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
 RUN(internals.setPictureInPictureAPITestEnabled(video, true))
-RUN(video.src = findMediaFile("video", "content/test"))
+RUN(video.src = findMediaFile("video", "../content/test"))
 EVENT(canplaythrough)
 EVENT(enterpictureinpicture)
+EXPECTED (pipWindow.width > '0') OK
+EXPECTED (pipWindow.height > '0') OK
 EVENT(leavepictureinpicture)
 END OF TEST
 
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script src="video-test.js"></script>
-    <script src="media-file.js"></script>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
     <script>
         window.addEventListener('load', async event => {
             findMediaElement();
             run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
             run('internals.setPictureInPictureAPITestEnabled(video, true)');
 
-            run('video.src = findMediaFile("video", "content/test")');
+            run('video.src = findMediaFile("video", "../content/test")');
             await waitFor(video, 'canplaythrough');
 
             runWithKeyDown(function() { video.requestPictureInPicture(); });
-            await waitFor(video, 'enterpictureinpicture');
-            document.exitPictureInPicture();
-            await waitFor(video, 'leavepictureinpicture');
+            waitForEventOnce('enterpictureinpicture', event => {
+                window.pipWindow = event.pictureInPictureWindow;
+                testExpected('pipWindow.width', 0, '>');
+                testExpected('pipWindow.height', 0, '>');
 
-            endTest();
+                document.exitPictureInPicture();
+                waitForEventAndEnd('leavepictureinpicture');
+            });
         });
     </script>
 </head>
@@ -2,7 +2,7 @@ This tests that exit Picture-in-Picture resolves when there is a Picture-in-Pict
 
 RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
 RUN(internals.setPictureInPictureAPITestEnabled(video, true))
-RUN(video.src = findMediaFile("video", "content/test"))
+RUN(video.src = findMediaFile("video", "../content/test"))
 EVENT(canplaythrough)
 EVENT(enterpictureinpicture)
 END OF TEST
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script src="video-test.js"></script>
-    <script src="media-file.js"></script>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
     <script>
         window.addEventListener('load', async event => {
             findMediaElement();
@@ -10,7 +10,7 @@
             run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
             run('internals.setPictureInPictureAPITestEnabled(video, true)');
 
-            run('video.src = findMediaFile("video", "content/test")');
+            run('video.src = findMediaFile("video", "../content/test")');
             await waitFor(video, 'canplaythrough');
 
             runWithKeyDown(function() { video.requestPictureInPicture() });
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script src="video-test.js"></script>
-    <script src="media-file.js"></script>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
     <script>
         window.addEventListener('load', async event => {
             findMediaElement();
@@ -2,7 +2,7 @@ This tests that a pip window is returned correctly when a video element enters t
 
 RUN(internals.settings.setAllowsPictureInPictureMediaPlayback(true))
 RUN(internals.setPictureInPictureAPITestEnabled(video, true))
-RUN(video.src = findMediaFile("video", "content/test"))
+RUN(video.src = findMediaFile("video", "../content/test"))
 EVENT(canplaythrough)
 EXPECTED (pipWindow.width > '0') OK
 EXPECTED (pipWindow.height > '0') OK
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script src="video-test.js"></script>
-    <script src="media-file.js"></script>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
     <script>
         window.addEventListener('load', async event => {
             findMediaElement();
@@ -10,7 +10,7 @@
             run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
             run('internals.setPictureInPictureAPITestEnabled(video, true)');
 
-            run('video.src = findMediaFile("video", "content/test")');
+            run('video.src = findMediaFile("video", "../content/test")');
             await waitFor(video, 'canplaythrough');
 
             runWithKeyDown(function() {
diff --git a/LayoutTests/media/picture-in-picture/picture-in-picture-events-expected.txt b/LayoutTests/media/picture-in-picture/picture-in-picture-events-expected.txt
new file mode 100644 (file)
index 0000000..be2ea40
--- /dev/null
@@ -0,0 +1,12 @@
+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(video.src = findMediaFile("video", "../content/test"))
+EVENT(canplaythrough)
+EVENT(enterpictureinpicture)
+EXPECTED (pipWindow.width > '0') OK
+EXPECTED (pipWindow.height > '0') OK
+EVENT(leavepictureinpicture)
+END OF TEST
+
diff --git a/LayoutTests/media/picture-in-picture/picture-in-picture-events.html b/LayoutTests/media/picture-in-picture/picture-in-picture-events.html
new file mode 100644 (file)
index 0000000..0ea0911
--- /dev/null
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
+    <script>
+        window.addEventListener('load', async event => {
+            findMediaElement();
+
+            run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
+            run('internals.setPictureInPictureAPITestEnabled(video, true)');
+
+            run('video.src = findMediaFile("video", "../content/test")');
+            await waitFor(video, 'canplaythrough');
+
+            runWithKeyDown(function() { video.webkitSetPresentationMode('picture-in-picture'); });
+            waitForEventOnce('enterpictureinpicture', event => {
+                window.pipWindow = event.pictureInPictureWindow;
+                testExpected('pipWindow.width', 0, '>');
+                testExpected('pipWindow.height', 0, '>');
+
+                video.webkitSetPresentationMode('inline');
+                waitForEventAndEnd('leavepictureinpicture');
+            });
+        });
+    </script>
+</head>
+<body>
+    <div>This tests that events are fired correctly when we use the webkit prefixed API to enters and exits the Picture-in-Picture mode.</div>
+    <video controls></video>
+</body>
+</html>
@@ -1,7 +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(video.src = findMediaFile("video", "content/test"))
+RUN(video.src = findMediaFile("video", "../content/test"))
 EVENT(canplaythrough)
 RUN(video.play())
 EVENT(playing)
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <script src="video-test.js"></script>
-    <script src="media-file.js"></script>
+    <script src="../video-test.js"></script>
+    <script src="../media-file.js"></script>
     <script>
         window.addEventListener('load', async event => {
             findMediaElement();
 
             run('internals.settings.setAllowsPictureInPictureMediaPlayback(true)');
 
-            run('video.src = findMediaFile("video", "content/test")');
+            run('video.src = findMediaFile("video", "../content/test")');
             await waitFor(video, 'canplaythrough');
 
             run('video.play()');
index d2287a1..f189cea 100644 (file)
@@ -2478,7 +2478,7 @@ webkit.org/b/186252 legacy-animation-engine/css3/filters/backdrop/animation.html
 
 webkit.org/b/187266 imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/track/track-element/track-api-texttracks.html [ Pass Timeout ]
 
-webkit.org/b/187273 media/picture-in-picture-interruption.html [ Timeout ]
+webkit.org/b/187273 media/picture-in-picture/picture-in-picture-interruption.html [ Timeout ]
 
 webkit.org/b/188103 imported/w3c/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-1.html [ Failure Pass ]
 webkit.org/b/188103 imported/w3c/web-platform-tests/mathml/presentation-markup/fractions/frac-parameters-2.html [ Failure Pass ]
index 82ddad6..b28fcef 100644 (file)
@@ -991,7 +991,7 @@ http/tests/resourceLoadStatistics/prevalent-resource-handled-keydown.html [ Skip
 http/tests/resourceLoadStatistics/prevalent-resource-handled-keydown-database.html [ Skip ]
 media/audio-playback-volume-changes-with-restrictions-and-user-gestures.html [ Skip ]
 media/audio-playback-volume-changes-with-restrictions.html [ Skip ]
-media/picture-in-picture-interruption.html [ Skip ]
+media/picture-in-picture/picture-in-picture-interruption.html [ Skip ]
 scrollbars/scrolling-backward-by-page-accounting-bottom-fixed-elements-on-keyboard-spacebar.html [ Skip ]
 scrollbars/scrolling-backward-by-page-on-keyboard-spacebar.html [ Skip ]
 scrollbars/scrolling-by-page-accounting-oversized-fixed-elements-on-keyboard-spacebar.html [ Skip ]
index e33e3ed..a985170 100644 (file)
@@ -67,12 +67,4 @@ webkit.org/b/203264 editing/pasteboard/smart-paste-paragraph-001.html [ Pass ]
 webkit.org/b/203264 editing/pasteboard/smart-paste-paragraph-002.html [ Pass ]
 webkit.org/b/203264 editing/pasteboard/smart-paste-paragraph-004.html [ Pass ]
 
-media/picture-in-picture-api-element-attributes.html [ Pass ]
-media/picture-in-picture-api-enter-pip-1.html [ Pass ]
-media/picture-in-picture-api-enter-pip-2.html [ Pass ]
-media/picture-in-picture-api-enter-pip-3.html [ Pass ]
-webkit.org/b/203614 media/picture-in-picture-api-enter-pip-4.html [ Pass Timeout ]
-webkit.org/b/203614 media/picture-in-picture-api-exit-pip-1.html [ Pass Timeout ]
-media/picture-in-picture-api-exit-pip-2.html [ Pass ]
-webkit.org/b/203614 media/picture-in-picture-api-pip-events.html [ Pass Timeout ]
-webkit.org/b/203614 media/picture-in-picture-api-pip-window.html [ Pass Timeout ]
\ No newline at end of file
+media/picture-in-picture [ Pass ]
\ No newline at end of file
index 86ca787..181ef92 100644 (file)
@@ -541,15 +541,7 @@ webkit.org/b/170620 [ Sierra+ ] media/controls/pip-placeholder-without-video-con
 webkit.org/b/172998 [ Sierra+ ] media/fullscreen-api-enabled-media-with-presentation-mode.html [ Failure ]
 webkit.org/b/173199 [ Sierra+ ] media/navigate-with-pip-should-not-crash.html [ Pass Failure ]
 [ Sierra+ ] media/pip-video-going-into-fullscreen.html [ Pass ]
-[ Sierra+ ] media/picture-in-picture-api-element-attributes.html [ Pass ]
-[ Sierra+ ] media/picture-in-picture-api-enter-pip-1.html [ Pass ]
-[ Sierra+ ] media/picture-in-picture-api-enter-pip-2.html [ Pass ]
-[ Sierra+ ] media/picture-in-picture-api-enter-pip-3.html [ Pass ]
-webkit.org/b/203614 [ Sierra+ ] media/picture-in-picture-api-enter-pip-4.html [ Pass Timeout ]
-webkit.org/b/203614 [ Sierra+ ] media/picture-in-picture-api-exit-pip-1.html [ Pass Timeout ]
-[ Sierra+ ] media/picture-in-picture-api-exit-pip-2.html [ Pass ]
-webkit.org/b/203614 [ Sierra+ ] media/picture-in-picture-api-pip-events.html [ Pass Timeout ]
-webkit.org/b/203614 [ Sierra+ ] media/picture-in-picture-api-pip-window.html [ Pass Timeout ]
+[ Sierra+ ] media/picture-in-picture [ Pass ]
 
 # RTL Scrollbars are enabled on Sierra WebKit2.
 webkit.org/b/179455 [ Sierra+ ] fast/scrolling/rtl-scrollbars.html [ Pass ImageOnlyFailure ]
index 1a4252f..9f6fbb3 100644 (file)
@@ -1,3 +1,23 @@
+2019-11-08  Peng Liu  <peng.liu6@apple.com>
+
+        Entering/Exiting Picture-in-Picture mode through webkitSetPresentationMode() does not fire events (enterpictureinpicture and leavepictureinpicture) defined in the spec
+        https://bugs.webkit.org/show_bug.cgi?id=203989
+
+        Reviewed by Eric Carlson.
+
+        Instantiate a HTMLVideoElementPictureInPicture object when we create a new video element
+        so that the events defined in the spec will be fired no matter which interface is used
+        to enter/exit the Picture-in-Picture mode.
+
+        Test: media/picture-in-picture/picture-in-picture-events.html
+
+        * Modules/pictureinpicture/HTMLVideoElementPictureInPicture.cpp:
+        (WebCore::HTMLVideoElementPictureInPicture::providePictureInPictureTo):
+        * Modules/pictureinpicture/HTMLVideoElementPictureInPicture.h:
+        * WebCore.xcodeproj/project.pbxproj:
+        * html/HTMLVideoElement.cpp:
+        (WebCore::HTMLVideoElement::create):
+
 2019-11-08  Chris Dumez  <cdumez@apple.com>
 
         Make DeferredPromise behave nicely with regards to the back/forward cache
index 1b37df7..7b24df5 100644 (file)
@@ -71,6 +71,11 @@ HTMLVideoElementPictureInPicture* HTMLVideoElementPictureInPicture::from(HTMLVid
     return supplement;
 }
 
+void HTMLVideoElementPictureInPicture::providePictureInPictureTo(HTMLVideoElement& videoElement)
+{
+    provideTo(&videoElement, supplementName(), makeUnique<HTMLVideoElementPictureInPicture>(videoElement));
+}
+
 void HTMLVideoElementPictureInPicture::requestPictureInPicture(HTMLVideoElement& videoElement, Ref<DeferredPromise>&& promise)
 {
     if (!supportsPictureInPicture()) {
index e4f0624..69fbb2d 100644 (file)
@@ -50,6 +50,7 @@ class HTMLVideoElementPictureInPicture
 public:
     HTMLVideoElementPictureInPicture(HTMLVideoElement&);
     static HTMLVideoElementPictureInPicture* from(HTMLVideoElement&);
+    static void providePictureInPictureTo(HTMLVideoElement&);
     virtual ~HTMLVideoElementPictureInPicture();
 
     static void requestPictureInPicture(HTMLVideoElement&, Ref<DeferredPromise>&&);
index 2ce5a97..afadee5 100644 (file)
                1CCD81502231F83E0065FC2B /* WebCoreResourceHandleAsOperationQueueDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E152551416FD234F003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.mm */; };
                1CCDF5BE1990332400BCEBAD /* SVGToOTFFontConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CCDF5BC1990332400BCEBAD /* SVGToOTFFontConversion.h */; };
                1CFAE3230A6D6A3F0032593D /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CFAE3220A6D6A3F0032593D /* libobjc.dylib */; };
+               1D0026A42374D62400CA6CDF /* JSPictureInPictureWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D0026A22374D62300CA6CDF /* JSPictureInPictureWindow.h */; };
+               1D0026AA2374F9EA00CA6CDF /* JSEnterPictureInPictureEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D0026A82374F9D900CA6CDF /* JSEnterPictureInPictureEvent.h */; };
                1D2C82B7236A3F6A0055D6C5 /* PictureInPictureSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 1D2C82B6236A3F6A0055D6C5 /* PictureInPictureSupport.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1D2F8E03234474EF00993B68 /* DocumentPictureInPicture.h in Headers */ = {isa = PBXBuildFile; fileRef = 1DEF06DD233D2E1C00EE228D /* DocumentPictureInPicture.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1D2F8E042344751600993B68 /* EnterPictureInPictureEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 1DEF06CA233C3D0B00EE228D /* EnterPictureInPictureEvent.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1CECB3C721F59C8700F44542 /* WHLSLNativeTypeWriter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLNativeTypeWriter.h; sourceTree = "<group>"; };
                1CF0BFD42298706800ED2074 /* TextSizeAdjustment.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TextSizeAdjustment.cpp; sourceTree = "<group>"; };
                1CFAE3220A6D6A3F0032593D /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = /usr/lib/libobjc.dylib; sourceTree = "<absolute>"; };
+               1D0026A22374D62300CA6CDF /* JSPictureInPictureWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPictureInPictureWindow.h; sourceTree = "<group>"; };
+               1D0026A32374D62400CA6CDF /* JSPictureInPictureWindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPictureInPictureWindow.cpp; sourceTree = "<group>"; };
+               1D0026A82374F9D900CA6CDF /* JSEnterPictureInPictureEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSEnterPictureInPictureEvent.h; path = JSEnterPictureInPictureEvent.h; sourceTree = "<group>"; };
+               1D0026A92374F9D900CA6CDF /* JSEnterPictureInPictureEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSEnterPictureInPictureEvent.cpp; path = JSEnterPictureInPictureEvent.cpp; sourceTree = "<group>"; };
                1D2C82B6236A3F6A0055D6C5 /* PictureInPictureSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PictureInPictureSupport.h; sourceTree = "<group>"; };
                1DBC1B552347B3D200B901AF /* PictureInPictureObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PictureInPictureObserver.h; sourceTree = "<group>"; };
                1DC553FD211BA12A004B780E /* NavigatorShare.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NavigatorShare.idl; sourceTree = "<group>"; };
                                33503C9C10179A9A003B47E1 /* Notifications */,
                                1AC226020DB69EA70089B669 /* Offline */,
                                A1CC564A1F4613BB00A4555B /* PaymentRequest */,
+                               1D00269A2374B9F800CA6CDF /* PictureInPicture */,
                                A9D247F90D757E4100FDF959 /* Plugins */,
                                89F60B17157F6A020075E157 /* Quota */,
                                BC9854460CD3DA5F00069BC1 /* Ranges */,
                        path = Metal;
                        sourceTree = "<group>";
                };
+               1D00269A2374B9F800CA6CDF /* PictureInPicture */ = {
+                       isa = PBXGroup;
+                       children = (
+                               1D0026A92374F9D900CA6CDF /* JSEnterPictureInPictureEvent.cpp */,
+                               1D0026A82374F9D900CA6CDF /* JSEnterPictureInPictureEvent.h */,
+                               1D0026A32374D62400CA6CDF /* JSPictureInPictureWindow.cpp */,
+                               1D0026A22374D62300CA6CDF /* JSPictureInPictureWindow.h */,
+                       );
+                       name = PictureInPicture;
+                       sourceTree = "<group>";
+               };
                1DEF06A2233C32DB00EE228D /* pictureinpicture */ = {
                        isa = PBXGroup;
                        children = (
                                71495DDB202B06F100ADFD34 /* JSEffectTiming.h in Headers */,
                                65DF31FA09D1CC60000BE325 /* JSElement.h in Headers */,
                                ADEC78F818EE5308001315C2 /* JSElementCustom.h in Headers */,
+                               1D0026AA2374F9EA00CA6CDF /* JSEnterPictureInPictureEvent.h in Headers */,
                                83EE598F1F50958E003E8B30 /* JSErrorCallback.h in Headers */,
                                2ECF7ADD10162B3800427DE7 /* JSErrorEvent.h in Headers */,
                                F3D461491161D53200CA0D09 /* JSErrorHandler.h in Headers */,
                                CB38FD5B1CD2325B00592A3F /* JSPerformanceResourceTiming.h in Headers */,
                                8A9A588811E84F37008ACFD1 /* JSPerformanceTiming.h in Headers */,
                                FDEA6247152102FC00479DF0 /* JSPeriodicWave.h in Headers */,
+                               1D0026A42374D62400CA6CDF /* JSPictureInPictureWindow.h in Headers */,
                                712BE4891FE86875002031CC /* JSPlaybackDirection.h in Headers */,
                                93B70D6C09EB0C7C009D8468 /* JSPluginElementFunctions.h in Headers */,
                                5189F01E10B37BD900F3C739 /* JSPopStateEvent.h in Headers */,
index edad9fb..244260c 100644 (file)
 #include <wtf/text/TextStream.h>
 
 #if ENABLE(VIDEO_PRESENTATION_MODE)
-#include "PictureInPictureObserver.h"
 #include "VideoFullscreenModel.h"
 #endif
 
+#if ENABLE(PICTURE_IN_PICTURE_API)
+#include "HTMLVideoElementPictureInPicture.h"
+#include "PictureInPictureObserver.h"
+#endif
+
 namespace WebCore {
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLVideoElement);
@@ -69,6 +73,11 @@ inline HTMLVideoElement::HTMLVideoElement(const QualifiedName& tagName, Document
 Ref<HTMLVideoElement> HTMLVideoElement::create(const QualifiedName& tagName, Document& document, bool createdByParser)
 {
     auto videoElement = adoptRef(*new HTMLVideoElement(tagName, document, createdByParser));
+
+#if ENABLE(PICTURE_IN_PICTURE_API)
+    HTMLVideoElementPictureInPicture::providePictureInPictureTo(videoElement);
+#endif
+
     videoElement->finishInitialization();
     videoElement->suspendIfNeeded();
     return videoElement;