diff options
Diffstat (limited to 'dom/media/mediacontrol/tests/browser/browser_remove_controllable_media_for_active_controller.js')
-rw-r--r-- | dom/media/mediacontrol/tests/browser/browser_remove_controllable_media_for_active_controller.js | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/dom/media/mediacontrol/tests/browser/browser_remove_controllable_media_for_active_controller.js b/dom/media/mediacontrol/tests/browser/browser_remove_controllable_media_for_active_controller.js new file mode 100644 index 0000000000..a0aa5af4e9 --- /dev/null +++ b/dom/media/mediacontrol/tests/browser/browser_remove_controllable_media_for_active_controller.js @@ -0,0 +1,108 @@ +const PAGE_URL = + "https://example.com/browser/dom/media/mediacontrol/tests/browser/file_non_autoplay.html"; + +const testVideoId = "video"; + +add_task(async function setupTestingPref() { + await SpecialPowers.pushPrefEnv({ + set: [["media.mediacontrol.testingevents.enabled", true]], + }); +}); + +/** + * If an active controller has an active media session, then it can still be + * controlled via media key even if there is no controllable media presents. + * As active media session could still create other controllable media in its + * action handler, it should still receive media key. However, if a controller + * doesn't have an active media session, then it won't be controlled via media + * key when no controllable media presents. + */ +add_task( + async function testControllerWithActiveMediaSessionShouldStillBeActiveWhenNoControllableMediaPresents() { + info(`open media page`); + const tab = await createLoadedTabWrapper(PAGE_URL); + + info(`play media would activate controller and media session`); + await setupMediaSession(tab); + await playMedia(tab, testVideoId); + await checkOrWaitControllerBecomesActive(tab); + + info(`remove playing media so we don't have any controllable media now`); + await Promise.all([ + new Promise(r => (tab.controller.onplaybackstatechange = r)), + removePlayingMedia(tab), + ]); + + info(`despite that, controller should still be active`); + await checkOrWaitControllerBecomesActive(tab); + + info(`active media session can still receive media key`); + await ensureActiveMediaSessionReceivedMediaKey(tab); + + info(`remove tab`); + await tab.close(); + } +); + +add_task( + async function testControllerWithoutActiveMediaSessionShouldBecomeInactiveWhenNoControllableMediaPresents() { + info(`open media page`); + const tab = await createLoadedTabWrapper(PAGE_URL); + + info(`play media would activate controller`); + await playMedia(tab, testVideoId); + await checkOrWaitControllerBecomesActive(tab); + + info( + `remove playing media so we don't have any controllable media, which would deactivate controller` + ); + await Promise.all([ + new Promise(r => (tab.controller.ondeactivated = r)), + removePlayingMedia(tab), + ]); + + info(`remove tab`); + await tab.close(); + } +); + +/** + * The following are helper functions. + */ +function setupMediaSession(tab) { + return SpecialPowers.spawn(tab.linkedBrowser, [], _ => { + // except `play/pause/stop`, set an action handler for arbitrary key in + // order to later verify if the session receives that media key by listening + // to session's `onpositionstatechange`. + content.navigator.mediaSession.setActionHandler("seekforward", _ => { + content.navigator.mediaSession.setPositionState({ + duration: 60, + }); + }); + }); +} + +async function ensureActiveMediaSessionReceivedMediaKey(tab) { + const controller = tab.linkedBrowser.browsingContext.mediaController; + const positionChangePromise = new Promise( + r => (controller.onpositionstatechange = r) + ); + MediaControlService.generateMediaControlKey("seekforward"); + await positionChangePromise; + ok(true, "active media session received media key"); +} + +function removePlayingMedia(tab) { + return SpecialPowers.spawn(tab.linkedBrowser, [testVideoId], Id => { + content.document.getElementById(Id).remove(); + }); +} + +async function checkOrWaitControllerBecomesActive(tab) { + const controller = tab.linkedBrowser.browsingContext.mediaController; + if (!controller.isActive) { + info(`wait until controller gets activated`); + await new Promise(r => (controller.onactivated = r)); + } + ok(controller.isActive, `controller is active`); +} |