/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; const { PermissionTestUtils } = ChromeUtils.importESModule( "resource://testing-common/PermissionTestUtils.sys.mjs" ); const VIDEO_PAGE_URI = GetTestWebBasedURL("file_empty.html"); const SAME_ORIGIN_FRAME_URI = GetTestWebBasedURL( "file_mediaplayback_frame.html" ); const DIFFERENT_ORIGIN_FRAME_URI = GetTestWebBasedURL( "file_mediaplayback_frame.html", { crossOrigin: true } ); const gPermissionName = "autoplay-media"; function setTestingPreferences(defaultSetting) { info(`set default autoplay setting to '${defaultSetting}'`); let defaultValue = defaultSetting == "blocked" ? SpecialPowers.Ci.nsIAutoplay.BLOCKED : SpecialPowers.Ci.nsIAutoplay.ALLOWED; return SpecialPowers.pushPrefEnv({ set: [ ["media.autoplay.default", defaultValue], ["media.autoplay.blocking_policy", 0], ["media.autoplay.block-event.enabled", true], ], }); } async function testAutoplayExistingPermission(args) { info("- Starting '" + args.name + "' -"); await BrowserTestUtils.withNewTab( { gBrowser, url: VIDEO_PAGE_URI, }, async browser => { let promptShowing = () => PopupNotifications.getNotification("autoplay-media", browser); PermissionTestUtils.add( 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. PermissionTestUtils.remove(browser.currentURI, "autoplay-media"); info("- Finished '" + args.name + "' -"); } ); } async function testAutoplayExistingPermissionAgainstDefaultSetting(args) { await setTestingPreferences(args.defaultSetting); await testAutoplayExistingPermission(args); } // Test the simple ALLOW/BLOCK cases; when permission is already set to ALLOW, // we shoud be able to autoplay via calling play(), or via the autoplay attribute, // and when it's set to BLOCK, we should not. add_task(async () => { await setTestingPreferences("blocked" /* default setting */); await testAutoplayExistingPermission({ name: "Prexisting allow permission autoplay attribute", permission: Services.perms.ALLOW_ACTION, shouldPlay: true, mode: "autoplay attribute", }); await testAutoplayExistingPermission({ name: "Prexisting allow permission call play", permission: Services.perms.ALLOW_ACTION, shouldPlay: true, mode: "call play", }); await testAutoplayExistingPermission({ name: "Prexisting block permission autoplay attribute", permission: Services.perms.DENY_ACTION, shouldPlay: false, mode: "autoplay attribute", }); await testAutoplayExistingPermission({ name: "Prexisting block permission call play", permission: Services.perms.DENY_ACTION, shouldPlay: false, mode: "call play", }); }); /** * These tests are used to ensure the autoplay setting for specific site can * always override the default autoplay setting. */ add_task(async () => { await testAutoplayExistingPermissionAgainstDefaultSetting({ name: "Site has prexisting allow permission but default setting is 'blocked'", permission: Services.perms.ALLOW_ACTION, defaultSetting: "blocked", shouldPlay: true, mode: "autoplay attribute", }); await testAutoplayExistingPermissionAgainstDefaultSetting({ name: "Site has prexisting block permission but default setting is 'allowed'", permission: Services.perms.DENY_ACTION, defaultSetting: "allowed", shouldPlay: false, mode: "autoplay attribute", }); }); /** * The permission of the main page's domain would determine the final autoplay * result when a page contains multiple iframes which are in the different * domain from the main pages's. * That means we would not check the permission of iframe's domain, even if it * has been set. */ add_task(async function testExistingPermissionForIframe() { await setTestingPreferences("blocked" /* default setting */); await testAutoplayExistingPermissionForIframe({ name: "Prexisting ALLOW for main page with same origin iframe", permissionForParent: Services.perms.ALLOW_ACTION, isIframeDifferentOrgin: true, shouldPlay: true, }); await testAutoplayExistingPermissionForIframe({ name: "Prexisting ALLOW for main page with different origin iframe", permissionForParent: Services.perms.ALLOW_ACTION, isIframeDifferentOrgin: false, shouldPlay: true, }); await testAutoplayExistingPermissionForIframe({ name: "Prexisting ALLOW for main page, prexisting DENY for different origin iframe", permissionForParent: Services.perms.ALLOW_ACTION, permissionForChild: Services.perms.DENY_ACTION, isIframeDifferentOrgin: false, shouldPlay: true, }); await testAutoplayExistingPermissionForIframe({ name: "Prexisting DENY for main page, prexisting ALLOW for different origin iframe", permissionForParent: Services.perms.DENY_ACTION, permissionForChild: Services.perms.ALLOW_ACTION, isIframeDifferentOrgin: false, shouldPlay: false, }); }); /** * The following are helper functions. */ async function testAutoplayExistingPermissionForIframe(args) { info(`Start test : ${args.name}`); await BrowserTestUtils.withNewTab( { gBrowser, url: VIDEO_PAGE_URI, }, async browser => { setupSitesPermission(browser, args); await createIframe(browser, args); await checkAutplayInIframe(browser, args); clearSitesPermission(browser, args); } ); info(`Finish test : ${args.name}`); } function setupSitesPermission( browser, { isIframeDifferentOrgin, permissionForParent, permissionForChild = Services.perms.UNKNOWN_ACTION, } ) { info(`setupSitesPermission`); // Set permission for the main page's domain setPermissionForBrowser(browser, browser.currentURI, permissionForParent); if (isIframeDifferentOrgin) { // Set permission for different domain of the iframe setPermissionForBrowser( browser, DIFFERENT_ORIGIN_FRAME_URI, permissionForChild ); } } function clearSitesPermission(browser, { isIframeDifferentOrgin }) { info(`clearSitesPermission`); // Clear permission for the main page's domain setPermissionForBrowser( browser, browser.currentURI, Services.perms.UNKNOWN_ACTION ); if (isIframeDifferentOrgin) { // Clear permission for different domain of the iframe setPermissionForBrowser( browser, DIFFERENT_ORIGIN_FRAME_URI, Services.perms.UNKNOWN_ACTION ); } } function setPermissionForBrowser(browser, uri, permValue) { const promptShowing = () => PopupNotifications.getNotification(gPermissionName, browser); PermissionTestUtils.add(uri, gPermissionName, permValue); ok(!promptShowing(), "Should not be showing permission prompt yet"); is( PermissionTestUtils.testExactPermission(uri, gPermissionName), permValue, "Set permission correctly" ); } function createIframe(browser, { isIframeDifferentOrgin }) { const iframeURL = isIframeDifferentOrgin ? DIFFERENT_ORIGIN_FRAME_URI : SAME_ORIGIN_FRAME_URI; return SpecialPowers.spawn(browser, [iframeURL], async url => { info(`Create iframe and wait until it finsihes loading`); const iframe = content.document.createElement("iframe"); iframe.src = url; content.document.body.appendChild(iframe); await new Promise(r => (iframe.onload = r)); }); } function checkAutplayInIframe(browser, args) { return SpecialPowers.spawn(browser, [args], async ({ shouldPlay }) => { info(`check if media in iframe can start playing`); const iframe = content.document.getElementsByTagName("iframe")[0]; if (!iframe) { ok(false, `can not get the iframe!`); return; } iframe.contentWindow.postMessage("play", "*"); await new Promise(r => { content.onmessage = event => { if (shouldPlay) { is(event.data, "played", `played media in iframe`); } else { is(event.data, "blocked", `blocked media in iframe`); } r(); }; }); }); }