browser_autoplay_policy_request_permission.js (8342B)
1 /* Any copyright is dedicated to the Public Domain. 2 * http://creativecommons.org/publicdomain/zero/1.0/ 3 */ 4 5 "use strict"; 6 7 const { PermissionTestUtils } = ChromeUtils.importESModule( 8 "resource://testing-common/PermissionTestUtils.sys.mjs" 9 ); 10 11 const VIDEO_PAGE_URI = GetTestWebBasedURL("file_empty.html"); 12 const SAME_ORIGIN_FRAME_URI = GetTestWebBasedURL( 13 "file_mediaplayback_frame.html" 14 ); 15 const DIFFERENT_ORIGIN_FRAME_URI = GetTestWebBasedURL( 16 "file_mediaplayback_frame.html", 17 { crossOrigin: true } 18 ); 19 20 const gPermissionName = "autoplay-media"; 21 22 function setTestingPreferences(defaultSetting) { 23 info(`set default autoplay setting to '${defaultSetting}'`); 24 let defaultValue = 25 defaultSetting == "blocked" 26 ? SpecialPowers.Ci.nsIAutoplay.BLOCKED 27 : SpecialPowers.Ci.nsIAutoplay.ALLOWED; 28 return SpecialPowers.pushPrefEnv({ 29 set: [ 30 ["media.autoplay.default", defaultValue], 31 ["media.autoplay.blocking_policy", 0], 32 ["media.autoplay.block-event.enabled", true], 33 ], 34 }); 35 } 36 37 async function testAutoplayExistingPermission(args) { 38 info("- Starting '" + args.name + "' -"); 39 await BrowserTestUtils.withNewTab( 40 { 41 gBrowser, 42 url: VIDEO_PAGE_URI, 43 }, 44 async browser => { 45 let promptShowing = () => 46 PopupNotifications.getNotification("autoplay-media", browser); 47 48 PermissionTestUtils.add( 49 browser.currentURI, 50 "autoplay-media", 51 args.permission 52 ); 53 ok(!promptShowing(), "Should not be showing permission prompt yet"); 54 55 await loadAutoplayVideo(browser, args); 56 await checkVideoDidPlay(browser, args); 57 58 // Reset permission. 59 PermissionTestUtils.remove(browser.currentURI, "autoplay-media"); 60 61 info("- Finished '" + args.name + "' -"); 62 } 63 ); 64 } 65 66 async function testAutoplayExistingPermissionAgainstDefaultSetting(args) { 67 await setTestingPreferences(args.defaultSetting); 68 await testAutoplayExistingPermission(args); 69 } 70 71 // Test the simple ALLOW/BLOCK cases; when permission is already set to ALLOW, 72 // we shoud be able to autoplay via calling play(), or via the autoplay attribute, 73 // and when it's set to BLOCK, we should not. 74 add_task(async () => { 75 await setTestingPreferences("blocked" /* default setting */); 76 await testAutoplayExistingPermission({ 77 name: "Prexisting allow permission autoplay attribute", 78 permission: Services.perms.ALLOW_ACTION, 79 shouldPlay: true, 80 mode: "autoplay attribute", 81 }); 82 await testAutoplayExistingPermission({ 83 name: "Prexisting allow permission call play", 84 permission: Services.perms.ALLOW_ACTION, 85 shouldPlay: true, 86 mode: "call play", 87 }); 88 await testAutoplayExistingPermission({ 89 name: "Prexisting block permission autoplay attribute", 90 permission: Services.perms.DENY_ACTION, 91 shouldPlay: false, 92 mode: "autoplay attribute", 93 }); 94 await testAutoplayExistingPermission({ 95 name: "Prexisting block permission call play", 96 permission: Services.perms.DENY_ACTION, 97 shouldPlay: false, 98 mode: "call play", 99 }); 100 }); 101 102 /** 103 * These tests are used to ensure the autoplay setting for specific site can 104 * always override the default autoplay setting. 105 */ 106 add_task(async () => { 107 await testAutoplayExistingPermissionAgainstDefaultSetting({ 108 name: "Site has prexisting allow permission but default setting is 'blocked'", 109 permission: Services.perms.ALLOW_ACTION, 110 defaultSetting: "blocked", 111 shouldPlay: true, 112 mode: "autoplay attribute", 113 }); 114 await testAutoplayExistingPermissionAgainstDefaultSetting({ 115 name: "Site has prexisting block permission but default setting is 'allowed'", 116 permission: Services.perms.DENY_ACTION, 117 defaultSetting: "allowed", 118 shouldPlay: false, 119 mode: "autoplay attribute", 120 }); 121 }); 122 123 /** 124 * The permission of the main page's domain would determine the final autoplay 125 * result when a page contains multiple iframes which are in the different 126 * domain from the main pages's. 127 * That means we would not check the permission of iframe's domain, even if it 128 * has been set. 129 */ 130 add_task(async function testExistingPermissionForIframe() { 131 await setTestingPreferences("blocked" /* default setting */); 132 await testAutoplayExistingPermissionForIframe({ 133 name: "Prexisting ALLOW for main page with same origin iframe", 134 permissionForParent: Services.perms.ALLOW_ACTION, 135 isIframeDifferentOrgin: true, 136 shouldPlay: true, 137 }); 138 139 await testAutoplayExistingPermissionForIframe({ 140 name: "Prexisting ALLOW for main page with different origin iframe", 141 permissionForParent: Services.perms.ALLOW_ACTION, 142 isIframeDifferentOrgin: false, 143 shouldPlay: true, 144 }); 145 146 await testAutoplayExistingPermissionForIframe({ 147 name: "Prexisting ALLOW for main page, prexisting DENY for different origin iframe", 148 permissionForParent: Services.perms.ALLOW_ACTION, 149 permissionForChild: Services.perms.DENY_ACTION, 150 isIframeDifferentOrgin: false, 151 shouldPlay: true, 152 }); 153 154 await testAutoplayExistingPermissionForIframe({ 155 name: "Prexisting DENY for main page, prexisting ALLOW for different origin iframe", 156 permissionForParent: Services.perms.DENY_ACTION, 157 permissionForChild: Services.perms.ALLOW_ACTION, 158 isIframeDifferentOrgin: false, 159 shouldPlay: false, 160 }); 161 }); 162 163 /** 164 * The following are helper functions. 165 */ 166 async function testAutoplayExistingPermissionForIframe(args) { 167 info(`Start test : ${args.name}`); 168 await BrowserTestUtils.withNewTab( 169 { 170 gBrowser, 171 url: VIDEO_PAGE_URI, 172 }, 173 async browser => { 174 setupSitesPermission(browser, args); 175 176 await createIframe(browser, args); 177 await checkAutplayInIframe(browser, args); 178 179 clearSitesPermission(browser, args); 180 } 181 ); 182 info(`Finish test : ${args.name}`); 183 } 184 185 function setupSitesPermission( 186 browser, 187 { 188 isIframeDifferentOrgin, 189 permissionForParent, 190 permissionForChild = Services.perms.UNKNOWN_ACTION, 191 } 192 ) { 193 info(`setupSitesPermission`); 194 // Set permission for the main page's domain 195 setPermissionForBrowser(browser, browser.currentURI, permissionForParent); 196 if (isIframeDifferentOrgin) { 197 // Set permission for different domain of the iframe 198 setPermissionForBrowser( 199 browser, 200 DIFFERENT_ORIGIN_FRAME_URI, 201 permissionForChild 202 ); 203 } 204 } 205 206 function clearSitesPermission(browser, { isIframeDifferentOrgin }) { 207 info(`clearSitesPermission`); 208 // Clear permission for the main page's domain 209 setPermissionForBrowser( 210 browser, 211 browser.currentURI, 212 Services.perms.UNKNOWN_ACTION 213 ); 214 if (isIframeDifferentOrgin) { 215 // Clear permission for different domain of the iframe 216 setPermissionForBrowser( 217 browser, 218 DIFFERENT_ORIGIN_FRAME_URI, 219 Services.perms.UNKNOWN_ACTION 220 ); 221 } 222 } 223 224 function setPermissionForBrowser(browser, uri, permValue) { 225 const promptShowing = () => 226 PopupNotifications.getNotification(gPermissionName, browser); 227 PermissionTestUtils.add(uri, gPermissionName, permValue); 228 ok(!promptShowing(), "Should not be showing permission prompt yet"); 229 is( 230 PermissionTestUtils.testExactPermission(uri, gPermissionName), 231 permValue, 232 "Set permission correctly" 233 ); 234 } 235 236 function createIframe(browser, { isIframeDifferentOrgin }) { 237 const iframeURL = isIframeDifferentOrgin 238 ? DIFFERENT_ORIGIN_FRAME_URI 239 : SAME_ORIGIN_FRAME_URI; 240 return SpecialPowers.spawn(browser, [iframeURL], async url => { 241 info(`Create iframe and wait until it finsihes loading`); 242 const iframe = content.document.createElement("iframe"); 243 iframe.src = url; 244 content.document.body.appendChild(iframe); 245 await new Promise(r => (iframe.onload = r)); 246 }); 247 } 248 249 function checkAutplayInIframe(browser, args) { 250 return SpecialPowers.spawn(browser, [args], async ({ shouldPlay }) => { 251 info(`check if media in iframe can start playing`); 252 const iframe = content.document.getElementsByTagName("iframe")[0]; 253 if (!iframe) { 254 ok(false, `can not get the iframe!`); 255 return; 256 } 257 iframe.contentWindow.postMessage("play", "*"); 258 await new Promise(r => { 259 content.onmessage = event => { 260 if (shouldPlay) { 261 is(event.data, "played", `played media in iframe`); 262 } else { 263 is(event.data, "blocked", `blocked media in iframe`); 264 } 265 r(); 266 }; 267 }); 268 }); 269 }