browser_autoplay_blocked.js (10237B)
1 /* 2 * Test that a blocked request to autoplay media is shown to the user 3 */ 4 5 const AUTOPLAY_PAGE = 6 getRootDirectory(gTestPath).replace( 7 "chrome://mochitests/content", 8 "https://example.com" 9 ) + "browser_autoplay_blocked.html"; 10 11 const AUTOPLAY_JS_PAGE = 12 getRootDirectory(gTestPath).replace( 13 "chrome://mochitests/content", 14 "https://example.com" 15 ) + "browser_autoplay_js.html"; 16 17 const SLOW_AUTOPLAY_PAGE = 18 getRootDirectory(gTestPath).replace( 19 "chrome://mochitests/content", 20 "https://example.com" 21 ) + "browser_autoplay_blocked_slow.sjs"; 22 23 const MUTED_AUTOPLAY_PAGE = 24 getRootDirectory(gTestPath).replace( 25 "chrome://mochitests/content", 26 "https://example.com" 27 ) + "browser_autoplay_muted.html"; 28 29 const EMPTY_PAGE = 30 getRootDirectory(gTestPath).replace( 31 "chrome://mochitests/content", 32 "https://example.com" 33 ) + "empty.html"; 34 35 const AUTOPLAY_PREF = "media.autoplay.default"; 36 const AUTOPLAY_PERM = "autoplay-media"; 37 38 function autoplayBlockedIcon() { 39 return document.querySelector( 40 "#blocked-permissions-container " + 41 ".blocked-permission-icon.autoplay-media-icon" 42 ); 43 } 44 45 function permissionListBlockedIcons() { 46 return document.querySelectorAll( 47 "image.permission-popup-permission-icon.blocked-permission-icon" 48 ); 49 } 50 51 function sleep(ms) { 52 /* eslint-disable mozilla/no-arbitrary-setTimeout */ 53 return new Promise(resolve => setTimeout(resolve, ms)); 54 } 55 56 async function blockedIconShown() { 57 await TestUtils.waitForCondition(() => { 58 return BrowserTestUtils.isVisible(autoplayBlockedIcon()); 59 }, "Blocked icon is shown"); 60 } 61 62 async function blockedIconHidden() { 63 await TestUtils.waitForCondition(() => { 64 return BrowserTestUtils.isHidden(autoplayBlockedIcon()); 65 }, "Blocked icon is hidden"); 66 } 67 68 function testPermListHasEntries(expectEntries) { 69 let permissionsList = document.getElementById( 70 "permission-popup-permission-list" 71 ); 72 let listEntryCount = permissionsList.querySelectorAll( 73 ".permission-popup-permission-item" 74 ).length; 75 if (expectEntries) { 76 ok(listEntryCount, "List of permissions is not empty"); 77 return; 78 } 79 ok(!listEntryCount, "List of permissions is empty"); 80 } 81 82 add_setup(async function () { 83 registerCleanupFunction(() => { 84 Services.perms.removeAll(); 85 Services.prefs.clearUserPref(AUTOPLAY_PREF); 86 }); 87 }); 88 89 add_task(async function testMainViewVisible() { 90 Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.ALLOWED); 91 92 await BrowserTestUtils.withNewTab(AUTOPLAY_PAGE, async function () { 93 ok( 94 BrowserTestUtils.isHidden(autoplayBlockedIcon()), 95 "Blocked icon not shown" 96 ); 97 98 await openPermissionPopup(); 99 testPermListHasEntries(false); 100 await closePermissionPopup(); 101 }); 102 103 Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED); 104 105 await BrowserTestUtils.withNewTab(AUTOPLAY_PAGE, async function () { 106 let permissionsList = document.getElementById( 107 "permission-popup-permission-list" 108 ); 109 110 await blockedIconShown(); 111 112 await openPermissionPopup(); 113 testPermListHasEntries(true); 114 115 let labelText = SitePermissions.getPermissionLabel(AUTOPLAY_PERM); 116 let labels = permissionsList.querySelectorAll( 117 ".permission-popup-permission-label" 118 ); 119 is(labels.length, 1, "One permission visible in main view"); 120 is(labels[0].textContent, labelText, "Correct value"); 121 122 let menulist = document.getElementById("permission-popup-menulist"); 123 Assert.equal(menulist.label, "Block Audio"); 124 125 await EventUtils.synthesizeMouseAtCenter(menulist, { type: "mousedown" }); 126 await TestUtils.waitForCondition(() => { 127 return ( 128 menulist.getElementsByTagName("menuitem")[0].label === 129 "Allow Audio and Video" 130 ); 131 }); 132 133 let menuitem = menulist.getElementsByTagName("menuitem")[0]; 134 Assert.equal(menuitem.getAttribute("label"), "Allow Audio and Video"); 135 136 menuitem.click(); 137 menulist.menupopup.hidePopup(); 138 await closePermissionPopup(); 139 140 let uri = Services.io.newURI(AUTOPLAY_PAGE); 141 let state = PermissionTestUtils.getPermissionObject( 142 uri, 143 AUTOPLAY_PERM 144 ).capability; 145 Assert.equal(state, Services.perms.ALLOW_ACTION); 146 }); 147 148 Services.perms.removeAll(); 149 }); 150 151 add_task(async function testGloballyBlockedOnNewWindow() { 152 Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED); 153 154 let principal = 155 Services.scriptSecurityManager.createContentPrincipalFromOrigin( 156 AUTOPLAY_PAGE 157 ); 158 159 let tab = await BrowserTestUtils.openNewForegroundTab( 160 gBrowser, 161 AUTOPLAY_PAGE 162 ); 163 await blockedIconShown(); 164 165 Assert.deepEqual( 166 SitePermissions.getForPrincipal( 167 principal, 168 AUTOPLAY_PERM, 169 tab.linkedBrowser 170 ), 171 { 172 state: SitePermissions.BLOCK, 173 scope: SitePermissions.SCOPE_PERSISTENT, 174 } 175 ); 176 177 let promiseWin = BrowserTestUtils.waitForNewWindow(); 178 gBrowser.replaceTabWithWindow(tab); 179 let win = await promiseWin; 180 tab = win.gBrowser.selectedTab; 181 182 Assert.deepEqual( 183 SitePermissions.getForPrincipal( 184 principal, 185 AUTOPLAY_PERM, 186 tab.linkedBrowser 187 ), 188 { 189 state: SitePermissions.BLOCK, 190 scope: SitePermissions.SCOPE_PERSISTENT, 191 } 192 ); 193 194 SitePermissions.removeFromPrincipal( 195 principal, 196 AUTOPLAY_PERM, 197 tab.linkedBrowser 198 ); 199 await BrowserTestUtils.closeWindow(win); 200 }); 201 202 add_task(async function testBFCache() { 203 Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED); 204 205 await BrowserTestUtils.withNewTab("about:home", async function (browser) { 206 BrowserTestUtils.startLoadingURIString(browser, AUTOPLAY_PAGE); 207 await blockedIconShown(); 208 209 gBrowser.goBack(); 210 await blockedIconHidden(); 211 212 // Not sure why using `gBrowser.goForward()` doesn't trigger document's 213 // visibility changes in some debug build on try server, which makes us not 214 // to receive the blocked event. 215 await SpecialPowers.spawn(browser, [], () => { 216 content.history.forward(); 217 }); 218 await blockedIconShown(); 219 }); 220 221 Services.perms.removeAll(); 222 }); 223 224 add_task(async function testBlockedIconFromCORSIframe() { 225 Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED); 226 227 await BrowserTestUtils.withNewTab(EMPTY_PAGE, async browser => { 228 const blockedIconShownPromise = blockedIconShown(); 229 const CORS_AUTOPLAY_PAGE = AUTOPLAY_PAGE.replace( 230 "example.com", 231 "example.org" 232 ); 233 info(`Load CORS autoplay on an iframe`); 234 await SpecialPowers.spawn(browser, [CORS_AUTOPLAY_PAGE], async url => { 235 const iframe = content.document.createElement("iframe"); 236 iframe.src = url; 237 content.document.body.appendChild(iframe); 238 info("Wait until iframe finishes loading"); 239 await new Promise(r => (iframe.onload = r)); 240 }); 241 await blockedIconShownPromise; 242 ok(true, "Blocked icon shown for the CORS autoplay iframe"); 243 }); 244 245 Services.perms.removeAll(); 246 }); 247 248 add_task(async function testChangingBlockingSettingDuringNavigation() { 249 Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED); 250 251 await BrowserTestUtils.withNewTab("about:home", async function (browser) { 252 await blockedIconHidden(); 253 BrowserTestUtils.startLoadingURIString(browser, AUTOPLAY_PAGE); 254 await blockedIconShown(); 255 Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.ALLOWED); 256 257 gBrowser.goBack(); 258 await blockedIconHidden(); 259 260 gBrowser.goForward(); 261 262 // Sleep here to prevent false positives, the icon gets shown with an 263 // async `GloballyAutoplayBlocked` event. The sleep gives it a little 264 // time for it to show otherwise there is a chance it passes before it 265 // would have shown. 266 await sleep(100); 267 ok( 268 BrowserTestUtils.isHidden(autoplayBlockedIcon()), 269 "Blocked icon is hidden" 270 ); 271 }); 272 273 Services.perms.removeAll(); 274 }); 275 276 add_task(async function testSlowLoadingPage() { 277 Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED); 278 279 let tab1 = await BrowserTestUtils.openNewForegroundTab( 280 gBrowser, 281 "about:home" 282 ); 283 let tab2 = await BrowserTestUtils.openNewForegroundTab( 284 gBrowser, 285 SLOW_AUTOPLAY_PAGE 286 ); 287 await blockedIconShown(); 288 289 await BrowserTestUtils.switchTab(gBrowser, tab1); 290 // Wait until the blocked icon is hidden by switching tabs 291 await blockedIconHidden(); 292 await BrowserTestUtils.switchTab(gBrowser, tab2); 293 await blockedIconShown(); 294 295 BrowserTestUtils.removeTab(tab1); 296 BrowserTestUtils.removeTab(tab2); 297 298 Services.perms.removeAll(); 299 }); 300 301 add_task(async function testBlockedAll() { 302 Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED_ALL); 303 304 await BrowserTestUtils.withNewTab("about:home", async function (browser) { 305 await blockedIconHidden(); 306 BrowserTestUtils.startLoadingURIString(browser, MUTED_AUTOPLAY_PAGE); 307 await blockedIconShown(); 308 309 await openPermissionPopup(); 310 311 Assert.equal( 312 permissionListBlockedIcons().length, 313 1, 314 "Blocked icon is shown" 315 ); 316 317 let menulist = document.getElementById("permission-popup-menulist"); 318 await EventUtils.synthesizeMouseAtCenter(menulist, { type: "mousedown" }); 319 await TestUtils.waitForCondition(() => { 320 return ( 321 menulist.getElementsByTagName("menuitem")[1].label === "Block Audio" 322 ); 323 }); 324 325 let menuitem = menulist.getElementsByTagName("menuitem")[0]; 326 menuitem.click(); 327 menulist.menupopup.hidePopup(); 328 await closePermissionPopup(); 329 gBrowser.reload(); 330 await blockedIconHidden(); 331 }); 332 Services.perms.removeAll(); 333 }); 334 335 add_task(async function testMultiplePlayNotificationsFromJS() { 336 Services.prefs.setIntPref(AUTOPLAY_PREF, Ci.nsIAutoplay.BLOCKED); 337 338 await BrowserTestUtils.withNewTab("about:home", async function (browser) { 339 let count = 0; 340 browser.addEventListener("GloballyAutoplayBlocked", function () { 341 is(++count, 1, "Shouldn't get more than one autoplay blocked event"); 342 }); 343 344 await blockedIconHidden(); 345 346 BrowserTestUtils.startLoadingURIString(browser, AUTOPLAY_JS_PAGE); 347 348 await blockedIconShown(); 349 350 // Sleep here a bit to ensure that multiple events don't arrive. 351 await sleep(100); 352 353 is(count, 1, "Shouldn't have got more events"); 354 }); 355 356 Services.perms.removeAll(); 357 });