Bug 1617033 - part7 : modify tests to allow simulating media keys would always happen after controller's playback changes. r=chunmin

Whenever pressing the media control keys, it would not only change the media playback state, but also change the playback state of the media controller. Therefore, we want to ensure simulating events always happen after media controller changes its playback state.

In addition, for `play/pause` key, it would check controller's playback state to decide if we should file `play` event or `pause` event, so we definitely have to do that only after the controller changes its playback state.

Changing a file to non-autoplay to prevent missing the `main-media-controller-playback-changed` notification, because we can control when to start media and ensure we have already create a listener for that event.

For non-browser test, we have no way to listen to that notification, which could only be observed in the chrome process, so we do a hack to listen `timeupdate` several times to wait and hope the controller has been created and changed its state in the chrome process.

Differential Revision: https://phabricator.services.mozilla.com/D63926

--HG--
extra : moz-landing-system : lando
This commit is contained in:
alwu 2020-03-06 17:51:48 +00:00
Родитель dd40c9b01a
Коммит 7eec59aab2
5 изменённых файлов: 87 добавлений и 22 удалений

Просмотреть файл

@ -190,6 +190,12 @@ void MediaControlService::ControllerManager::ControllerPlaybackStateChanged(
PlaybackState aState) {
MOZ_ASSERT(NS_IsMainThread());
mSource->SetPlaybackState(aState);
if (StaticPrefs::media_mediacontrol_testingevents_enabled()) {
if (nsCOMPtr<nsIObserverService> obs = services::GetObserverService()) {
obs->NotifyObservers(nullptr, "main-media-controller-playback-changed",
nullptr);
}
}
}
void MediaControlService::ControllerManager::ControllerMetadataChanged(

Просмотреть файл

@ -1,7 +1,7 @@
/* eslint-disable no-undef */
const PAGE_AUTOPLAY =
"https://example.com/browser/dom/media/mediacontrol/tests/file_autoplay.html";
const testVideoId = "autoplay";
const PAGE =
"https://example.com/browser/dom/media/mediacontrol/tests/file_non_autoplay.html";
const testVideoId = "video";
/**
* This test is used to generate platform-independent media control keys event
@ -15,39 +15,74 @@ add_task(async function setupTestingPref() {
});
add_task(async function testPlayPauseAndStop() {
info(`open autoplay media`);
const tab = await createTabAndLoad(PAGE_AUTOPLAY);
await checkOrWaitUntilMediaStartedPlaying(tab, testVideoId);
info(`open page and start media`);
const tab = await createTabAndLoad(PAGE);
await playMedia(tab);
info(`pressing 'pause' key`);
ChromeUtils.generateMediaControlKeysTestEvent("pause");
await checkOrWaitUntilMediaStoppedPlaying(tab, testVideoId);
await waitUntilPlaybackStops(tab);
info(`pressing 'play' key`);
ChromeUtils.generateMediaControlKeysTestEvent("play");
await checkOrWaitUntilMediaStartedPlaying(tab, testVideoId);
await waitUntilPlaybackStarts(tab);
info(`pressing 'stop' key`);
ChromeUtils.generateMediaControlKeysTestEvent("stop");
await checkOrWaitUntilMediaStoppedPlaying(tab, testVideoId);
await waitUntilPlaybackStops(tab);
info(`remove tab`);
await BrowserTestUtils.removeTab(tab);
});
add_task(async function testPlayPause() {
info(`open autoplay media`);
const tab = await createTabAndLoad(PAGE_AUTOPLAY);
await checkOrWaitUntilMediaStartedPlaying(tab, testVideoId);
info(`open page and start media`);
const tab = await createTabAndLoad(PAGE);
await playMedia(tab);
info(`pressing 'playPause' key`);
info(`pressing 'playPause' key, media should stop`);
ChromeUtils.generateMediaControlKeysTestEvent("playPause");
await checkOrWaitUntilMediaStoppedPlaying(tab, testVideoId);
await waitUntilPlaybackStops(tab);
info(`pressing 'playPause' key`);
info(`pressing 'playPause' key, media should start`);
ChromeUtils.generateMediaControlKeysTestEvent("playPause");
await checkOrWaitUntilMediaStartedPlaying(tab, testVideoId);
await waitUntilPlaybackStarts(tab);
info(`remove tab`);
await BrowserTestUtils.removeTab(tab);
});
/**
* The following are helper functions.
*/
function waitUntilPlaybackStarts(tab) {
return Promise.all([
checkOrWaitUntilMediaStartedPlaying(tab, testVideoId),
waitUntilMainMediaControllerPlaybackChanged(),
]);
}
function waitUntilPlaybackStops(tab) {
return Promise.all([
checkOrWaitUntilMediaStoppedPlaying(tab, testVideoId),
waitUntilMainMediaControllerPlaybackChanged(),
]);
}
function playMedia(tab) {
const playPromise = SpecialPowers.spawn(
tab.linkedBrowser,
[testVideoId],
Id => {
const video = content.document.getElementById(Id);
if (!video) {
ok(false, `can't get the media element!`);
}
return video.play();
}
);
return Promise.all([
playPromise,
waitUntilMainMediaControllerPlaybackChanged(),
]);
}

Просмотреть файл

@ -48,3 +48,7 @@ function checkOrWaitUntilMediaStoppedPlaying(tab, elementId) {
});
});
}
function waitUntilMainMediaControllerPlaybackChanged() {
return BrowserUtils.promiseObserved("main-media-controller-playback-changed");
}

Просмотреть файл

@ -47,11 +47,21 @@ nextWindowMessage().then(
/**
* The following are helper functions
*/
function startMediaPlayback() {
async function startMediaPlayback() {
info(`wait until media starts playing`);
const video = document.getElementById("testVideo");
video.play();
return new Promise(r => video.onplaying = r);
await video.play();
// As we can't observe `main-media-controller-playback-changed` notification,
// which can only be observed in the chrome process. Therefore, we use a
// workaround instead which is to wait for a while to ensure that the
// controller has already been created in the chrome process.
let timeupdatecount = 0;
await new Promise(r => video.ontimeupdate = () => {
if (++timeupdatecount == 3) {
video.ontimeupdate = null;
r();
}
});
}
function createSessionInMainFrame() {

Просмотреть файл

@ -29,11 +29,21 @@ nextWindowMessage().then(
/**
* The following are helper functions
*/
function startMediaPlayback() {
async function startMediaPlayback() {
info(`wait until media starts playing`);
const video = document.getElementById("testVideo");
video.play();
return new Promise(r => video.onplaying = r);
await video.play();
// As we can't observe `main-media-controller-playback-changed` notification,
// which can only be observed in the chrome process. Therefore, we use a
// workaround instead which is to wait for a while to ensure that the
// controller has already been created in the chrome process.
let timeupdatecount = 0;
await new Promise(r => video.ontimeupdate = () => {
if (++timeupdatecount == 3) {
video.ontimeupdate = null;
r();
}
});
}
async function createSession({shouldCreateFrom, origin}) {