Source code

Revision control

Copy as Markdown

Other Tools

Test Info: Warnings

const PAGE_URL =
add_task(async function setupTestingPref() {
await SpecialPowers.pushPrefEnv({
set: [["media.mediacontrol.stopcontrol.aftermediaends", true]],
});
});
/**
* This test is used to ensure that we would stop controlling media after it
* reaches to the end when a controller doesn't have an active media session.
* If a controller has an active media session, it would keep active despite
* media reaches to the end.
*/
add_task(async function testControllerShouldStopAfterMediaReachesToTheEnd() {
info(`open media page and play media until the end`);
const tab = await createLoadedTabWrapper(PAGE_URL);
await Promise.all([
checkIfMediaControllerBecomeInactiveAfterMediaEnds(tab),
playMediaUntilItReachesToTheEnd(tab),
]);
info(`remove tab`);
await tab.close();
});
add_task(async function testControllerWontStopAfterMediaReachesToTheEnd() {
info(`open media page and create media session`);
const tab = await createLoadedTabWrapper(PAGE_URL);
await createMediaSession(tab);
info(`play media until the end`);
await playMediaUntilItReachesToTheEnd(tab);
info(`controller is still active because of having active media session`);
await checkControllerIsActive(tab);
info(`remove tab`);
await tab.close();
});
/**
* The following are helper functions.
*/
function checkIfMediaControllerBecomeInactiveAfterMediaEnds(tab) {
return new Promise(r => {
let activeChangedNums = 0;
const controller = tab.linkedBrowser.browsingContext.mediaController;
controller.onactivated = () => {
is(
++activeChangedNums,
1,
`Receive ${activeChangedNums} times 'onactivechange'`
);
// We activate controller when it becomes playing, which doesn't guarantee
// it's already audible, so we won't check audible state here.
ok(controller.isActive, "controller should be active");
ok(controller.isPlaying, "controller should be playing");
};
controller.ondeactivated = () => {
is(
++activeChangedNums,
2,
`Receive ${activeChangedNums} times 'onactivechange'`
);
ok(!controller.isActive, "controller should be inactive");
ok(!controller.isAudible, "controller should be inaudible");
ok(!controller.isPlaying, "controller should be paused");
r();
};
});
}
function playMediaUntilItReachesToTheEnd(tab) {
return SpecialPowers.spawn(tab.linkedBrowser, [], async () => {
const video = content.document.getElementById("video");
if (!video) {
ok(false, "can't get video");
}
if (video.readyState < video.HAVE_METADATA) {
info(`load media to get its duration`);
video.load();
await new Promise(r => (video.loadedmetadata = r));
}
info(`adjust the start position to faster reach to the end`);
Assert.greater(video.duration, 1.0, "video's duration is larger than 1.0s");
video.currentTime = video.duration - 1.0;
info(`play ${video.id} video`);
video.play();
await new Promise(r => (video.onended = r));
});
}
function createMediaSession(tab) {
return SpecialPowers.spawn(tab.linkedBrowser, [], _ => {
// simply create a media session, which would become the active media session later.
content.navigator.mediaSession;
});
}
function checkControllerIsActive(tab) {
const controller = tab.linkedBrowser.browsingContext.mediaController;
ok(controller.isActive, `controller is active`);
}