summaryrefslogtreecommitdiffstats
path: root/dom/media/mediacontrol/tests/browser/browser_media_control_before_media_starts.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/mediacontrol/tests/browser/browser_media_control_before_media_starts.js')
-rw-r--r--dom/media/mediacontrol/tests/browser/browser_media_control_before_media_starts.js205
1 files changed, 205 insertions, 0 deletions
diff --git a/dom/media/mediacontrol/tests/browser/browser_media_control_before_media_starts.js b/dom/media/mediacontrol/tests/browser/browser_media_control_before_media_starts.js
new file mode 100644
index 0000000000..292c2f521f
--- /dev/null
+++ b/dom/media/mediacontrol/tests/browser/browser_media_control_before_media_starts.js
@@ -0,0 +1,205 @@
+// Import this in order to use `triggerPictureInPicture()`.
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/toolkit/components/pictureinpicture/tests/head.js",
+ this
+);
+
+const PAGE_NON_AUTOPLAY =
+ "https://example.com/browser/dom/media/mediacontrol/tests/browser/file_non_autoplay.html";
+const IFRAME_URL =
+ "https://example.com/browser/dom/media/mediacontrol/tests/browser/file_iframe_media.html";
+const testVideoId = "video";
+
+add_task(async function setupTestingPref() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["media.mediacontrol.testingevents.enabled", true],
+ ["full-screen-api.allow-trusted-requests-only", false],
+ ],
+ });
+});
+
+/**
+ * Usually we would only start controlling media after media starts, but if
+ * media has entered Picture-in-Picture mode or fullscreen, then we would allow
+ * users to control them directly without prior to starting media.
+ */
+add_task(async function testMediaEntersPIPMode() {
+ info(`open media page`);
+ const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY);
+
+ info(`trigger PIP mode`);
+ const winPIP = await triggerPictureInPicture(tab.linkedBrowser, testVideoId);
+
+ info(`press 'play' and wait until media starts`);
+ await generateMediaControlKeyEvent("play");
+ await checkOrWaitUntilMediaStartedPlaying(tab, testVideoId);
+
+ info(`remove tab`);
+ await BrowserTestUtils.closeWindow(winPIP);
+ await tab.close();
+});
+
+add_task(async function testMutedMediaEntersPIPMode() {
+ info(`open media page and mute video`);
+ const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY);
+ await muteMedia(tab, testVideoId);
+
+ info(`trigger PIP mode`);
+ const winPIP = await triggerPictureInPicture(tab.linkedBrowser, testVideoId);
+
+ info(`press 'play' and wait until media starts`);
+ await generateMediaControlKeyEvent("play");
+ await checkOrWaitUntilMediaStartedPlaying(tab, testVideoId);
+
+ info(`remove tab`);
+ await BrowserTestUtils.closeWindow(winPIP);
+ await tab.close();
+});
+
+add_task(async function testMediaEntersFullScreen() {
+ info(`open media page`);
+ const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY);
+
+ info(`make video fullscreen`);
+ await enableFullScreen(tab, testVideoId);
+
+ info(`press 'play' and wait until media starts`);
+ await generateMediaControlKeyEvent("play");
+ await checkOrWaitUntilMediaStartedPlaying(tab, testVideoId);
+
+ info(`remove tab`);
+ await tab.close();
+});
+
+add_task(async function testMutedMediaEntersFullScreen() {
+ info(`open media page and mute video`);
+ const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY);
+ await muteMedia(tab, testVideoId);
+
+ info(`make video fullscreen`);
+ await enableFullScreen(tab, testVideoId);
+
+ info(`press 'play' and wait until media starts`);
+ await generateMediaControlKeyEvent("play");
+ await checkOrWaitUntilMediaStartedPlaying(tab, testVideoId);
+
+ info(`remove tab`);
+ await tab.close();
+});
+
+add_task(async function testNonMediaEntersFullScreen() {
+ info(`open media page which won't have an activated controller`);
+ // As we won't activate controller in this test case, not need to
+ // check controller's status.
+ const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY, {
+ needCheck: false,
+ });
+
+ info(`make non-media element fullscreen`);
+ const nonMediaElementId = "image";
+ await enableFullScreen(tab, nonMediaElementId);
+
+ info(`press 'play' which should not start media`);
+ // Use `generateMediaControlKey()` directly because `play` won't affect the
+ // controller's playback state (don't need to wait for the change).
+ MediaControlService.generateMediaControlKey("play");
+ await checkOrWaitUntilMediaStoppedPlaying(tab, testVideoId);
+
+ info(`remove tab`);
+ await tab.close();
+});
+
+add_task(async function testMediaInIframeEntersFullScreen() {
+ info(`open media page`);
+ const tab = await createLoadedTabWrapper(PAGE_NON_AUTOPLAY);
+
+ info(`make video in iframe fullscreen`);
+ await enableMediaFullScreenInIframe(tab, testVideoId);
+
+ info(`press 'play' and wait until media starts`);
+ await generateMediaControlKeyEvent("play");
+
+ info(`full screen media in inframe should be started`);
+ await waitUntilIframeMediaStartedPlaying(tab);
+
+ info(`media not in fullscreen should keep paused`);
+ await checkOrWaitUntilMediaStoppedPlaying(tab, testVideoId);
+
+ info(`remove iframe that contains fullscreen video`);
+ await removeIframeFromDocument(tab);
+
+ info(`remove tab`);
+ await tab.close();
+});
+
+/**
+ * The following are helper functions.
+ */
+function muteMedia(tab, videoId) {
+ return SpecialPowers.spawn(tab.linkedBrowser, [videoId], videoId => {
+ content.document.getElementById(videoId).muted = true;
+ });
+}
+
+function enableFullScreen(tab, elementId) {
+ return SpecialPowers.spawn(tab.linkedBrowser, [elementId], elementId => {
+ return new Promise(r => {
+ const element = content.document.getElementById(elementId);
+ element.requestFullscreen();
+ element.onfullscreenchange = () => {
+ element.onfullscreenchange = null;
+ element.onfullscreenerror = null;
+ r();
+ };
+ element.onfullscreenerror = () => {
+ // Retry until the element successfully enters fullscreen.
+ element.requestFullscreen();
+ };
+ });
+ });
+}
+
+function enableMediaFullScreenInIframe(tab) {
+ return SpecialPowers.spawn(tab.linkedBrowser, [IFRAME_URL], async url => {
+ info(`create iframe and wait until it finishes loading`);
+ const iframe = content.document.getElementById("iframe");
+ iframe.src = url;
+ await new Promise(r => (iframe.onload = r));
+
+ info(`trigger media in iframe entering into fullscreen`);
+ iframe.contentWindow.postMessage("fullscreen", "*");
+ info(`wait until media in frame enters fullscreen`);
+ return new Promise(r => {
+ content.onmessage = event => {
+ is(
+ event.data,
+ "entered-fullscreen",
+ `media in iframe entered fullscreen`
+ );
+ r();
+ };
+ });
+ });
+}
+
+function waitUntilIframeMediaStartedPlaying(tab) {
+ return SpecialPowers.spawn(tab.linkedBrowser, [IFRAME_URL], async url => {
+ info(`check if media in iframe starts playing`);
+ const iframe = content.document.getElementById("iframe");
+ iframe.contentWindow.postMessage("check-playing", "*");
+ return new Promise(r => {
+ content.onmessage = event => {
+ is(event.data, "checked-playing", `media in iframe is playing`);
+ r();
+ };
+ });
+ });
+}
+
+function removeIframeFromDocument(tab) {
+ return SpecialPowers.spawn(tab.linkedBrowser, [], () => {
+ info(`remove iframe from document`);
+ content.document.getElementById("iframe").remove();
+ });
+}