Bug 1956490 - Update (add-on) post-install prompt. r=rpl,fluent-reviewers,bolsson

Differential Revision: https://phabricator.services.mozilla.com/D246624
This commit is contained in:
William Durand
2025-05-06 12:42:51 +00:00
committed by wdurand@mozilla.com
parent 8f2bc4a20c
commit 0207bbbb0b
5 changed files with 160 additions and 3 deletions

View File

@@ -437,7 +437,8 @@ customElements.define(
return checkboxEl;
}
}
},
{ extends: "popupnotification" }
);
customElements.define(
@@ -599,7 +600,8 @@ customElements.define(
onDownloadEnded() {
this.updateProgress();
}
}
},
{ extends: "popupnotification" }
);
// This custom element wraps the messagebar shown in the extensions panel
@@ -671,6 +673,80 @@ customElements.define(
}
);
customElements.define(
"addon-installed-notification",
class MozAddonInstalledNotification extends customElements.get(
"popupnotification"
) {
connectedCallback() {
this.descriptionEl = this.querySelector("#addon-install-description");
this.settingsLinkEl = this.querySelector("#addon-install-settings-link");
this.addEventListener("click", this);
}
disconnectedCallback() {
this.removeEventListener("click", this);
}
handleEvent(event) {
const { target } = event;
switch (event.type) {
case "click": {
if (target.id === this.settingsLinkEl.id) {
const { addonId } = this.notification.options.customElementOptions;
BrowserAddonUI.openAddonsMgr(
"addons://detail/" + encodeURIComponent(addonId)
);
}
break;
}
}
}
show() {
super.show();
if (!this.notification) {
return;
}
if (!this.notification.options?.customElementOptions) {
throw new Error(
"Mandatory customElementOptions property missing from notification options"
);
}
this.render();
}
render() {
this.settingsLinkEl.hidden = true;
let fluentId = "appmenu-addon-post-install-message3";
if (this.#dataCollectionPermissionsEnabled) {
MozXULElement.insertFTLIfNeeded(
"locales-preview/dataCollectionPermissions.ftl"
);
this.settingsLinkEl.hidden = false;
fluentId = "appmenu-addon-post-install-message-with-data-collection";
}
this.ownerDocument.l10n.setAttributes(this.descriptionEl, fluentId);
}
get #dataCollectionPermissionsEnabled() {
return Services.prefs.getBoolPref(
"extensions.dataCollectionPermissions.enabled",
false
);
}
},
{ extends: "popupnotification" }
);
// Removes a doorhanger notification if all of the installs it was notifying
// about have ended in some way.
function removeNotificationOnEnd(notification, installs) {

View File

@@ -215,6 +215,7 @@
</popupnotification>
<popupnotification id="appMenu-addon-installed-notification"
is="addon-installed-notification"
popupid="addon-installed"
closebuttonhidden="true"
secondarybuttonhidden="true"
@@ -223,7 +224,9 @@
buttonhighlight="true"
hidden="true">
<popupnotificationcontent class="addon-installed-notification-content" orient="vertical">
<description id="addon-install-description" data-lazy-l10n-id="appmenu-addon-post-install-message3"/>
<description id="addon-install-description">
<html:a id="addon-install-settings-link" data-l10n-name="settings-link"></html:a>
</description>
</popupnotificationcontent>
</popupnotification>

View File

@@ -704,6 +704,9 @@ export var ExtensionsUI = {
lazy.AppMenuNotifications.removeNotification("addon-installed");
resolve();
},
customElementOptions: {
addonId: addon.id,
},
};
lazy.AppMenuNotifications.showNotification(
"addon-installed",

View File

@@ -82,3 +82,6 @@ permissions-data-addon-button = Permissions and data
popup-notification-addon-technicalAndInteraction-checkbox =
.label = Share technical and interaction data with extension developer
.accesskey = S
# This string is used in the confirmation popup displayed after an extension has been installed.
appmenu-addon-post-install-message-with-data-collection = Update permissions and data preferences any time in the <a data-l10n-name="settings-link">extension settings</a>.

View File

@@ -1201,3 +1201,75 @@ add_task(async function testTechnicalAndInteractionData() {
await SpecialPowers.popPrefEnv();
});
add_task(async function testVerifyPostInstallPopupWithDataCollection() {
await SpecialPowers.pushPrefEnv({
set: [["extensions.dataCollectionPermissions.enabled", true]],
});
const extensionId = "@test-id";
const extension = AddonTestUtils.createTempWebExtensionFile({
manifest: {
browser_specific_settings: {
gecko: { id: extensionId },
},
},
});
await BrowserTestUtils.withNewTab(
{ gBrowser, url: "about:robots" },
async () => {
const dialogPromise = promisePopupNotificationShown(
"addon-webext-permissions"
);
gURLBar.value = extension.path;
gURLBar.focus();
EventUtils.synthesizeKey("KEY_Enter");
const popupContentEl = await dialogPromise;
// Install the add-on.
let notificationPromise = waitAppMenuNotificationShown(
"addon-installed",
extensionId
);
popupContentEl.button.click();
let notification = await notificationPromise;
// Verify the post-install popup.
Assert.ok(
notification
.querySelector("#addon-install-description")
.textContent.startsWith(
"Update permissions and data preferences any time"
),
"Expected notification content with data collection"
);
let settingsLink = notification.querySelector(
"#addon-install-description > a"
);
Assert.ok(settingsLink, "Expected a link in the post-install popup");
const tabPromise = BrowserTestUtils.waitForNewTab(
gBrowser,
"about:addons",
true
);
settingsLink.click();
const tab = await tabPromise;
Assert.ok(tab, "Expected tab");
is(
gBrowser.selectedBrowser.contentWindow.gViewController.currentViewId,
`addons://detail/${encodeURIComponent(extensionId)}`,
"Expected about:addons to show the detail view of the extension"
);
BrowserTestUtils.removeTab(tab);
// Dismiss the popup by clicking "OK".
notification.button.click();
const addon = await AddonManager.getAddonByID(extensionId);
Assert.ok(addon, "Expected add-on");
await addon.uninstall();
}
);
await SpecialPowers.popPrefEnv();
});