--- a/toolkit/content/tests/browser/browser_autoplay_policy_request_permission.js
+++ b/toolkit/content/tests/browser/browser_autoplay_policy_request_permission.js
@@ -21,24 +21,24 @@ add_task(() => {
// browser: the browser to run the script in.
// args: test case definition, required members {
// mode: String, "autoplay attribute" or "call play".
// }
function loadAutoplayVideo(browser, args) {
return ContentTask.spawn(browser, args, async (args) => {
info("- create a new autoplay video -");
let video = content.document.createElement("video");
- video.id = "v1";
video.didPlayPromise = new Promise((resolve, reject) => {
video.addEventListener("play", (e) => {
video.didPlay = true;
resolve();
}, {once: true});
video.addEventListener("blocked", (e) => {
video.didPlay = false;
+ video.playPromiseRejected = true;
resolve();
}, {once: true});
});
if (args.mode == "autoplay attribute") {
info("autoplay attribute set to true");
video.autoplay = true;
} else if (args.mode == "call play") {
info("will call play() when reached loadedmetadata");
@@ -65,33 +65,33 @@ function loadAutoplayVideo(browser, args
// browser: the browser to run the script in.
// args: test case definition, required members {
// name: String, description of test.
// mode: String, "autoplay attribute" or "call play".
// shouldPlay: boolean, whether video should play.
// }
function checkVideoDidPlay(browser, args) {
return ContentTask.spawn(browser, args, async (args) => {
- let video = content.document.getElementById("v1");
+ let video = content.document.querySelector("video");
await video.didPlayPromise;
is(video.didPlay, args.shouldPlay,
args.name + " should " + (!args.shouldPlay ? "not " : "") + "be able to autoplay");
video.src = "";
content.document.body.remove(video);
});
}
async function testAutoplayExistingPermission(args) {
info("- Starting '" + args.name + "' -");
await BrowserTestUtils.withNewTab({
gBrowser,
url: VIDEO_PAGE,
}, async (browser) => {
let promptShowing = () =>
- PopupNotifications.getNotification("autoplay-media", browser);
+ PopupNotifications.getNotification("autoplay-media", browser);
SitePermissions.set(browser.currentURI, "autoplay-media", args.permission);
ok(!promptShowing(), "Should not be showing permission prompt yet");
await loadAutoplayVideo(browser, args);
await checkVideoDidPlay(browser, args);
// Reset permission.
@@ -197,17 +197,53 @@ add_task(async () => {
await testAutoplayUnknownPermission({
name: "Unknown permission click block call play",
button: "block",
shouldPlay: false,
mode: "call play",
});
});
-// Test that if playback starts while the permission prompt is shown,
+function checkAllVideosNotPlayed(browser) {
+ return ContentTask.spawn(browser, null,
+ async () => {
+ content.document.querySelectorAll("video").forEach((video) => {
+ ok(video.paused && !video.didPlay, "Video should not be playing");
+ });
+ });
+}
+
+function unblockAndPlayVideo(browser, args) {
+ return ContentTask.spawn(browser, args,
+ async (args) => {
+ ok(args.index != undefined, "Must specify index");
+ ok(args.unblockMode != undefined, "Must specify unblock mode");
+ let video = content.document.querySelectorAll("video")[args.index];
+ if (args.unblockMode == "muted") {
+ video.muted = true;
+ // Muting in itself should not cause the previous pending play to proceed.
+ ok(video.paused && !video.didPlay, "First video should not have played yet");
+ } else if (args.unblockMode == "gesture") {
+ // Gesture activate the document, i.e. simulate a click in the document,
+ // to unblock autoplay,
+ content.document.notifyUserGestureActivation();
+ } else {
+ ok(false, "Invalid unblock mode.");
+ }
+ // Trying to play now that we're unblocked should work...
+ let played = await video.play().then(() => true, () => false);
+ ok(played, "Should have played as now muted");
+ // And because we started playing, the previous promise returned in the
+ // previous call to play() should also resolve too.
+ await video.didPlayPromise;
+ ok(video.didPlay, "Existing promise should resolve when media starts playing");
+ });
+}
+
+// Test that if audible playback starts due to user gesture while the permission prompt is shown,
// that the prompt is hidden.
add_task(async () => {
await BrowserTestUtils.withNewTab({
gBrowser,
url: VIDEO_PAGE,
}, async (browser) => {
info("- Started test prompt hides upon play -");
let promptShowing = () =>
@@ -220,43 +256,131 @@ add_task(async () => {
let popupshown = BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
await loadAutoplayVideo(browser, { mode: "call play" });
info("Awaiting popupshown");
await popupshown;
ok(promptShowing(), "Should now be showing permission prompt");
// Check that the video didn't start playing.
- await ContentTask.spawn(browser, null,
- async () => {
- let video = content.document.getElementById("v1");
- ok(video.paused && !video.didPlay, "Video should not be playing");
- });
+ await checkAllVideosNotPlayed(browser);
let popuphidden = BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden");
- await ContentTask.spawn(browser, null,
- async () => {
- // Gesture activate the document, i.e. simulate a click in the document,
- // to unblock autoplay,
- content.document.notifyUserGestureActivation();
- let video = content.document.getElementById("v1");
- // Gesture activating in itself should not cause the previous pending
- // play to proceed.
- ok(video.paused && !video.didPlay, "Video should not have played yet");
- // But trying to play again now that we're gesture activated will work...
- let played = await video.play().then(() => true, () => false);
- ok(played, "Should have played as now gesture activated");
- // And because we started playing, the previous promise returned in the
- // first call to play() above should also resolve too.
- await video.didPlayPromise;
- ok(video.didPlay, "Existing promise should resolve when media starts playing");
- });
+ // Unblock via user gesture and play.
+ await unblockAndPlayVideo(browser, {index: 0, unblockMode: "gesture"});
info("Awaiting popuphidden");
await popuphidden;
ok(!promptShowing(), "Permission prompt should have hidden when media started playing");
// Reset permission.
SitePermissions.remove(browser.currentURI, "autoplay-media");
info("- Finished test prompt hides upon play -");
});
});
+
+// Test that if there's only 1 document, and inaudible playback starts while
+// the permission prompt is shown, that the prompt is hidden.
+add_task(async () => {
+ await BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: VIDEO_PAGE,
+ }, async (browser) => {
+ info("- Started test prompt hides upon inaudible play in 1 doc -");
+ let promptShowing = () =>
+ PopupNotifications.getNotification("autoplay-media", browser);
+
+ // Set this site to ask permission to autoplay.
+ SitePermissions.set(browser.currentURI, "autoplay-media", SitePermissions.UNKNOWN);
+ ok(!promptShowing(), "Should not be showing permission prompt");
+
+ let popupshown = BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
+ await loadAutoplayVideo(browser, { mode: "call play" });
+
+ info("Awaiting popupshown");
+ await popupshown;
+ ok(promptShowing(), "Should now be showing permission prompt");
+
+ // Check that the video didn't start playing.
+ await checkAllVideosNotPlayed(browser);
+
+ let popuphidden = BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden");
+
+ // Make video inaudible, and then start to play.
+ await unblockAndPlayVideo(browser, {index: 0, unblockMode: "muted"});
+
+ info("Awaiting popuphidden");
+ await popuphidden;
+ ok(!promptShowing(), "Permission prompt should have hidden when media started playing");
+
+ // Reset permission.
+ SitePermissions.remove(browser.currentURI, "autoplay-media");
+ info("- Finished test prompt hides upon inaudible play in 1 doc -");
+ });
+});
+
+// Test that one media element playing inaudibly will cause other media elements
+// waiting on a doorhanger to have their play promises rejected.
+add_task(async () => {
+ await BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: VIDEO_PAGE,
+ }, async (browser) => {
+ info("- Started test prompt hides upon inaudible play in multi doc -");
+ let promptShowing = () =>
+ PopupNotifications.getNotification("autoplay-media", browser);
+
+ // Set this site to ask permission to autoplay.
+ SitePermissions.set(browser.currentURI, "autoplay-media", SitePermissions.UNKNOWN);
+ ok(!promptShowing(), "Should not be showing permission prompt");
+
+ let popupshown = BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popupshown");
+
+ // Load multiple videos.
+ await loadAutoplayVideo(browser, { mode: "call play" });
+ await loadAutoplayVideo(browser, { mode: "call play" });
+
+ // Create an autoplay audio element in a subdocument.
+ await ContentTask.spawn(browser, null,
+ async () => {
+ let iframe = content.document.createElement("iframe");
+ let iframeLoaded = new Promise((resolve, reject) => {
+ iframe.addEventListener("load", e => resolve(), {once: true});
+ });
+ iframe.src = "file_video_autoplay.html";
+ content.document.body.appendChild(iframe);
+ await iframeLoaded;
+ });
+
+ info("Awaiting popupshown");
+ await popupshown;
+ ok(promptShowing(), "Should now be showing permission prompt");
+
+ // Check that the video didn't start playing.
+ await checkAllVideosNotPlayed(browser);
+
+ let popuphidden = BrowserTestUtils.waitForEvent(PopupNotifications.panel, "popuphidden");
+
+ // Make one video inaudible, and then start to play.
+ await unblockAndPlayVideo(browser, {index: 0, unblockMode: "muted"});
+
+ // Test that the second video shouldn't have been unblocked when the first was.
+ await ContentTask.spawn(browser, null,
+ async () => {
+ let video = content.document.querySelectorAll("video")[1];
+ ok(video.paused && !video.didPlay, "Second video should not have played yet");
+ ok(video.playPromiseRejected, "Second video should have had its play promise rejected");
+
+ // Check the video in the subdocument had its promise rejected too.
+ let iframe = content.document.querySelector("iframe");
+ video = iframe.contentDocument.querySelector("video");
+ ok(video.paused, "Subdoc video should not have played");
+ is(video.played.length, 0, "Should have empty played ranges");
+ });
+
+ ok(!promptShowing(), "We should no longer be showing permission prompt");
+
+ // Reset permission.
+ SitePermissions.remove(browser.currentURI, "autoplay-media");
+ info("- Finished test prompt hides upon inaudible play in multi doc -");
+ });
+});