Bug 1877416 - handle reentrancy when showing infobars via EncryptedMediaParent.receiveMessage r=reusable-components-reviewers,tgiles

`notificationBox.appendNotification` is now async, so in cases where we were receiving multiple "cdm-not-installed" messages in quick succession it was possible that the notification from the prior call hadn't actully been appended yet. This made it so that calls to `notificationBox.getNotificationWithValue` wouldn't return anything, and we would show the same message multiple times. This patch adds code to track which notification related messages are being handled to avoid re-appending the same notification.

Differential Revision: https://phabricator.services.mozilla.com/D200030
This commit is contained in:
Hanna Jones 2024-02-01 15:27:12 +00:00
Родитель 01243cdf59
Коммит 3fff1b9985
2 изменённых файлов: 64 добавлений и 2 удалений

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

@ -59,7 +59,10 @@ export class EncryptedMediaParent extends JSWindowActorParent {
]);
}
receiveMessage(aMessage) {
async receiveMessage(aMessage) {
if (!this.handledMessages) {
this.handledMessages = new Set();
}
// The top level browsing context's embedding element should be a xul browser element.
let browser = this.browsingContext.top.embedderElement;
@ -76,6 +79,9 @@ export class EncryptedMediaParent extends JSWindowActorParent {
return;
}
let { status, keySystem } = parsedData;
if (this.handledMessages.has(status)) {
return;
}
// First, see if we need to do updates. We don't need to do anything for
// hidden keysystems:
@ -108,6 +114,7 @@ export class EncryptedMediaParent extends JSWindowActorParent {
case "api-disabled":
case "cdm-disabled":
this.handledMessages.add(status);
notificationId = "drmContentDisabled";
buttonCallback = () => {
this.ensureEMEEnabled(browser, keySystem);
@ -119,6 +126,7 @@ export class EncryptedMediaParent extends JSWindowActorParent {
break;
case "cdm-not-installed":
this.handledMessages.add(status);
notificationId = "drmContentCDMInstalling";
notificationMessage = this.getMessageWithBrandName(notificationId);
break;
@ -143,6 +151,7 @@ export class EncryptedMediaParent extends JSWindowActorParent {
let notificationBox = browser.getTabBrowser().getNotificationBox(browser);
if (notificationBox.getNotificationWithValue(notificationId)) {
this.handledMessages.delete(status);
return;
}
@ -162,7 +171,7 @@ export class EncryptedMediaParent extends JSWindowActorParent {
}
let iconURL = "chrome://browser/skin/drm-icon.svg";
notificationBox.appendNotification(
await notificationBox.appendNotification(
notificationId,
{
label: notificationMessage,
@ -171,6 +180,7 @@ export class EncryptedMediaParent extends JSWindowActorParent {
},
buttons
);
this.handledMessages.delete(status);
}
async showPopupNotificationForSuccess(aBrowser) {

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

@ -244,3 +244,55 @@ add_task(async function test_drm_prompt_shows_for_cross_origin_iframe() {
);
});
});
add_task(async function test_drm_prompt_only_shows_one_notification() {
await BrowserTestUtils.withNewTab(TEST_URL, async function (browser) {
// Turn off EME and Widevine CDM.
Services.prefs.setBoolPref("media.eme.enabled", false);
Services.prefs.setBoolPref("media.gmp-widevinecdm.enabled", false);
let notificationShownPromise = BrowserTestUtils.waitForNotificationBar(
gBrowser,
browser,
"drmContentDisabled"
);
// Send three EME requests to ensure only one instance of the
// "Enable DRM" notification appears in the chrome
for (let i = 0; i < 3; i++) {
await SpecialPowers.spawn(browser, [], async function () {
try {
let config = [
{
initDataTypes: ["webm"],
videoCapabilities: [{ contentType: 'video/webm; codecs="vp9"' }],
},
];
await content.navigator.requestMediaKeySystemAccess(
"com.widevine.alpha",
config
);
} catch (ex) {
return { rejected: true };
}
return { rejected: false };
});
}
// Verify the UI prompt showed.
let box = gBrowser.getNotificationBox(browser);
await notificationShownPromise;
let notification = box.currentNotification;
ok(notification, "Notification should be visible");
is(
notification.getAttribute("value"),
"drmContentDisabled",
"Should be showing the right notification"
);
is(
box.allNotifications.length,
1,
"There should only be one notification shown"
);
});
});